|
@@ -1,6 +1,5 @@
|
|
|
package eu.kanade.presentation.more.settings.screen
|
|
|
|
|
|
-import android.content.ActivityNotFoundException
|
|
|
import android.content.Context
|
|
|
import android.content.Intent
|
|
|
import android.net.Uri
|
|
@@ -13,11 +12,9 @@ import androidx.annotation.StringRes
|
|
|
import androidx.compose.foundation.layout.Box
|
|
|
import androidx.compose.foundation.layout.Column
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
-import androidx.compose.foundation.lazy.rememberLazyListState
|
|
|
import androidx.compose.foundation.rememberScrollState
|
|
|
import androidx.compose.foundation.verticalScroll
|
|
|
import androidx.compose.material3.AlertDialog
|
|
|
-import androidx.compose.material3.HorizontalDivider
|
|
|
import androidx.compose.material3.Text
|
|
|
import androidx.compose.material3.TextButton
|
|
|
import androidx.compose.runtime.Composable
|
|
@@ -27,41 +24,34 @@ import androidx.compose.runtime.mutableIntStateOf
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
import androidx.compose.runtime.remember
|
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
|
|
-import androidx.compose.runtime.saveable.rememberSaveable
|
|
|
import androidx.compose.runtime.setValue
|
|
|
-import androidx.compose.runtime.toMutableStateList
|
|
|
-import androidx.compose.ui.Alignment
|
|
|
import androidx.compose.ui.Modifier
|
|
|
import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
+import cafe.adriel.voyager.navigator.LocalNavigator
|
|
|
+import cafe.adriel.voyager.navigator.currentOrThrow
|
|
|
import eu.kanade.presentation.more.settings.Preference
|
|
|
+import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
|
|
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
|
|
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
|
|
import eu.kanade.presentation.permissions.PermissionRequestHelper
|
|
|
import eu.kanade.presentation.util.relativeTimeSpanString
|
|
|
import eu.kanade.tachiyomi.R
|
|
|
-import eu.kanade.tachiyomi.data.backup.BackupConst
|
|
|
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
|
|
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
|
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
|
|
-import eu.kanade.tachiyomi.data.backup.models.Backup
|
|
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
|
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
|
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
|
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
|
|
import eu.kanade.tachiyomi.util.system.toast
|
|
|
-import kotlinx.coroutines.launch
|
|
|
import logcat.LogPriority
|
|
|
import tachiyomi.core.util.lang.launchNonCancellable
|
|
|
import tachiyomi.core.util.lang.withUIContext
|
|
|
import tachiyomi.core.util.system.logcat
|
|
|
import tachiyomi.domain.backup.service.BackupPreferences
|
|
|
import tachiyomi.domain.library.service.LibraryPreferences
|
|
|
-import tachiyomi.presentation.core.components.LabeledCheckbox
|
|
|
-import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
|
|
import tachiyomi.presentation.core.util.collectAsState
|
|
|
-import tachiyomi.presentation.core.util.isScrolledToEnd
|
|
|
-import tachiyomi.presentation.core.util.isScrolledToStart
|
|
|
import uy.kohesive.injekt.Injekt
|
|
|
import uy.kohesive.injekt.api.get
|
|
|
|
|
@@ -131,124 +121,11 @@ object SettingsDataScreen : SearchableSettings {
|
|
|
|
|
|
@Composable
|
|
|
private fun getCreateBackupPref(): Preference.PreferenceItem.TextPreference {
|
|
|
- val scope = rememberCoroutineScope()
|
|
|
- val context = LocalContext.current
|
|
|
-
|
|
|
- var flag by rememberSaveable { mutableIntStateOf(0) }
|
|
|
- val chooseBackupDir = rememberLauncherForActivityResult(
|
|
|
- contract = ActivityResultContracts.CreateDocument("application/*"),
|
|
|
- ) {
|
|
|
- if (it != null) {
|
|
|
- context.contentResolver.takePersistableUriPermission(
|
|
|
- it,
|
|
|
- Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
|
|
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
|
|
|
- )
|
|
|
- BackupCreateJob.startNow(context, it, flag)
|
|
|
- }
|
|
|
- flag = 0
|
|
|
- }
|
|
|
- var showCreateDialog by rememberSaveable { mutableStateOf(false) }
|
|
|
- if (showCreateDialog) {
|
|
|
- CreateBackupDialog(
|
|
|
- onConfirm = {
|
|
|
- showCreateDialog = false
|
|
|
- flag = it
|
|
|
- try {
|
|
|
- chooseBackupDir.launch(Backup.getFilename())
|
|
|
- } catch (e: ActivityNotFoundException) {
|
|
|
- flag = 0
|
|
|
- context.toast(R.string.file_picker_error)
|
|
|
- }
|
|
|
- },
|
|
|
- onDismissRequest = { showCreateDialog = false },
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
+ val navigator = LocalNavigator.currentOrThrow
|
|
|
return Preference.PreferenceItem.TextPreference(
|
|
|
title = stringResource(R.string.pref_create_backup),
|
|
|
subtitle = stringResource(R.string.pref_create_backup_summ),
|
|
|
- onClick = {
|
|
|
- scope.launch {
|
|
|
- if (!BackupCreateJob.isManualJobRunning(context)) {
|
|
|
- if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
|
|
|
- context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG)
|
|
|
- }
|
|
|
- showCreateDialog = true
|
|
|
- } else {
|
|
|
- context.toast(R.string.backup_in_progress)
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- @Composable
|
|
|
- private fun CreateBackupDialog(
|
|
|
- onConfirm: (flag: Int) -> Unit,
|
|
|
- onDismissRequest: () -> Unit,
|
|
|
- ) {
|
|
|
- val choices = remember {
|
|
|
- mapOf(
|
|
|
- BackupConst.BACKUP_CATEGORY to R.string.categories,
|
|
|
- BackupConst.BACKUP_CHAPTER to R.string.chapters,
|
|
|
- BackupConst.BACKUP_TRACK to R.string.track,
|
|
|
- BackupConst.BACKUP_HISTORY to R.string.history,
|
|
|
- BackupConst.BACKUP_APP_PREFS to R.string.app_settings,
|
|
|
- BackupConst.BACKUP_SOURCE_PREFS to R.string.source_settings,
|
|
|
- )
|
|
|
- }
|
|
|
- val flags = remember { choices.keys.toMutableStateList() }
|
|
|
- AlertDialog(
|
|
|
- onDismissRequest = onDismissRequest,
|
|
|
- title = { Text(text = stringResource(R.string.backup_choice)) },
|
|
|
- text = {
|
|
|
- Box {
|
|
|
- val state = rememberLazyListState()
|
|
|
- ScrollbarLazyColumn(state = state) {
|
|
|
- item {
|
|
|
- LabeledCheckbox(
|
|
|
- label = stringResource(R.string.manga),
|
|
|
- checked = true,
|
|
|
- onCheckedChange = {},
|
|
|
- )
|
|
|
- }
|
|
|
- choices.forEach { (k, v) ->
|
|
|
- item {
|
|
|
- val isSelected = flags.contains(k)
|
|
|
- LabeledCheckbox(
|
|
|
- label = stringResource(v),
|
|
|
- checked = isSelected,
|
|
|
- onCheckedChange = {
|
|
|
- if (it) {
|
|
|
- flags.add(k)
|
|
|
- } else {
|
|
|
- flags.remove(k)
|
|
|
- }
|
|
|
- },
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!state.isScrolledToStart()) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
|
|
|
- if (!state.isScrolledToEnd()) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
|
|
|
- }
|
|
|
- },
|
|
|
- dismissButton = {
|
|
|
- TextButton(onClick = onDismissRequest) {
|
|
|
- Text(text = stringResource(R.string.action_cancel))
|
|
|
- }
|
|
|
- },
|
|
|
- confirmButton = {
|
|
|
- TextButton(
|
|
|
- onClick = {
|
|
|
- val flag = flags.fold(initial = 0, operation = { a, b -> a or b })
|
|
|
- onConfirm(flag)
|
|
|
- },
|
|
|
- ) {
|
|
|
- Text(text = stringResource(R.string.action_ok))
|
|
|
- }
|
|
|
- },
|
|
|
+ onClick = { navigator.push(CreateBackupScreen()) },
|
|
|
)
|
|
|
}
|
|
|
|
|
@@ -336,7 +213,7 @@ object SettingsDataScreen : SearchableSettings {
|
|
|
},
|
|
|
) {
|
|
|
if (it == null) {
|
|
|
- error = InvalidRestore(message = context.getString(R.string.file_null_uri_error))
|
|
|
+ context.toast(R.string.file_null_uri_error)
|
|
|
return@rememberLauncherForActivityResult
|
|
|
}
|
|
|
|