diff --git a/app/src/main/java/io/legado/app/help/AppWebDav.kt b/app/src/main/java/io/legado/app/help/AppWebDav.kt index 5f6748aa6..b78ca1b05 100644 --- a/app/src/main/java/io/legado/app/help/AppWebDav.kt +++ b/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), 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 a5098a740..247b56cd9 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 @@ -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) 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 0d3183813..f8db6ccec 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 @@ -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() + 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() } }