pull/94/head
kunfei 5 years ago
parent c97017e961
commit 952abab4f9
  1. 9
      app/src/main/java/io/legado/app/help/storage/WebDavHelp.kt
  2. 151
      app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt
  3. 173
      app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt
  4. 156
      app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt

@ -10,6 +10,7 @@ import io.legado.app.utils.FileUtils
import io.legado.app.utils.ZipUtils import io.legado.app.utils.ZipUtils
import io.legado.app.utils.getPrefString import io.legado.app.utils.getPrefString
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jetbrains.anko.selector import org.jetbrains.anko.selector
import java.io.File import java.io.File
@ -58,9 +59,11 @@ object WebDavHelp {
suspend fun showRestoreDialog(context: Context, restoreSuccess: () -> Unit): Boolean { suspend fun showRestoreDialog(context: Context, restoreSuccess: () -> Unit): Boolean {
val names = withContext(IO) { getWebDavFileNames() } val names = withContext(IO) { getWebDavFileNames() }
return if (names.isNotEmpty()) { return if (names.isNotEmpty()) {
context.selector(title = "选择恢复文件", items = names) { _, index -> withContext(Main) {
if (index in 0 until names.size) { context.selector(title = "选择恢复文件", items = names) { _, index ->
restoreWebDav(names[index], restoreSuccess) if (index in 0 until names.size) {
restoreWebDav(names[index], restoreSuccess)
}
} }
} }
true true

@ -15,19 +15,19 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.help.AppConfig
import io.legado.app.help.IntentHelp import io.legado.app.help.IntentHelp
import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.Permissions
import io.legado.app.help.permission.PermissionsCompat import io.legado.app.help.permission.PermissionsCompat
import io.legado.app.help.storage.Backup
import io.legado.app.help.storage.Restore 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.alert
import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.yesButton import io.legado.app.lib.dialogs.yesButton
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
import io.legado.app.utils.* 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.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
@ -38,8 +38,6 @@ class BackupConfigFragment : PreferenceFragmentCompat(),
CoroutineScope { CoroutineScope {
private lateinit var job: Job private lateinit var job: Job
private val oldDataRequestCode = 11 private val oldDataRequestCode = 11
private val backupSelectRequestCode = 22
private val restoreSelectRequestCode = 33
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main get() = job + Dispatchers.Main
@ -137,122 +135,14 @@ class BackupConfigFragment : PreferenceFragmentCompat(),
override fun onPreferenceTreeClick(preference: Preference?): Boolean { override fun onPreferenceTreeClick(preference: Preference?): Boolean {
when (preference?.key) { when (preference?.key) {
PreferKey.backupPath -> selectBackupFolder() PreferKey.backupPath -> BackupRestoreUi.selectBackupFolder(this)
"web_dav_backup" -> backup() "web_dav_backup" -> BackupRestoreUi.backup(this)
"web_dav_restore" -> restore() "web_dav_restore" -> BackupRestoreUi.restore(this)
"import_old" -> importOldData() "import_old" -> importOldData()
} }
return super.onPreferenceTreeClick(preference) return super.onPreferenceTreeClick(preference)
} }
private fun backup() {
val backupPath = AppConfig.backupPath
if (backupPath.isNullOrEmpty()) {
selectBackupFolder()
} else {
if (backupPath.isContentPath()) {
val uri = Uri.parse(backupPath)
val doc = DocumentFile.fromTreeUri(requireContext(), uri)
if (doc?.canWrite() == true) {
launch {
Backup.backup(requireContext(), backupPath)
toast(R.string.backup_success)
}
} else {
selectBackupFolder()
}
} else {
backupUsePermission()
}
}
}
private fun backupUsePermission(path: String = Backup.legadoPath) {
PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
launch {
Backup.backup(requireContext(), path)
toast(R.string.backup_success)
}
}
.request()
}
private fun selectBackupFolder() {
alert {
titleResource = R.string.select_folder
items(arrayListOf("默认路径", "系统文件夹选择器", "自带文件夹选择器")) { _, index ->
when (index) {
0 -> PermissionsCompat.Builder(this@BackupConfigFragment)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
launch {
AppConfig.backupPath = Backup.legadoPath
}
}
.request()
1 -> {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(intent, backupSelectRequestCode)
} catch (e: java.lang.Exception) {
e.printStackTrace()
toast(e.localizedMessage ?: "ERROR")
}
}
2 -> {
}
}
}
}.show()
}
fun restore() {
launch {
if (!WebDavHelp.showRestoreDialog(requireContext()) {
toast(R.string.restore_success)
}) {
val backupPath = getPrefString(PreferKey.backupPath)
if (backupPath?.isNotEmpty() == true) {
val uri = Uri.parse(backupPath)
val doc = DocumentFile.fromTreeUri(requireContext(), uri)
if (doc?.canWrite() == true) {
Restore.restore(requireContext(), uri)
toast(R.string.restore_success)
} else {
selectBackupFolder()
}
} else {
selectRestoreFolder()
}
}
}
}
private fun selectRestoreFolder() {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(intent, restoreSelectRequestCode)
} catch (e: java.lang.Exception) {
PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
launch {
Restore.restore(Backup.legadoPath)
toast(R.string.restore_success)
}
}
.request()
}
}
private fun importOldData() { private fun importOldData() {
try { try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
@ -351,37 +241,12 @@ class BackupConfigFragment : PreferenceFragmentCompat(),
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
BackupRestoreUi.onActivityResult(requestCode, resultCode, data)
when (requestCode) { when (requestCode) {
oldDataRequestCode -> oldDataRequestCode ->
if (resultCode == RESULT_OK) data?.data?.let { uri -> if (resultCode == RESULT_OK) data?.data?.let { uri ->
importOldData(uri) importOldData(uri)
} }
backupSelectRequestCode -> if (resultCode == RESULT_OK) {
data?.data?.let { uri ->
requireContext().contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
AppConfig.backupPath = uri.toString()
launch {
Backup.backup(requireContext(), uri.toString())
toast(R.string.backup_success)
}
}
}
restoreSelectRequestCode -> if (resultCode == RESULT_OK) {
data?.data?.let { uri ->
requireContext().contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
AppConfig.backupPath = uri.toString()
launch {
Restore.restore(requireContext(), uri)
toast(R.string.restore_success)
}
}
}
} }
} }
} }

@ -0,0 +1,173 @@
package io.legado.app.ui.config
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import io.legado.app.App
import io.legado.app.R
import io.legado.app.constant.PreferKey
import io.legado.app.help.AppConfig
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.Restore
import io.legado.app.help.storage.WebDavHelp
import io.legado.app.lib.dialogs.alert
import io.legado.app.utils.getPrefString
import io.legado.app.utils.isContentPath
import io.legado.app.utils.toast
import kotlinx.coroutines.Dispatchers.Main
import org.jetbrains.anko.toast
object BackupRestoreUi {
private const val backupSelectRequestCode = 22
private const val restoreSelectRequestCode = 33
fun backup(fragment: Fragment) {
val backupPath = AppConfig.backupPath
if (backupPath.isNullOrEmpty()) {
selectBackupFolder(fragment)
} else {
if (backupPath.isContentPath()) {
val uri = Uri.parse(backupPath)
val doc = DocumentFile.fromTreeUri(fragment.requireContext(), uri)
if (doc?.canWrite() == true) {
Coroutine.async {
Backup.backup(fragment.requireContext(), backupPath)
}.onSuccess {
fragment.toast(R.string.backup_success)
}
} else {
selectBackupFolder(fragment)
}
} else {
backupUsePermission(fragment)
}
}
}
private fun backupUsePermission(fragment: Fragment, path: String = Backup.legadoPath) {
PermissionsCompat.Builder(fragment)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
Coroutine.async {
Backup.backup(fragment.requireContext(), path)
}.onSuccess {
fragment.toast(R.string.backup_success)
}
}
.request()
}
fun selectBackupFolder(fragment: Fragment) {
fragment.alert {
titleResource = R.string.select_folder
items(arrayListOf("默认路径", "系统文件夹选择器", "自带文件夹选择器")) { _, index ->
when (index) {
0 -> PermissionsCompat.Builder(fragment)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
AppConfig.backupPath = Backup.legadoPath
backupUsePermission(fragment)
}
.request()
1 -> {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
fragment.startActivityForResult(intent, backupSelectRequestCode)
} catch (e: java.lang.Exception) {
e.printStackTrace()
fragment.toast(e.localizedMessage ?: "ERROR")
}
}
2 -> {
}
}
}
}.show()
}
fun restore(fragment: Fragment) {
Coroutine.async(context = Main) {
if (!WebDavHelp.showRestoreDialog(fragment.requireContext()) {
fragment.toast(R.string.restore_success)
}) {
val backupPath = fragment.getPrefString(PreferKey.backupPath)
if (backupPath?.isNotEmpty() == true) {
val uri = Uri.parse(backupPath)
val doc = DocumentFile.fromTreeUri(fragment.requireContext(), uri)
if (doc?.canWrite() == true) {
Restore.restore(fragment.requireContext(), uri)
fragment.toast(R.string.restore_success)
} else {
selectRestoreFolder(fragment)
}
} else {
selectRestoreFolder(fragment)
}
}
}
}
private fun selectRestoreFolder(fragment: Fragment) {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
fragment.startActivityForResult(intent, restoreSelectRequestCode)
} catch (e: java.lang.Exception) {
PermissionsCompat.Builder(fragment)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
Coroutine.async {
Restore.restore(Backup.legadoPath)
}.onSuccess {
fragment.toast(R.string.restore_success)
}
}
.request()
}
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
backupSelectRequestCode -> if (resultCode == RESULT_OK) {
data?.data?.let { uri ->
App.INSTANCE.contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
AppConfig.backupPath = uri.toString()
Coroutine.async {
Backup.backup(App.INSTANCE, uri.toString())
}.onSuccess {
App.INSTANCE.toast(R.string.backup_success)
}
}
}
restoreSelectRequestCode -> if (resultCode == RESULT_OK) {
data?.data?.let { uri ->
App.INSTANCE.contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
AppConfig.backupPath = uri.toString()
Coroutine.async {
Restore.restore(App.INSTANCE, uri)
}.onSuccess {
App.INSTANCE.toast(R.string.restore_success)
}
}
}
}
}
}

