Просмотр исходного кода

Merge pull request #2143 from 821938089/opt-backup-config

优化备份与恢复
kunfei 4 лет назад
Родитель
Сommit
6b6cbe5817

+ 3 - 2
app/src/main/java/io/legado/app/help/AppWebDav.kt

@@ -18,14 +18,14 @@ import io.legado.app.lib.webdav.WebDav
 import io.legado.app.lib.webdav.WebDavException
 import io.legado.app.lib.webdav.WebDavFile
 import io.legado.app.utils.*
+import kotlinx.coroutines.*
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.Main
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withContext
 import splitties.init.appCtx
 import java.io.File
 import java.text.SimpleDateFormat
 import java.util.*
+import kotlin.coroutines.coroutineContext
 
 /**
  * webDav初始化会访问网络,不要放到主线程
@@ -102,6 +102,7 @@ object AppWebDav {
     suspend fun showRestoreDialog(context: Context) {
         val names = withContext(IO) { getBackupNames() }
         if (names.isNotEmpty()) {
+            coroutineContext.ensureActive()
             withContext(Main) {
                 context.selector(
                     title = context.getString(R.string.select_restore_file),

+ 5 - 0
app/src/main/java/io/legado/app/help/storage/Backup.kt

@@ -14,6 +14,7 @@ import io.legado.app.help.config.ThemeConfig
 import io.legado.app.help.coroutine.Coroutine
 import io.legado.app.utils.*
 import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.ensureActive
 import kotlinx.coroutines.withContext
 import splitties.init.appCtx
 import java.io.File
@@ -75,6 +76,7 @@ object Backup {
             writeListToJson(appDb.bookSourceDao.all, "bookSource.json", backupPath)
             writeListToJson(appDb.rssSourceDao.all, "rssSources.json", backupPath)
             writeListToJson(appDb.rssStarDao.all, "rssStar.json", backupPath)
+            ensureActive()
             writeListToJson(appDb.replaceRuleDao.all, "replaceRule.json", backupPath)
             writeListToJson(appDb.readRecordDao.all, "readRecord.json", backupPath)
             writeListToJson(appDb.searchKeywordDao.all, "searchHistory.json", backupPath)
@@ -82,6 +84,7 @@ object Backup {
             writeListToJson(appDb.txtTocRuleDao.all, "txtTocRule.json", backupPath)
             writeListToJson(appDb.httpTTSDao.all, "httpTTS.json", backupPath)
             writeListToJson(appDb.keyboardAssistsDao.all, "keyboardAssists.json", backupPath)
+            ensureActive()
             GSON.toJson(ReadBookConfig.configList).let {
                 FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.configFileName)
                     .writeText(it)
@@ -98,6 +101,7 @@ object Backup {
                 FileUtils.createFileIfNotExist(backupPath + File.separator + DirectLinkUpload.ruleFileName)
                     .writeText(GSON.toJson(it))
             }
+            ensureActive()
             Preferences.getSharedPreferences(appCtx, backupPath, "config")?.let { sp ->
                 val edit = sp.edit()
                 appCtx.defaultSharedPreferences.all.forEach { (key, value) ->
@@ -113,6 +117,7 @@ object Backup {
                 }
                 edit.commit()
             }
+            ensureActive()
             when {
                 path.isNullOrBlank() -> {
                     copyBackup(context.getExternalFilesDir(null)!!, false)

+ 29 - 1
app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt

@@ -33,9 +33,10 @@ import io.legado.app.lib.prefs.fragment.PreferenceFragment
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.ui.document.HandleFileContract
 import io.legado.app.ui.widget.dialog.TextDialog
+import io.legado.app.ui.widget.dialog.WaitDialog
 import io.legado.app.utils.*
+import kotlinx.coroutines.*
 import kotlinx.coroutines.Dispatchers.Main
-import kotlinx.coroutines.launch
 import splitties.init.appCtx
 import kotlin.collections.set
 
@@ -44,6 +45,9 @@ class BackupConfigFragment : PreferenceFragment(),
     MenuProvider {
 
     private val viewModel by activityViewModels<ConfigViewModel>()
+    private val waitDialog by lazy { WaitDialog(requireContext()) }
+    private var backupJob: Job? = null
+    private var restoreJob: Job? = null
 
     private val selectBackupPath = registerForActivityResult(HandleFileContract()) {
         it.uri?.let { uri ->
@@ -245,7 +249,13 @@ class BackupConfigFragment : PreferenceFragment(),
                 val uri = Uri.parse(backupPath)
                 val doc = DocumentFile.fromTreeUri(requireContext(), uri)
                 if (doc?.canWrite() == true) {
+                    waitDialog.setText("备份中…")
+                    waitDialog.setOnCancelListener {
+                        backupJob?.cancel()
+                    }
+                    waitDialog.show()
                     Coroutine.async {
+                        backupJob = coroutineContext[Job]
                         Backup.backup(requireContext(), backupPath)
                     }.onSuccess {
                         appCtx.toastOnUi(R.string.backup_success)
@@ -257,6 +267,8 @@ class BackupConfigFragment : PreferenceFragment(),
                                 it.localizedMessage
                             )
                         )
+                    }.onFinally(Main) {
+                        waitDialog.dismiss()
                     }
                 } else {
                     backupDir.launch()
@@ -272,7 +284,13 @@ class BackupConfigFragment : PreferenceFragment(),
             .addPermissions(*Permissions.Group.STORAGE)
             .rationale(R.string.tip_perm_request_storage)
             .onGranted {
+                waitDialog.setText("备份中…")
+                waitDialog.setOnCancelListener {
+                    backupJob?.cancel()
+                }
+                waitDialog.show()
                 Coroutine.async {
+                    backupJob = coroutineContext[Job]
                     AppConfig.backupPath = path
                     Backup.backup(requireContext(), path)
                 }.onSuccess {
@@ -280,13 +298,21 @@ class BackupConfigFragment : PreferenceFragment(),
                 }.onError {
                     AppLog.put("备份出错\n${it.localizedMessage}", it)
                     appCtx.toastOnUi(appCtx.getString(R.string.backup_fail, it.localizedMessage))
+                }.onFinally(Main) {
+                    waitDialog.dismiss()
                 }
             }
             .request()
     }
 
     fun restore() {
+        waitDialog.setText(R.string.loading)
+        waitDialog.setOnCancelListener {
+            restoreJob?.cancel()
+        }
+        waitDialog.show()
         Coroutine.async {
+            restoreJob = coroutineContext[Job]
             AppWebDav.showRestoreDialog(requireContext())
         }.onError {
             alert {
@@ -297,6 +323,8 @@ class BackupConfigFragment : PreferenceFragment(),
                 }
                 cancelButton()
             }
+        }.onFinally(Main) {
+            waitDialog.dismiss()
         }
     }