Rename "Backup and restore" settings screen to "Data and storage"
We can house more things in here in the future, like: - A unified storage location setting (with scoped storage) - Sync - Disk usage info
Cette révision appartient à :
Parent
d7d7a6d2fc
révision
c46c39d4ae
8 fichiers modifiés avec 100 ajouts et 117 suppressions
|
@ -16,7 +16,7 @@ import androidx.compose.material.icons.outlined.Info
|
|||
import androidx.compose.material.icons.outlined.Label
|
||||
import androidx.compose.material.icons.outlined.QueryStats
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.SettingsBackupRestore
|
||||
import androidx.compose.material.icons.outlined.Storage
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -45,7 +45,7 @@ fun MoreScreen(
|
|||
onClickDownloadQueue: () -> Unit,
|
||||
onClickCategories: () -> Unit,
|
||||
onClickStats: () -> Unit,
|
||||
onClickBackupAndRestore: () -> Unit,
|
||||
onClickDataAndStorage: () -> Unit,
|
||||
onClickSettings: () -> Unit,
|
||||
onClickAbout: () -> Unit,
|
||||
) {
|
||||
|
@ -141,9 +141,9 @@ fun MoreScreen(
|
|||
}
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.label_backup),
|
||||
icon = Icons.Outlined.SettingsBackupRestore,
|
||||
onPreferenceClick = onClickBackupAndRestore,
|
||||
title = stringResource(R.string.label_data_storage),
|
||||
icon = Icons.Outlined.Storage,
|
||||
onPreferenceClick = onClickDataAndStorage,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ import androidx.compose.material3.TextButton
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
|
@ -31,7 +30,6 @@ import eu.kanade.presentation.more.settings.Preference
|
|||
import eu.kanade.presentation.more.settings.screen.advanced.ClearDatabaseScreen
|
||||
import eu.kanade.presentation.more.settings.screen.debug.DebugInfoScreen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
|
@ -61,7 +59,6 @@ import okhttp3.Headers
|
|||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
@ -183,40 +180,12 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||
|
||||
@Composable
|
||||
private fun getDataGroup(): Preference.PreferenceGroup {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
|
||||
|
||||
val chapterCache = remember { Injekt.get<ChapterCache>() }
|
||||
var readableSizeSema by remember { mutableIntStateOf(0) }
|
||||
val readableSize = remember(readableSizeSema) { chapterCache.readableSize }
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.label_data),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_clear_chapter_cache),
|
||||
subtitle = stringResource(R.string.used_cache, readableSize),
|
||||
onClick = {
|
||||
scope.launchNonCancellable {
|
||||
try {
|
||||
val deletedFiles = chapterCache.clear()
|
||||
withUIContext {
|
||||
context.toast(context.getString(R.string.cache_deleted, deletedFiles))
|
||||
readableSizeSema++
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
withUIContext { context.toast(R.string.cache_delete_error) }
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = libraryPreferences.autoClearChapterCache(),
|
||||
title = stringResource(R.string.pref_auto_clear_chapter_cache),
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_invalidate_download_cache),
|
||||
subtitle = stringResource(R.string.pref_invalidate_download_cache_summary),
|
||||
|
|
|
@ -31,8 +31,6 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.permissions.PermissionRequestHelper
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
@ -41,11 +39,17 @@ 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.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
|
||||
|
@ -54,12 +58,12 @@ import tachiyomi.presentation.core.util.isScrolledToStart
|
|||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsBackupScreen : SearchableSettings {
|
||||
object SettingsDataScreen : SearchableSettings {
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
@StringRes
|
||||
override fun getTitleRes() = R.string.label_backup
|
||||
override fun getTitleRes() = R.string.label_data_storage
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
|
@ -68,9 +72,49 @@ object SettingsBackupScreen : SearchableSettings {
|
|||
PermissionRequestHelper.requestStoragePermission()
|
||||
|
||||
return listOf(
|
||||
getCreateBackupPref(),
|
||||
getRestoreBackupPref(),
|
||||
getAutomaticBackupGroup(backupPreferences = backupPreferences),
|
||||
getBackupAndRestoreGroup(backupPreferences = backupPreferences),
|
||||
getDataGroup(),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getBackupAndRestoreGroup(backupPreferences: BackupPreferences): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val backupIntervalPref = backupPreferences.backupInterval()
|
||||
val backupInterval by backupIntervalPref.collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.label_backup),
|
||||
preferenceItems = listOf(
|
||||
// Manual actions
|
||||
getCreateBackupPref(),
|
||||
getRestoreBackupPref(),
|
||||
|
||||
// Automatic backups
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = backupIntervalPref,
|
||||
title = stringResource(R.string.pref_backup_interval),
|
||||
entries = mapOf(
|
||||
0 to stringResource(R.string.off),
|
||||
6 to stringResource(R.string.update_6hour),
|
||||
12 to stringResource(R.string.update_12hour),
|
||||
24 to stringResource(R.string.update_24hour),
|
||||
48 to stringResource(R.string.update_48hour),
|
||||
168 to stringResource(R.string.update_weekly),
|
||||
),
|
||||
onValueChanged = {
|
||||
BackupCreateJob.setupTask(context, it)
|
||||
true
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = backupPreferences.numberOfBackups(),
|
||||
enabled = backupInterval != 0,
|
||||
title = stringResource(R.string.pref_backup_slots),
|
||||
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
|
||||
),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.backup_info)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -318,70 +362,40 @@ object SettingsBackupScreen : SearchableSettings {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun getAutomaticBackupGroup(
|
||||
backupPreferences: BackupPreferences,
|
||||
): Preference.PreferenceGroup {
|
||||
private fun getDataGroup(): Preference.PreferenceGroup {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val backupIntervalPref = backupPreferences.backupInterval()
|
||||
val backupInterval by backupIntervalPref.collectAsState()
|
||||
val backupDirPref = backupPreferences.backupsDirectory()
|
||||
val backupDir by backupDirPref.collectAsState()
|
||||
val pickBackupLocation = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.OpenDocumentTree(),
|
||||
) { uri ->
|
||||
if (uri != null) {
|
||||
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
|
||||
|
||||
context.contentResolver.takePersistableUriPermission(uri, flags)
|
||||
|
||||
val file = UniFile.fromUri(context, uri)
|
||||
backupDirPref.set(file.uri.toString())
|
||||
}
|
||||
}
|
||||
val chapterCache = remember { Injekt.get<ChapterCache>() }
|
||||
var readableSizeSema by remember { mutableIntStateOf(0) }
|
||||
val readableSize = remember(readableSizeSema) { chapterCache.readableSize }
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.pref_backup_service_category),
|
||||
title = stringResource(R.string.label_data),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = backupIntervalPref,
|
||||
title = stringResource(R.string.pref_backup_interval),
|
||||
entries = mapOf(
|
||||
0 to stringResource(R.string.off),
|
||||
6 to stringResource(R.string.update_6hour),
|
||||
12 to stringResource(R.string.update_12hour),
|
||||
24 to stringResource(R.string.update_24hour),
|
||||
48 to stringResource(R.string.update_48hour),
|
||||
168 to stringResource(R.string.update_weekly),
|
||||
),
|
||||
onValueChanged = {
|
||||
BackupCreateJob.setupTask(context, it)
|
||||
true
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_backup_directory),
|
||||
enabled = backupInterval != 0,
|
||||
subtitle = remember(backupDir) {
|
||||
(UniFile.fromUri(context, backupDir.toUri())?.filePath)?.let {
|
||||
"$it/automatic"
|
||||
}
|
||||
} ?: stringResource(R.string.invalid_location, backupDir),
|
||||
title = stringResource(R.string.pref_clear_chapter_cache),
|
||||
subtitle = stringResource(R.string.used_cache, readableSize),
|
||||
onClick = {
|
||||
try {
|
||||
pickBackupLocation.launch(null)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
context.toast(R.string.file_picker_error)
|
||||
scope.launchNonCancellable {
|
||||
try {
|
||||
val deletedFiles = chapterCache.clear()
|
||||
withUIContext {
|
||||
context.toast(context.getString(R.string.cache_deleted, deletedFiles))
|
||||
readableSizeSema++
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
withUIContext { context.toast(R.string.cache_delete_error) }
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = backupPreferences.numberOfBackups(),
|
||||
enabled = backupInterval != 0,
|
||||
title = stringResource(R.string.pref_backup_slots),
|
||||
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = libraryPreferences.autoClearChapterCache(),
|
||||
title = stringResource(R.string.pref_auto_clear_chapter_cache),
|
||||
),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.backup_info)),
|
||||
),
|
||||
)
|
||||
}
|
|
@ -18,7 +18,7 @@ import androidx.compose.material.icons.outlined.Info
|
|||
import androidx.compose.material.icons.outlined.Palette
|
||||
import androidx.compose.material.icons.outlined.Search
|
||||
import androidx.compose.material.icons.outlined.Security
|
||||
import androidx.compose.material.icons.outlined.SettingsBackupRestore
|
||||
import androidx.compose.material.icons.outlined.Storage
|
||||
import androidx.compose.material.icons.outlined.Sync
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
@ -208,10 +208,10 @@ object SettingsMainScreen : Screen() {
|
|||
screen = SettingsBrowseScreen,
|
||||
),
|
||||
Item(
|
||||
titleRes = R.string.label_backup,
|
||||
titleRes = R.string.label_data_storage,
|
||||
subtitleRes = R.string.pref_backup_summary,
|
||||
icon = Icons.Outlined.SettingsBackupRestore,
|
||||
screen = SettingsBackupScreen,
|
||||
icon = Icons.Outlined.Storage,
|
||||
screen = SettingsDataScreen,
|
||||
),
|
||||
Item(
|
||||
titleRes = R.string.pref_category_security,
|
||||
|
|
|
@ -291,7 +291,7 @@ private val settingScreens = listOf(
|
|||
SettingsDownloadScreen,
|
||||
SettingsTrackingScreen,
|
||||
SettingsBrowseScreen,
|
||||
SettingsBackupScreen,
|
||||
SettingsDataScreen,
|
||||
SettingsSecurityScreen,
|
||||
SettingsAdvancedScreen,
|
||||
)
|
||||
|
|
|
@ -71,7 +71,7 @@ object MoreTab : Tab {
|
|||
onClickDownloadQueue = { navigator.push(DownloadQueueScreen) },
|
||||
onClickCategories = { navigator.push(CategoryScreen()) },
|
||||
onClickStats = { navigator.push(StatsScreen()) },
|
||||
onClickBackupAndRestore = { navigator.push(SettingsScreen.toBackupScreen()) },
|
||||
onClickDataAndStorage = { navigator.push(SettingsScreen.toDataAndStorageScreen()) },
|
||||
onClickSettings = { navigator.push(SettingsScreen.toMainScreen()) },
|
||||
onClickAbout = { navigator.push(SettingsScreen.toAboutScreen()) },
|
||||
)
|
||||
|
|
|
@ -13,7 +13,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator
|
|||
import cafe.adriel.voyager.navigator.Navigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.more.settings.screen.SettingsAppearanceScreen
|
||||
import eu.kanade.presentation.more.settings.screen.SettingsBackupScreen
|
||||
import eu.kanade.presentation.more.settings.screen.SettingsDataScreen
|
||||
import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
|
||||
import eu.kanade.presentation.more.settings.screen.about.AboutScreen
|
||||
import eu.kanade.presentation.util.DefaultNavigatorScreenTransition
|
||||
|
@ -23,7 +23,7 @@ import eu.kanade.presentation.util.isTabletUi
|
|||
import tachiyomi.presentation.core.components.TwoPanelBox
|
||||
|
||||
class SettingsScreen private constructor(
|
||||
val toBackup: Boolean,
|
||||
val toDataAndStorage: Boolean,
|
||||
val toAbout: Boolean,
|
||||
) : Screen() {
|
||||
|
||||
|
@ -32,8 +32,8 @@ class SettingsScreen private constructor(
|
|||
val parentNavigator = LocalNavigator.currentOrThrow
|
||||
if (!isTabletUi()) {
|
||||
Navigator(
|
||||
screen = if (toBackup) {
|
||||
SettingsBackupScreen
|
||||
screen = if (toDataAndStorage) {
|
||||
SettingsDataScreen
|
||||
} else if (toAbout) {
|
||||
AboutScreen
|
||||
} else {
|
||||
|
@ -54,8 +54,8 @@ class SettingsScreen private constructor(
|
|||
)
|
||||
} else {
|
||||
Navigator(
|
||||
screen = if (toBackup) {
|
||||
SettingsBackupScreen
|
||||
screen = if (toDataAndStorage) {
|
||||
SettingsDataScreen
|
||||
} else if (toAbout) {
|
||||
AboutScreen
|
||||
} else {
|
||||
|
@ -79,10 +79,10 @@ class SettingsScreen private constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun toMainScreen() = SettingsScreen(toBackup = false, toAbout = false)
|
||||
fun toMainScreen() = SettingsScreen(toDataAndStorage = false, toAbout = false)
|
||||
|
||||
fun toBackupScreen() = SettingsScreen(toBackup = true, toAbout = false)
|
||||
fun toDataAndStorageScreen() = SettingsScreen(toDataAndStorage = true, toAbout = false)
|
||||
|
||||
fun toAboutScreen() = SettingsScreen(toBackup = false, toAbout = true)
|
||||
fun toAboutScreen() = SettingsScreen(toDataAndStorage = false, toAbout = true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<string name="label_recent_manga">History</string>
|
||||
<string name="label_sources">Sources</string>
|
||||
<string name="label_backup">Backup and restore</string>
|
||||
<string name="label_data_storage">Data and storage</string>
|
||||
<string name="label_stats">Statistics</string>
|
||||
<string name="label_migration">Migrate</string>
|
||||
<string name="label_extensions">Extensions</string>
|
||||
|
@ -181,7 +182,7 @@
|
|||
<string name="pref_downloads_summary">Automatic download, download ahead</string>
|
||||
<string name="pref_tracking_summary">One-way progress sync, enhanced sync</string>
|
||||
<string name="pref_browse_summary">Sources, extensions, global search</string>
|
||||
<string name="pref_backup_summary">Manual & automatic backups</string>
|
||||
<string name="pref_backup_summary">Manual & automatic backups, storage space</string>
|
||||
<string name="pref_security_summary">App lock, secure screen</string>
|
||||
<string name="pref_advanced_summary">Dump crash logs, battery optimizations</string>
|
||||
|
||||
|
@ -467,15 +468,14 @@
|
|||
<!-- Browse section -->
|
||||
<string name="pref_hide_in_library_items">Hide entries already in library</string>
|
||||
|
||||
<!-- Backup section -->
|
||||
<!-- Data and storage section -->
|
||||
<string name="pref_create_backup">Create backup</string>
|
||||
<string name="pref_create_backup_summ">Can be used to restore current library</string>
|
||||
<string name="pref_restore_backup">Restore backup</string>
|
||||
<string name="pref_restore_backup_summ">Restore library from backup file</string>
|
||||
<string name="pref_backup_directory">Backup location</string>
|
||||
<string name="pref_backup_service_category">Automatic backups</string>
|
||||
<string name="pref_backup_interval">Backup frequency</string>
|
||||
<string name="pref_backup_slots">Maximum backups</string>
|
||||
<string name="pref_backup_interval">Automatic backup frequency</string>
|
||||
<string name="pref_backup_slots">Maximum automatic backups</string>
|
||||
<string name="backup_created">Backup created</string>
|
||||
<string name="invalid_backup_file">Invalid backup file</string>
|
||||
<string name="invalid_backup_file_missing_manga">Backup does not contain any library entries.</string>
|
||||
|
@ -509,7 +509,7 @@
|
|||
<string name="library_sync_complete">Library sync complete</string>
|
||||
|
||||
<!-- Advanced section -->
|
||||
<string name="label_network">Network</string>
|
||||
<string name="label_network">Networking</string>
|
||||
<string name="pref_clear_cookies">Clear cookies</string>
|
||||
<string name="pref_dns_over_https">DNS over HTTPS (DoH)</string>
|
||||
<string name="pref_user_agent_string">Default user agent string</string>
|
||||
|
|
Référencer dans un nouveau ticket