@ -1,14 +1,11 @@
package io.legado.app.ui.main.my package io.legado.app.ui.main.my
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.documentfile.provider.DocumentFile
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import io.legado.app.App import io.legado.app.App
@ -16,31 +13,22 @@ import io.legado.app.R
import io.legado.app.base.BaseFragment import io.legado.app.base.BaseFragment
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
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.Restore
import io.legado.app.help.storage.WebDavHelp
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.prefs.ATESwitchPreference import io.legado.app.lib.theme.prefs.ATESwitchPreference
import io.legado.app.service.WebService import io.legado.app.service.WebService
import io.legado.app.ui.about.AboutActivity import io.legado.app.ui.about.AboutActivity
import io.legado.app.ui.about.DonateActivity import io.legado.app.ui.about.DonateActivity
import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.book.source.manage.BookSourceActivity
import io.legado.app.ui.config.BackupRestoreUi
import io.legado.app.ui.config.ConfigActivity import io.legado.app.ui.config.ConfigActivity
import io.legado.app.ui.config.ConfigViewModel import io.legado.app.ui.config.ConfigViewModel
import io.legado.app.ui.replacerule.ReplaceRuleActivity import io.legado.app.ui.replacerule.ReplaceRuleActivity
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.view_title_bar.* import kotlinx.android.synthetic.main.view_title_bar.*
import kotlinx.coroutines.launch
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
class MyFragment : BaseFragment(R.layout.fragment_my_config) { class MyFragment : BaseFragment(R.layout.fragment_my_config) {
private val backupSelectRequestCode = 22
private val restoreSelectRequestCode = 33
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setSupportToolbar(toolbar) setSupportToolbar(toolbar)
@ -58,150 +46,14 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config) {
override fun onCompatOptionsItemSelected(item: MenuItem) { override fun onCompatOptionsItemSelected(item: MenuItem) {
when (item.itemId) { when (item.itemId) {
R.id.menu_help -> startActivity<AboutActivity>() R.id.menu_help -> startActivity<AboutActivity>()
R.id.menu_backup -> backup() R.id.menu_backup -> BackupRestoreUi.backup(this)
R.id.menu_restore -> restore() R.id.menu_restore -> BackupRestoreUi.restore(this)
}
}
private fun backup() {
val backupPath = AppConfig.backupPath
if (backupPath.isNullOrEmpty()) {
selectBackupFolder()
} else {
if (backupPath.isContentPath()) {
val uri = Uri.parse(backupPath)
val doc = DocumentFile.fromTreeUri(requireContext(), uri)
if (doc?.canWrite() == true) {
launch {
Backup.backup(requireContext(), backupPath)
toast(R.string.backup_success)
}
} else {
selectBackupFolder()
}
} else {
backupUsePermission()
}
}
}
private fun backupUsePermission(path: String = Backup.legadoPath) {
PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
launch {
Backup.backup(requireContext(), path)
toast(R.string.backup_success)
}
}
.request()
}
private fun selectBackupFolder() {
alert {
titleResource = R.string.select_folder
items(arrayListOf("默认路径", "系统文件夹选择器", "自带文件夹选择器")) { _, index ->
when (index) {
0 -> PermissionsCompat.Builder(this@MyFragment)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
launch {
AppConfig.backupPath = Backup.legadoPath
backupUsePermission()
}
}
.request()
1 -> {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(intent, backupSelectRequestCode)
} catch (e: java.lang.Exception) {
e.printStackTrace()
toast(e.localizedMessage ?: "ERROR")
}
}
2 -> {
}
}
}
}.show()
}
fun restore() {
launch {
if (!WebDavHelp.showRestoreDialog(requireContext()) {
toast(R.string.restore_success)
}) {
val backupPath = getPrefString(PreferKey.backupPath)
if (backupPath?.isNotEmpty() == true) {
val uri = Uri.parse(backupPath)
val doc = DocumentFile.fromTreeUri(requireContext(), uri)
if (doc?.canWrite() == true) {
Restore.restore(requireContext(), uri)
toast(R.string.restore_success)
} else {
selectBackupFolder()
}
} else {
selectRestoreFolder()
}
}
}
}
private fun selectRestoreFolder() {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(intent, restoreSelectRequestCode)
} catch (e: java.lang.Exception) {
PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
launch {
Restore.restore(Backup.legadoPath)
toast(R.string.restore_success)
}
}
.request()
} }
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
when (requestCode) { BackupRestoreUi.onActivityResult(requestCode, resultCode, data)
backupSelectRequestCode -> if (resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
requireContext().contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
AppConfig.backupPath = uri.toString()
launch {
Backup.backup(requireContext(), uri.toString())
toast(R.string.backup_success)
}
}
}
restoreSelectRequestCode -> if (resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
requireContext().contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
AppConfig.backupPath = uri.toString()
launch {
Restore.restore(requireContext(), uri)
toast(R.string.restore_success)
}
}
}
}
} }
class PreferenceFragment : PreferenceFragmentCompat(), class PreferenceFragment : PreferenceFragmentCompat(),

Loading…
Cancel
Save