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