Clean up storage usage info

- Show bar representation of used/total space
- Handle all mounted storages
- Also included a bunch of unrelated immutables changes, sorry

(cherry picked from commit f31bc47757b3792f92c2c8721739b5e2d91b825d)

# Conflicts:
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt
This commit is contained in:
arkon 2023-12-25 18:11:22 -05:00 committed by Jobobby04
parent 25ab1ed7b8
commit 0c8268fe7b
23 changed files with 360 additions and 180 deletions

View File

@ -29,6 +29,7 @@ import dev.icerock.moko.resources.StringResource
import eu.kanade.core.preference.asToggleableState import eu.kanade.core.preference.asToggleableState
import eu.kanade.presentation.category.visualName import eu.kanade.presentation.category.visualName
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import tachiyomi.core.preference.CheckboxState import tachiyomi.core.preference.CheckboxState
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category

View File

@ -4,6 +4,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.core.preference.Preference as PreferenceData import tachiyomi.core.preference.Preference as PreferenceData
@ -67,20 +69,20 @@ sealed class Preference {
val pref: PreferenceData<T>, val pref: PreferenceData<T>,
override val title: String, override val title: String,
override val subtitle: String? = "%s", override val subtitle: String? = "%s",
val subtitleProvider: @Composable (value: T, entries: Map<T, String>) -> String? = val subtitleProvider: @Composable (value: T, entries: ImmutableMap<T, String>) -> String? =
{ v, e -> subtitle?.format(e[v]) }, { v, e -> subtitle?.format(e[v]) },
override val icon: ImageVector? = null, override val icon: ImageVector? = null,
override val enabled: Boolean = true, override val enabled: Boolean = true,
override val onValueChanged: suspend (newValue: T) -> Boolean = { true }, override val onValueChanged: suspend (newValue: T) -> Boolean = { true },
val entries: Map<T, String>, val entries: ImmutableMap<T, String>,
) : PreferenceItem<T>() { ) : PreferenceItem<T>() {
internal fun internalSet(newValue: Any) = pref.set(newValue as T) internal fun internalSet(newValue: Any) = pref.set(newValue as T)
internal suspend fun internalOnValueChanged(newValue: Any) = onValueChanged(newValue as T) internal suspend fun internalOnValueChanged(newValue: Any) = onValueChanged(newValue as T)
@Composable @Composable
internal fun internalSubtitleProvider(value: Any?, entries: Map<out Any?, String>) = internal fun internalSubtitleProvider(value: Any?, entries: ImmutableMap<out Any?, String>) =
subtitleProvider(value as T, entries as Map<T, String>) subtitleProvider(value as T, entries as ImmutableMap<T, String>)
} }
/** /**
@ -90,13 +92,13 @@ sealed class Preference {
val value: String, val value: String,
override val title: String, override val title: String,
override val subtitle: String? = "%s", override val subtitle: String? = "%s",
val subtitleProvider: @Composable (value: String, entries: Map<String, String>) -> String? = val subtitleProvider: @Composable (value: String, entries: ImmutableMap<String, String>) -> String? =
{ v, e -> subtitle?.format(e[v]) }, { v, e -> subtitle?.format(e[v]) },
override val icon: ImageVector? = null, override val icon: ImageVector? = null,
override val enabled: Boolean = true, override val enabled: Boolean = true,
override val onValueChanged: suspend (newValue: String) -> Boolean = { true }, override val onValueChanged: suspend (newValue: String) -> Boolean = { true },
val entries: Map<String, String>, val entries: ImmutableMap<String, String>,
) : PreferenceItem<String>() ) : PreferenceItem<String>()
/** /**
@ -107,7 +109,10 @@ sealed class Preference {
val pref: PreferenceData<Set<String>>, val pref: PreferenceData<Set<String>>,
override val title: String, override val title: String,
override val subtitle: String? = "%s", override val subtitle: String? = "%s",
val subtitleProvider: @Composable (value: Set<String>, entries: Map<String, String>) -> String? = { v, e -> val subtitleProvider: @Composable (
value: Set<String>,
entries: ImmutableMap<String, String>,
) -> String? = { v, e ->
val combined = remember(v) { val combined = remember(v) {
v.map { e[it] } v.map { e[it] }
.takeIf { it.isNotEmpty() } .takeIf { it.isNotEmpty() }
@ -119,7 +124,7 @@ sealed class Preference {
override val enabled: Boolean = true, override val enabled: Boolean = true,
override val onValueChanged: suspend (newValue: Set<String>) -> Boolean = { true }, override val onValueChanged: suspend (newValue: Set<String>) -> Boolean = { true },
val entries: Map<String, String>, val entries: ImmutableMap<String, String>,
) : PreferenceItem<Set<String>>() ) : PreferenceItem<Set<String>>()
/** /**
@ -173,6 +178,6 @@ sealed class Preference {
override val title: String, override val title: String,
override val enabled: Boolean = true, override val enabled: Boolean = true,
val preferenceItems: List<PreferenceItem<out Any>>, val preferenceItems: ImmutableList<PreferenceItem<out Any>>,
) : Preference() ) : Preference()
} }

View File

@ -68,6 +68,9 @@ import exh.source.BlacklistedSources
import exh.source.EH_SOURCE_ID import exh.source.EH_SOURCE_ID
import exh.source.EXH_SOURCE_ID import exh.source.EXH_SOURCE_ID
import exh.util.toAnnotatedString import exh.util.toAnnotatedString
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
@ -180,7 +183,7 @@ object SettingsAdvancedScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_background_activity), title = stringResource(MR.strings.label_background_activity),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_disable_battery_optimization), title = stringResource(MR.strings.pref_disable_battery_optimization),
subtitle = stringResource(MR.strings.pref_disable_battery_optimization_summary), subtitle = stringResource(MR.strings.pref_disable_battery_optimization_summary),
@ -219,7 +222,7 @@ object SettingsAdvancedScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_data), title = stringResource(MR.strings.label_data),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_invalidate_download_cache), title = stringResource(MR.strings.pref_invalidate_download_cache),
subtitle = stringResource(MR.strings.pref_invalidate_download_cache_summary), subtitle = stringResource(MR.strings.pref_invalidate_download_cache_summary),
@ -249,7 +252,7 @@ object SettingsAdvancedScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_network), title = stringResource(MR.strings.label_network),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_clear_cookies), title = stringResource(MR.strings.pref_clear_cookies),
onClick = { onClick = {
@ -282,7 +285,7 @@ object SettingsAdvancedScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = networkPreferences.dohProvider(), pref = networkPreferences.dohProvider(),
title = stringResource(MR.strings.pref_dns_over_https), title = stringResource(MR.strings.pref_dns_over_https),
entries = mapOf( entries = persistentMapOf(
-1 to stringResource(MR.strings.disabled), -1 to stringResource(MR.strings.disabled),
PREF_DOH_CLOUDFLARE to "Cloudflare", PREF_DOH_CLOUDFLARE to "Cloudflare",
PREF_DOH_GOOGLE to "Google", PREF_DOH_GOOGLE to "Google",
@ -335,7 +338,7 @@ object SettingsAdvancedScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_library), title = stringResource(MR.strings.label_library),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_refresh_library_covers), title = stringResource(MR.strings.pref_refresh_library_covers),
onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.COVERS) }, onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.COVERS) },
@ -395,12 +398,13 @@ object SettingsAdvancedScreen : SearchableSettings {
} }
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_extensions), title = stringResource(MR.strings.label_extensions),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = extensionInstallerPref, pref = extensionInstallerPref,
title = stringResource(MR.strings.ext_installer_pref), title = stringResource(MR.strings.ext_installer_pref),
entries = extensionInstallerPref.entries entries = extensionInstallerPref.entries
.associateWith { stringResource(it.titleRes) }, .associateWith { stringResource(it.titleRes) }
.toImmutableMap(),
onValueChanged = { onValueChanged = {
if (it == BasePreferences.ExtensionInstaller.SHIZUKU && if (it == BasePreferences.ExtensionInstaller.SHIZUKU &&
!context.isShizukuInstalled !context.isShizukuInstalled
@ -537,7 +541,7 @@ object SettingsAdvancedScreen : SearchableSettings {
} }
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.download_notifier_downloader_title), title = stringResource(MR.strings.download_notifier_downloader_title),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(SYMR.strings.clean_up_downloaded_chapters), title = stringResource(SYMR.strings.clean_up_downloaded_chapters),
subtitle = stringResource(SYMR.strings.delete_unused_chapters), subtitle = stringResource(SYMR.strings.delete_unused_chapters),
@ -553,12 +557,12 @@ object SettingsAdvancedScreen : SearchableSettings {
val dataSaver by sourcePreferences.dataSaver().collectAsState() val dataSaver by sourcePreferences.dataSaver().collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(SYMR.strings.data_saver), title = stringResource(SYMR.strings.data_saver),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = sourcePreferences.dataSaver(), pref = sourcePreferences.dataSaver(),
title = stringResource(SYMR.strings.data_saver), title = stringResource(SYMR.strings.data_saver),
subtitle = stringResource(SYMR.strings.data_saver_summary), subtitle = stringResource(SYMR.strings.data_saver_summary),
entries = mapOf( entries = persistentMapOf(
DataSaver.NONE to stringResource(MR.strings.disabled), DataSaver.NONE to stringResource(MR.strings.disabled),
DataSaver.BANDWIDTH_HERO to stringResource(SYMR.strings.bandwidth_hero), DataSaver.BANDWIDTH_HERO to stringResource(SYMR.strings.bandwidth_hero),
DataSaver.WSRV_NL to stringResource(SYMR.strings.wsrv), DataSaver.WSRV_NL to stringResource(SYMR.strings.wsrv),
@ -598,7 +602,7 @@ object SettingsAdvancedScreen : SearchableSettings {
"80%", "80%",
"90%", "90%",
"95%", "95%",
).associateBy { it.trimEnd('%').toInt() }, ).associateBy { it.trimEnd('%').toInt() }.toImmutableMap(),
enabled = dataSaver != DataSaver.NONE, enabled = dataSaver != DataSaver.NONE,
), ),
kotlin.run { kotlin.run {
@ -634,7 +638,7 @@ object SettingsAdvancedScreen : SearchableSettings {
val securityPreferences = remember { Injekt.get<SecurityPreferences>() } val securityPreferences = remember { Injekt.get<SecurityPreferences>() }
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(SYMR.strings.developer_tools), title = stringResource(SYMR.strings.developer_tools),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = unsortedPreferences.isHentaiEnabled(), pref = unsortedPreferences.isHentaiEnabled(),
title = stringResource(SYMR.strings.toggle_hentai_features), title = stringResource(SYMR.strings.toggle_hentai_features),
@ -664,11 +668,11 @@ object SettingsAdvancedScreen : SearchableSettings {
pref = unsortedPreferences.logLevel(), pref = unsortedPreferences.logLevel(),
title = stringResource(SYMR.strings.log_level), title = stringResource(SYMR.strings.log_level),
subtitle = stringResource(SYMR.strings.log_level_summary), subtitle = stringResource(SYMR.strings.log_level_summary),
entries = EHLogLevel.values().mapIndexed { index, ehLogLevel -> entries = EHLogLevel.entries.mapIndexed { index, ehLogLevel ->
index to "${context.stringResource(ehLogLevel.nameRes)} (${ index to "${context.stringResource(ehLogLevel.nameRes)} (${
context.stringResource(ehLogLevel.description) context.stringResource(ehLogLevel.description)
})" })"
}.toMap(), }.toMap().toImmutableMap(),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = sourcePreferences.enableSourceBlacklist(), pref = sourcePreferences.enableSourceBlacklist(),

View File

@ -24,6 +24,9 @@ import eu.kanade.presentation.more.settings.widget.AppThemePreferenceWidget
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableMap
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -71,7 +74,7 @@ object SettingsAppearanceScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_theme), title = stringResource(MR.strings.pref_category_theme),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.CustomPreference( Preference.PreferenceItem.CustomPreference(
title = stringResource(MR.strings.pref_app_theme), title = stringResource(MR.strings.pref_app_theme),
) { ) {
@ -132,7 +135,7 @@ object SettingsAppearanceScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_display), title = stringResource(MR.strings.pref_category_display),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.BasicListPreference( Preference.PreferenceItem.BasicListPreference(
value = currentLanguage, value = currentLanguage,
title = stringResource(MR.strings.pref_app_language), title = stringResource(MR.strings.pref_app_language),
@ -145,7 +148,9 @@ object SettingsAppearanceScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = uiPreferences.tabletUiMode(), pref = uiPreferences.tabletUiMode(),
title = stringResource(MR.strings.pref_tablet_ui_mode), title = stringResource(MR.strings.pref_tablet_ui_mode),
entries = TabletUiMode.entries.associateWith { stringResource(it.titleRes) }, entries = TabletUiMode.entries
.associateWith { stringResource(it.titleRes) }
.toImmutableMap(),
onValueChanged = { onValueChanged = {
context.toast(MR.strings.requires_app_restart) context.toast(MR.strings.requires_app_restart)
true true
@ -158,7 +163,8 @@ object SettingsAppearanceScreen : SearchableSettings {
.associateWith { .associateWith {
val formattedDate = UiPreferences.dateFormat(it).format(now) val formattedDate = UiPreferences.dateFormat(it).format(now)
"${it.ifEmpty { stringResource(MR.strings.label_default) }} ($formattedDate)" "${it.ifEmpty { stringResource(MR.strings.label_default) }} ($formattedDate)"
}, }
.toImmutableMap(),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.relativeTime(), pref = uiPreferences.relativeTime(),
@ -172,7 +178,7 @@ object SettingsAppearanceScreen : SearchableSettings {
), ),
) )
} }
private fun getLangs(context: Context): Map<String, String> { private fun getLangs(context: Context): ImmutableMap<String, String> {
val langs = mutableListOf<Pair<String, String>>() val langs = mutableListOf<Pair<String, String>>()
val parser = context.resources.getXml(R.xml.locales_config) val parser = context.resources.getXml(R.xml.locales_config)
var eventType = parser.eventType var eventType = parser.eventType
@ -194,7 +200,7 @@ object SettingsAppearanceScreen : SearchableSettings {
langs.sortBy { it.second } langs.sortBy { it.second }
langs.add(0, Pair("", context.stringResource(MR.strings.label_default))) langs.add(0, Pair("", context.stringResource(MR.strings.label_default)))
return langs.toMap() return langs.toMap().toImmutableMap()
} }
// SY --> // SY -->
@ -202,7 +208,7 @@ object SettingsAppearanceScreen : SearchableSettings {
fun getForkGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup { fun getForkGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
stringResource(SYMR.strings.pref_category_fork), stringResource(SYMR.strings.pref_category_fork),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.expandFilters(), pref = uiPreferences.expandFilters(),
title = stringResource(SYMR.strings.toggle_expand_search_filters), title = stringResource(SYMR.strings.toggle_expand_search_filters),
@ -225,7 +231,7 @@ object SettingsAppearanceScreen : SearchableSettings {
fun getNavbarGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup { fun getNavbarGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
stringResource(SYMR.strings.pref_category_navbar), stringResource(SYMR.strings.pref_category_navbar),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.showNavUpdates(), pref = uiPreferences.showNavUpdates(),
title = stringResource(SYMR.strings.pref_hide_updates_button), title = stringResource(SYMR.strings.pref_hide_updates_button),

View File

@ -14,6 +14,7 @@ import eu.kanade.presentation.more.settings.Preference
import eu.kanade.tachiyomi.ui.category.repos.RepoScreen import eu.kanade.tachiyomi.ui.category.repos.RepoScreen
import eu.kanade.tachiyomi.ui.category.sources.SourceCategoryScreen import eu.kanade.tachiyomi.ui.category.sources.SourceCategoryScreen
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.domain.UnsortedPreferences import tachiyomi.domain.UnsortedPreferences
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -42,7 +43,7 @@ object SettingsBrowseScreen : SearchableSettings {
// SY --> // SY -->
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(MR.strings.label_sources), title = stringResource(MR.strings.label_sources),
preferenceItems = listOf( preferenceItems = persistentListOf(
kotlin.run { kotlin.run {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val count by sourcePreferences.sourcesTabCategories().collectAsState() val count by sourcePreferences.sourcesTabCategories().collectAsState()
@ -73,7 +74,7 @@ object SettingsBrowseScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(SYMR.strings.feed), title = stringResource(SYMR.strings.feed),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.feedTabInFront(), pref = uiPreferences.feedTabInFront(),
title = stringResource(SYMR.strings.pref_feed_position), title = stringResource(SYMR.strings.pref_feed_position),
@ -83,7 +84,7 @@ object SettingsBrowseScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(MR.strings.label_extensions), title = stringResource(MR.strings.label_extensions),
preferenceItems = listOf( preferenceItems = persistentListOf(
kotlin.run { kotlin.run {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val count by unsortedPreferences.extensionRepos().collectAsState() val count by unsortedPreferences.extensionRepos().collectAsState()
@ -100,7 +101,7 @@ object SettingsBrowseScreen : SearchableSettings {
// SY <-- // SY <--
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(MR.strings.label_sources), title = stringResource(MR.strings.label_sources),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = sourcePreferences.hideInLibraryItems(), pref = sourcePreferences.hideInLibraryItems(),
title = stringResource(MR.strings.pref_hide_in_library_items), title = stringResource(MR.strings.pref_hide_in_library_items),
@ -109,7 +110,7 @@ object SettingsBrowseScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_nsfw_content), title = stringResource(MR.strings.pref_category_nsfw_content),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = sourcePreferences.showNsfwSource(), pref = sourcePreferences.showNsfwSource(),
title = stringResource(MR.strings.pref_show_nsfw_source), title = stringResource(MR.strings.pref_show_nsfw_source),

View File

@ -3,12 +3,9 @@ package eu.kanade.presentation.more.settings.screen
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Environment
import android.text.format.Formatter
import androidx.activity.compose.ManagedActivityResultLauncher import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MultiChoiceSegmentedButtonRow import androidx.compose.material3.MultiChoiceSegmentedButtonRow
@ -31,14 +28,16 @@ import com.hippo.unifile.UniFile
import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
import eu.kanade.presentation.more.settings.screen.data.RestoreBackupScreen import eu.kanade.presentation.more.settings.screen.data.RestoreBackupScreen
import eu.kanade.presentation.more.settings.screen.data.StorageInfo
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
import eu.kanade.presentation.util.relativeTimeSpanString import eu.kanade.presentation.util.relativeTimeSpanString
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.PagePreviewCache import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.util.lang.launchNonCancellable
@ -67,7 +66,7 @@ object SettingsDataScreen : SearchableSettings {
val backupPreferences = Injekt.get<BackupPreferences>() val backupPreferences = Injekt.get<BackupPreferences>()
val storagePreferences = Injekt.get<StoragePreferences>() val storagePreferences = Injekt.get<StoragePreferences>()
return listOf( return persistentListOf(
getStorageLocationPref(storagePreferences = storagePreferences), getStorageLocationPref(storagePreferences = storagePreferences),
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)), Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),
@ -144,7 +143,7 @@ object SettingsDataScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_backup), title = stringResource(MR.strings.label_backup),
preferenceItems = listOf( preferenceItems = persistentListOf(
// Manual actions // Manual actions
Preference.PreferenceItem.CustomPreference( Preference.PreferenceItem.CustomPreference(
title = stringResource(restorePreferenceKeyString), title = stringResource(restorePreferenceKeyString),
@ -179,7 +178,7 @@ object SettingsDataScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = backupPreferences.backupInterval(), pref = backupPreferences.backupInterval(),
title = stringResource(MR.strings.pref_backup_interval), title = stringResource(MR.strings.pref_backup_interval),
entries = mapOf( entries = persistentMapOf(
0 to stringResource(MR.strings.off), 0 to stringResource(MR.strings.off),
6 to stringResource(MR.strings.update_6hour), 6 to stringResource(MR.strings.update_6hour),
12 to stringResource(MR.strings.update_12hour), 12 to stringResource(MR.strings.update_12hour),
@ -202,8 +201,8 @@ object SettingsDataScreen : SearchableSettings {
@Composable @Composable
private fun getDataGroup(): Preference.PreferenceGroup { private fun getDataGroup(): Preference.PreferenceGroup {
val scope = rememberCoroutineScope()
val context = LocalContext.current val context = LocalContext.current
val scope = rememberCoroutineScope()
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() } val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
val chapterCache = remember { Injekt.get<ChapterCache>() } val chapterCache = remember { Injekt.get<ChapterCache>() }
@ -218,8 +217,19 @@ object SettingsDataScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_data), title = stringResource(MR.strings.label_data),
preferenceItems = listOf( preferenceItems = persistentListOf(
getStorageInfoPref(cacheReadableSize), Preference.PreferenceItem.CustomPreference(
title = stringResource(MR.strings.pref_storage_usage),
) {
BasePreferenceWidget(
title = stringResource(MR.strings.pref_storage_usage),
subcomponent = {
StorageInfo(
modifier = Modifier.padding(horizontal = PrefsHorizontalPadding),
)
},
)
},
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_clear_chapter_cache), title = stringResource(MR.strings.pref_clear_chapter_cache),
@ -266,31 +276,4 @@ object SettingsDataScreen : SearchableSettings {
), ),
) )
} }
@Composable
fun getStorageInfoPref(
chapterCacheReadableSize: String,
): Preference.PreferenceItem.CustomPreference {
val context = LocalContext.current
val available = remember {
Formatter.formatFileSize(context, DiskUtil.getAvailableStorageSpace(Environment.getDataDirectory()))
}
val total = remember {
Formatter.formatFileSize(context, DiskUtil.getTotalStorageSpace(Environment.getDataDirectory()))
}
return Preference.PreferenceItem.CustomPreference(
title = stringResource(MR.strings.pref_storage_usage),
) {
BasePreferenceWidget(
title = stringResource(MR.strings.pref_storage_usage),
subcomponent = {
// TODO: downloads, SD cards, bar representation?, i18n
Box(modifier = Modifier.padding(horizontal = PrefsHorizontalPadding)) {
Text(text = "Available: $available / $total (chapter cache: $chapterCacheReadableSize)")
}
},
)
}
}
} }

View File

@ -12,6 +12,9 @@ import androidx.compose.ui.util.fastMap
import eu.kanade.presentation.category.visualName import eu.kanade.presentation.category.visualName
import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.widget.TriStateListDialog import eu.kanade.presentation.more.settings.widget.TriStateListDialog
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
@ -68,7 +71,7 @@ object SettingsDownloadScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_delete_chapters), title = stringResource(MR.strings.pref_category_delete_chapters),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = downloadPreferences.removeAfterMarkedAsRead(), pref = downloadPreferences.removeAfterMarkedAsRead(),
title = stringResource(MR.strings.pref_remove_after_marked_as_read), title = stringResource(MR.strings.pref_remove_after_marked_as_read),
@ -76,7 +79,7 @@ object SettingsDownloadScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = downloadPreferences.removeAfterReadSlots(), pref = downloadPreferences.removeAfterReadSlots(),
title = stringResource(MR.strings.pref_remove_after_read), title = stringResource(MR.strings.pref_remove_after_read),
entries = mapOf( entries = persistentMapOf(
-1 to stringResource(MR.strings.disabled), -1 to stringResource(MR.strings.disabled),
0 to stringResource(MR.strings.last_read_chapter), 0 to stringResource(MR.strings.last_read_chapter),
1 to stringResource(MR.strings.second_to_last), 1 to stringResource(MR.strings.second_to_last),
@ -105,7 +108,9 @@ object SettingsDownloadScreen : SearchableSettings {
return Preference.PreferenceItem.MultiSelectListPreference( return Preference.PreferenceItem.MultiSelectListPreference(
pref = downloadPreferences.removeExcludeCategories(), pref = downloadPreferences.removeExcludeCategories(),
title = stringResource(MR.strings.pref_remove_exclude_categories), title = stringResource(MR.strings.pref_remove_exclude_categories),
entries = categories().associate { it.id.toString() to it.visualName }, entries = categories()
.associate { it.id.toString() to it.visualName }
.toImmutableMap(),
) )
} }
@ -142,7 +147,7 @@ object SettingsDownloadScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_auto_download), title = stringResource(MR.strings.pref_category_auto_download),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = downloadNewChaptersPref, pref = downloadNewChaptersPref,
title = stringResource(MR.strings.pref_download_new), title = stringResource(MR.strings.pref_download_new),
@ -167,17 +172,19 @@ object SettingsDownloadScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.download_ahead), title = stringResource(MR.strings.download_ahead),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = downloadPreferences.autoDownloadWhileReading(), pref = downloadPreferences.autoDownloadWhileReading(),
title = stringResource(MR.strings.auto_download_while_reading), title = stringResource(MR.strings.auto_download_while_reading),
entries = listOf(0, 2, 3, 5, 10).associateWith { entries = listOf(0, 2, 3, 5, 10)
.associateWith {
if (it == 0) { if (it == 0) {
stringResource(MR.strings.disabled) stringResource(MR.strings.disabled)
} else { } else {
pluralStringResource(MR.plurals.next_unread_chapters, count = it, it) pluralStringResource(MR.plurals.next_unread_chapters, count = it, it)
} }
}, }
.toImmutableMap(),
), ),
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.download_ahead_info)), Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.download_ahead_info)),
), ),

View File

@ -54,6 +54,8 @@ import exh.eh.EHentaiUpdaterStats
import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.EHentaiSearchMetadata
import exh.ui.login.EhLoginActivity import exh.ui.login.EhLoginActivity
import exh.util.nullIfBlank import exh.util.nullIfBlank
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.pluralStringResource import tachiyomi.core.i18n.pluralStringResource
@ -138,7 +140,7 @@ object SettingsEhScreen : SearchableSettings {
return listOf( return listOf(
Preference.PreferenceGroup( Preference.PreferenceGroup(
stringResource(SYMR.strings.ehentai_prefs_account_settings), stringResource(SYMR.strings.ehentai_prefs_account_settings),
preferenceItems = listOf( preferenceItems = persistentListOf(
getLoginPreference(unsortedPreferences, openWarnConfigureDialogController), getLoginPreference(unsortedPreferences, openWarnConfigureDialogController),
useHentaiAtHome(exhentaiEnabled, unsortedPreferences), useHentaiAtHome(exhentaiEnabled, unsortedPreferences),
useJapaneseTitle(exhentaiEnabled, unsortedPreferences), useJapaneseTitle(exhentaiEnabled, unsortedPreferences),
@ -155,7 +157,7 @@ object SettingsEhScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
stringResource(SYMR.strings.favorites_sync), stringResource(SYMR.strings.favorites_sync),
preferenceItems = listOf( preferenceItems = persistentListOf(
readOnlySync(unsortedPreferences), readOnlySync(unsortedPreferences),
syncFavoriteNotes(), syncFavoriteNotes(),
lenientSync(unsortedPreferences), lenientSync(unsortedPreferences),
@ -164,7 +166,7 @@ object SettingsEhScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
stringResource(SYMR.strings.gallery_update_checker), stringResource(SYMR.strings.gallery_update_checker),
preferenceItems = listOf( preferenceItems = persistentListOf(
updateCheckerFrequency(unsortedPreferences), updateCheckerFrequency(unsortedPreferences),
autoUpdateRequirements(unsortedPreferences), autoUpdateRequirements(unsortedPreferences),
updaterStatistics( updaterStatistics(
@ -220,7 +222,7 @@ object SettingsEhScreen : SearchableSettings {
pref = unsortedPreferences.useHentaiAtHome(), pref = unsortedPreferences.useHentaiAtHome(),
title = stringResource(SYMR.strings.use_hentai_at_home), title = stringResource(SYMR.strings.use_hentai_at_home),
subtitle = stringResource(SYMR.strings.use_hentai_at_home_summary), subtitle = stringResource(SYMR.strings.use_hentai_at_home_summary),
entries = mapOf( entries = persistentMapOf(
0 to stringResource(SYMR.strings.use_hentai_at_home_option_1), 0 to stringResource(SYMR.strings.use_hentai_at_home_option_1),
1 to stringResource(SYMR.strings.use_hentai_at_home_option_2), 1 to stringResource(SYMR.strings.use_hentai_at_home_option_2),
), ),
@ -816,7 +818,7 @@ object SettingsEhScreen : SearchableSettings {
pref = unsortedPreferences.imageQuality(), pref = unsortedPreferences.imageQuality(),
title = stringResource(SYMR.strings.eh_image_quality_summary), title = stringResource(SYMR.strings.eh_image_quality_summary),
subtitle = stringResource(SYMR.strings.eh_image_quality), subtitle = stringResource(SYMR.strings.eh_image_quality),
entries = mapOf( entries = persistentMapOf(
"auto" to stringResource(SYMR.strings.eh_image_quality_auto), "auto" to stringResource(SYMR.strings.eh_image_quality_auto),
"ovrs_2400" to stringResource(SYMR.strings.eh_image_quality_2400), "ovrs_2400" to stringResource(SYMR.strings.eh_image_quality_2400),
"ovrs_1600" to stringResource(SYMR.strings.eh_image_quality_1600), "ovrs_1600" to stringResource(SYMR.strings.eh_image_quality_1600),
@ -952,7 +954,7 @@ object SettingsEhScreen : SearchableSettings {
EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION, EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION,
) )
}, },
entries = mapOf( entries = persistentMapOf(
0 to stringResource(SYMR.strings.time_between_batches_never), 0 to stringResource(SYMR.strings.time_between_batches_never),
1 to stringResource(SYMR.strings.time_between_batches_1_hour), 1 to stringResource(SYMR.strings.time_between_batches_1_hour),
2 to stringResource(SYMR.strings.time_between_batches_2_hours), 2 to stringResource(SYMR.strings.time_between_batches_2_hours),
@ -995,7 +997,7 @@ object SettingsEhScreen : SearchableSettings {
.joinToString(), .joinToString(),
) )
}, },
entries = mapOf( entries = persistentMapOf(
DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi), DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi),
DEVICE_CHARGING to stringResource(MR.strings.charging), DEVICE_CHARGING to stringResource(MR.strings.charging),
), ),

View File

@ -21,6 +21,9 @@ import eu.kanade.presentation.more.settings.widget.TriStateListDialog
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.ui.category.CategoryScreen import eu.kanade.tachiyomi.ui.category.CategoryScreen
import eu.kanade.tachiyomi.ui.category.genre.SortTagScreen import eu.kanade.tachiyomi.ui.category.genre.SortTagScreen
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import tachiyomi.domain.UnsortedPreferences import tachiyomi.domain.UnsortedPreferences
@ -92,7 +95,7 @@ object SettingsLibraryScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.categories), title = stringResource(MR.strings.categories),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.action_edit_categories), title = stringResource(MR.strings.action_edit_categories),
subtitle = pluralStringResource( subtitle = pluralStringResource(
@ -106,7 +109,7 @@ object SettingsLibraryScreen : SearchableSettings {
pref = libraryPreferences.defaultCategory(), pref = libraryPreferences.defaultCategory(),
title = stringResource(MR.strings.default_category), title = stringResource(MR.strings.default_category),
subtitle = selectedCategory?.visualName ?: stringResource(MR.strings.default_category_summary), subtitle = selectedCategory?.visualName ?: stringResource(MR.strings.default_category_summary),
entries = ids.zip(labels).toMap(), entries = ids.zip(labels).toMap().toImmutableMap(),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = libraryPreferences.categorizedDisplaySettings(), pref = libraryPreferences.categorizedDisplaySettings(),
@ -159,11 +162,11 @@ object SettingsLibraryScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_library_update), title = stringResource(MR.strings.pref_category_library_update),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = autoUpdateIntervalPref, pref = autoUpdateIntervalPref,
title = stringResource(MR.strings.pref_library_update_interval), title = stringResource(MR.strings.pref_library_update_interval),
entries = mapOf( entries = persistentMapOf(
0 to stringResource(MR.strings.update_never), 0 to stringResource(MR.strings.update_never),
12 to stringResource(MR.strings.update_12hour), 12 to stringResource(MR.strings.update_12hour),
24 to stringResource(MR.strings.update_24hour), 24 to stringResource(MR.strings.update_24hour),
@ -181,7 +184,7 @@ object SettingsLibraryScreen : SearchableSettings {
enabled = autoUpdateInterval > 0, enabled = autoUpdateInterval > 0,
title = stringResource(MR.strings.pref_library_update_restriction), title = stringResource(MR.strings.pref_library_update_restriction),
subtitle = stringResource(MR.strings.restrictions), subtitle = stringResource(MR.strings.restrictions),
entries = mapOf( entries = persistentMapOf(
DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi), DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi),
DEVICE_NETWORK_NOT_METERED to stringResource(MR.strings.network_not_metered), DEVICE_NETWORK_NOT_METERED to stringResource(MR.strings.network_not_metered),
DEVICE_CHARGING to stringResource(MR.strings.charging), DEVICE_CHARGING to stringResource(MR.strings.charging),
@ -205,7 +208,7 @@ object SettingsLibraryScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = libraryPreferences.groupLibraryUpdateType(), pref = libraryPreferences.groupLibraryUpdateType(),
title = stringResource(SYMR.strings.library_group_updates), title = stringResource(SYMR.strings.library_group_updates),
entries = mapOf( entries = persistentMapOf(
GroupLibraryMode.GLOBAL to stringResource(SYMR.strings.library_group_updates_global), GroupLibraryMode.GLOBAL to stringResource(SYMR.strings.library_group_updates_global),
GroupLibraryMode.ALL_BUT_UNGROUPED to GroupLibraryMode.ALL_BUT_UNGROUPED to
stringResource(SYMR.strings.library_group_updates_all_but_ungrouped), stringResource(SYMR.strings.library_group_updates_all_but_ungrouped),
@ -221,7 +224,7 @@ object SettingsLibraryScreen : SearchableSettings {
Preference.PreferenceItem.MultiSelectListPreference( Preference.PreferenceItem.MultiSelectListPreference(
pref = libraryPreferences.autoUpdateMangaRestrictions(), pref = libraryPreferences.autoUpdateMangaRestrictions(),
title = stringResource(MR.strings.pref_library_update_manga_restriction), title = stringResource(MR.strings.pref_library_update_manga_restriction),
entries = mapOf( entries = persistentMapOf(
MANGA_HAS_UNREAD to stringResource(MR.strings.pref_update_only_completely_read), MANGA_HAS_UNREAD to stringResource(MR.strings.pref_update_only_completely_read),
MANGA_NON_READ to stringResource(MR.strings.pref_update_only_started), MANGA_NON_READ to stringResource(MR.strings.pref_update_only_started),
MANGA_NON_COMPLETED to stringResource(MR.strings.pref_update_only_non_completed), MANGA_NON_COMPLETED to stringResource(MR.strings.pref_update_only_non_completed),
@ -242,11 +245,11 @@ object SettingsLibraryScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_chapter_swipe), title = stringResource(MR.strings.pref_chapter_swipe),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = libraryPreferences.swipeToStartAction(), pref = libraryPreferences.swipeToStartAction(),
title = stringResource(MR.strings.pref_chapter_swipe_start), title = stringResource(MR.strings.pref_chapter_swipe_start),
entries = mapOf( entries = persistentMapOf(
LibraryPreferences.ChapterSwipeAction.Disabled to LibraryPreferences.ChapterSwipeAction.Disabled to
stringResource(MR.strings.disabled), stringResource(MR.strings.disabled),
LibraryPreferences.ChapterSwipeAction.ToggleBookmark to LibraryPreferences.ChapterSwipeAction.ToggleBookmark to
@ -260,13 +263,15 @@ object SettingsLibraryScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = libraryPreferences.swipeToEndAction(), pref = libraryPreferences.swipeToEndAction(),
title = stringResource(MR.strings.pref_chapter_swipe_end), title = stringResource(MR.strings.pref_chapter_swipe_end),
entries = mapOf( entries = persistentMapOf(
LibraryPreferences.ChapterSwipeAction.Disabled to stringResource(MR.strings.disabled), LibraryPreferences.ChapterSwipeAction.Disabled to
stringResource(MR.strings.disabled),
LibraryPreferences.ChapterSwipeAction.ToggleBookmark to LibraryPreferences.ChapterSwipeAction.ToggleBookmark to
stringResource(MR.strings.action_bookmark), stringResource(MR.strings.action_bookmark),
LibraryPreferences.ChapterSwipeAction.ToggleRead to LibraryPreferences.ChapterSwipeAction.ToggleRead to
stringResource(MR.strings.action_mark_as_read), stringResource(MR.strings.action_mark_as_read),
LibraryPreferences.ChapterSwipeAction.Download to stringResource(MR.strings.action_download), LibraryPreferences.ChapterSwipeAction.Download to
stringResource(MR.strings.action_download),
), ),
), ),
), ),
@ -279,7 +284,7 @@ object SettingsLibraryScreen : SearchableSettings {
val tagCount by libraryPreferences.sortTagsForLibrary().collectAsState() val tagCount by libraryPreferences.sortTagsForLibrary().collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
stringResource(SYMR.strings.pref_sorting_settings), stringResource(SYMR.strings.pref_sorting_settings),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(SYMR.strings.pref_tag_sorting), title = stringResource(SYMR.strings.pref_tag_sorting),
subtitle = pluralStringResource(SYMR.plurals.pref_tag_sorting_desc, tagCount.size, tagCount.size), subtitle = pluralStringResource(SYMR.plurals.pref_tag_sorting_desc, tagCount.size, tagCount.size),
@ -298,7 +303,7 @@ object SettingsLibraryScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
stringResource(SYMR.strings.migration), stringResource(SYMR.strings.migration),
enabled = skipPreMigration || migrationSources.isNotEmpty(), enabled = skipPreMigration || migrationSources.isNotEmpty(),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = unsortedPreferences.skipPreMigration(), pref = unsortedPreferences.skipPreMigration(),
title = stringResource(SYMR.strings.skip_pre_migration), title = stringResource(SYMR.strings.skip_pre_migration),

View File

@ -39,6 +39,7 @@ import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import exh.md.utils.MdConstants import exh.md.utils.MdConstants
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import kotlinx.collections.immutable.toImmutableMap
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.launchIO
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.lang.withUIContext
@ -181,7 +182,8 @@ object SettingsMangadexScreen : SearchableSettings {
title = stringResource(SYMR.strings.mangadex_preffered_source), title = stringResource(SYMR.strings.mangadex_preffered_source),
subtitle = stringResource(SYMR.strings.mangadex_preffered_source_summary), subtitle = stringResource(SYMR.strings.mangadex_preffered_source_summary),
entries = MdUtil.getEnabledMangaDexs(sourcePreferences) entries = MdUtil.getEnabledMangaDexs(sourcePreferences)
.associate { it.id.toString() to it.toString() }, .associate { it.id.toString() to it.toString() }
.toImmutableMap(),
) )
} }

View File

@ -12,6 +12,9 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@ -37,12 +40,13 @@ object SettingsReaderScreen : SearchableSettings {
pref = readerPref.defaultReadingMode(), pref = readerPref.defaultReadingMode(),
title = stringResource(MR.strings.pref_viewer_type), title = stringResource(MR.strings.pref_viewer_type),
entries = ReadingMode.entries.drop(1) entries = ReadingMode.entries.drop(1)
.associate { it.flagValue to stringResource(it.stringRes) }, .associate { it.flagValue to stringResource(it.stringRes) }
.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPref.doubleTapAnimSpeed(), pref = readerPref.doubleTapAnimSpeed(),
title = stringResource(MR.strings.pref_double_tap_anim_speed), title = stringResource(MR.strings.pref_double_tap_anim_speed),
entries = mapOf( entries = persistentMapOf(
1 to stringResource(MR.strings.double_tap_anim_speed_0), 1 to stringResource(MR.strings.double_tap_anim_speed_0),
500 to stringResource(MR.strings.double_tap_anim_speed_normal), 500 to stringResource(MR.strings.double_tap_anim_speed_normal),
250 to stringResource(MR.strings.double_tap_anim_speed_fast), 250 to stringResource(MR.strings.double_tap_anim_speed_fast),
@ -116,17 +120,18 @@ object SettingsReaderScreen : SearchableSettings {
val fullscreen by fullscreenPref.collectAsState() val fullscreen by fullscreenPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_display), title = stringResource(MR.strings.pref_category_display),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.defaultOrientationType(), pref = readerPreferences.defaultOrientationType(),
title = stringResource(MR.strings.pref_rotation_type), title = stringResource(MR.strings.pref_rotation_type),
entries = ReaderOrientation.entries.drop(1) entries = ReaderOrientation.entries.drop(1)
.associate { it.flagValue to stringResource(it.stringRes) }, .associate { it.flagValue to stringResource(it.stringRes) }
.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.readerTheme(), pref = readerPreferences.readerTheme(),
title = stringResource(MR.strings.pref_reader_theme), title = stringResource(MR.strings.pref_reader_theme),
entries = mapOf( entries = persistentMapOf(
1 to stringResource(MR.strings.black_background), 1 to stringResource(MR.strings.black_background),
2 to stringResource(MR.strings.gray_background), 2 to stringResource(MR.strings.gray_background),
0 to stringResource(MR.strings.white_background), 0 to stringResource(MR.strings.white_background),
@ -160,7 +165,7 @@ object SettingsReaderScreen : SearchableSettings {
private fun getReadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getReadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_reading), title = stringResource(MR.strings.pref_category_reading),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.skipRead(), pref = readerPreferences.skipRead(),
title = stringResource(MR.strings.pref_skip_read_chapters), title = stringResource(MR.strings.pref_skip_read_chapters),
@ -195,25 +200,26 @@ object SettingsReaderScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pager_viewer), title = stringResource(MR.strings.pager_viewer),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = navModePref, pref = navModePref,
title = stringResource(MR.strings.pref_viewer_nav), title = stringResource(MR.strings.pref_viewer_nav),
entries = ReaderPreferences.TapZones entries = ReaderPreferences.TapZones
.mapIndexed { index, it -> index to stringResource(it) } .mapIndexed { index, it -> index to stringResource(it) }
.toMap(), .toMap()
.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.pagerNavInverted(), pref = readerPreferences.pagerNavInverted(),
title = stringResource(MR.strings.pref_read_with_tapping_inverted), title = stringResource(MR.strings.pref_read_with_tapping_inverted),
entries = mapOf( entries = persistentListOf(
ReaderPreferences.TappingInvertMode.NONE to stringResource(MR.strings.none), ReaderPreferences.TappingInvertMode.NONE,
ReaderPreferences.TappingInvertMode.HORIZONTAL to ReaderPreferences.TappingInvertMode.HORIZONTAL,
stringResource(MR.strings.tapping_inverted_horizontal), ReaderPreferences.TappingInvertMode.VERTICAL,
ReaderPreferences.TappingInvertMode.VERTICAL to ReaderPreferences.TappingInvertMode.BOTH,
stringResource(MR.strings.tapping_inverted_vertical), )
ReaderPreferences.TappingInvertMode.BOTH to stringResource(MR.strings.tapping_inverted_both), .associateWith { stringResource(it.titleRes) }
), .toImmutableMap(),
enabled = navMode != 5, enabled = navMode != 5,
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
@ -221,14 +227,16 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_image_scale_type), title = stringResource(MR.strings.pref_image_scale_type),
entries = ReaderPreferences.ImageScaleType entries = ReaderPreferences.ImageScaleType
.mapIndexed { index, it -> index + 1 to stringResource(it) } .mapIndexed { index, it -> index + 1 to stringResource(it) }
.toMap(), .toMap()
.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.zoomStart(), pref = readerPreferences.zoomStart(),
title = stringResource(MR.strings.pref_zoom_start), title = stringResource(MR.strings.pref_zoom_start),
entries = ReaderPreferences.ZoomStart entries = ReaderPreferences.ZoomStart
.mapIndexed { index, it -> index + 1 to stringResource(it) } .mapIndexed { index, it -> index + 1 to stringResource(it) }
.toMap(), .toMap()
.toImmutableMap(),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.cropBorders(), pref = readerPreferences.cropBorders(),
@ -297,25 +305,26 @@ object SettingsReaderScreen : SearchableSettings {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.webtoon_viewer), title = stringResource(MR.strings.webtoon_viewer),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = navModePref, pref = navModePref,
title = stringResource(MR.strings.pref_viewer_nav), title = stringResource(MR.strings.pref_viewer_nav),
entries = ReaderPreferences.TapZones entries = ReaderPreferences.TapZones
.mapIndexed { index, it -> index to stringResource(it) } .mapIndexed { index, it -> index to stringResource(it) }
.toMap(), .toMap()
.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.webtoonNavInverted(), pref = readerPreferences.webtoonNavInverted(),
title = stringResource(MR.strings.pref_read_with_tapping_inverted), title = stringResource(MR.strings.pref_read_with_tapping_inverted),
entries = mapOf( entries = persistentListOf(
ReaderPreferences.TappingInvertMode.NONE to stringResource(MR.strings.none), ReaderPreferences.TappingInvertMode.NONE,
ReaderPreferences.TappingInvertMode.HORIZONTAL to ReaderPreferences.TappingInvertMode.HORIZONTAL,
stringResource(MR.strings.tapping_inverted_horizontal), ReaderPreferences.TappingInvertMode.VERTICAL,
ReaderPreferences.TappingInvertMode.VERTICAL to ReaderPreferences.TappingInvertMode.BOTH,
stringResource(MR.strings.tapping_inverted_vertical), )
ReaderPreferences.TappingInvertMode.BOTH to stringResource(MR.strings.tapping_inverted_both), .associateWith { stringResource(it.titleRes) }
), .toImmutableMap(),
enabled = navMode != 5, enabled = navMode != 5,
), ),
Preference.PreferenceItem.SliderPreference( Preference.PreferenceItem.SliderPreference(
@ -332,7 +341,7 @@ object SettingsReaderScreen : SearchableSettings {
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.readerHideThreshold(), pref = readerPreferences.readerHideThreshold(),
title = stringResource(MR.strings.pref_hide_threshold), title = stringResource(MR.strings.pref_hide_threshold),
entries = mapOf( entries = persistentMapOf(
ReaderPreferences.ReaderHideThreshold.HIGHEST to stringResource(MR.strings.pref_highest), ReaderPreferences.ReaderHideThreshold.HIGHEST to stringResource(MR.strings.pref_highest),
ReaderPreferences.ReaderHideThreshold.HIGH to stringResource(MR.strings.pref_high), ReaderPreferences.ReaderHideThreshold.HIGH to stringResource(MR.strings.pref_high),
ReaderPreferences.ReaderHideThreshold.LOW to stringResource(MR.strings.pref_low), ReaderPreferences.ReaderHideThreshold.LOW to stringResource(MR.strings.pref_low),
@ -394,7 +403,7 @@ object SettingsReaderScreen : SearchableSettings {
private fun getContinuousVerticalGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getContinuousVerticalGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.vertical_plus_viewer), title = stringResource(MR.strings.vertical_plus_viewer),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.continuousVerticalTappingByPage(), pref = readerPreferences.continuousVerticalTappingByPage(),
title = stringResource(SYMR.strings.tap_scroll_page), title = stringResource(SYMR.strings.tap_scroll_page),
@ -415,7 +424,7 @@ object SettingsReaderScreen : SearchableSettings {
val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState() val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_reader_navigation), title = stringResource(MR.strings.pref_reader_navigation),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readWithVolumeKeysPref, pref = readWithVolumeKeysPref,
title = stringResource(MR.strings.pref_read_with_volume_keys), title = stringResource(MR.strings.pref_read_with_volume_keys),
@ -433,7 +442,7 @@ object SettingsReaderScreen : SearchableSettings {
private fun getActionsGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getActionsGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_reader_actions), title = stringResource(MR.strings.pref_reader_actions),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.readWithLongTap(), pref = readerPreferences.readWithLongTap(),
title = stringResource(MR.strings.pref_read_with_long_tap), title = stringResource(MR.strings.pref_read_with_long_tap),
@ -452,12 +461,12 @@ object SettingsReaderScreen : SearchableSettings {
private fun getPageDownloadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getPageDownloadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(SYMR.strings.page_downloading), title = stringResource(SYMR.strings.page_downloading),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.preloadSize(), pref = readerPreferences.preloadSize(),
title = stringResource(SYMR.strings.reader_preload_amount), title = stringResource(SYMR.strings.reader_preload_amount),
subtitle = stringResource(SYMR.strings.reader_preload_amount_summary), subtitle = stringResource(SYMR.strings.reader_preload_amount_summary),
entries = mapOf( entries = persistentMapOf(
4 to stringResource(SYMR.strings.reader_preload_amount_4_pages), 4 to stringResource(SYMR.strings.reader_preload_amount_4_pages),
6 to stringResource(SYMR.strings.reader_preload_amount_6_pages), 6 to stringResource(SYMR.strings.reader_preload_amount_6_pages),
8 to stringResource(SYMR.strings.reader_preload_amount_8_pages), 8 to stringResource(SYMR.strings.reader_preload_amount_8_pages),
@ -472,13 +481,13 @@ object SettingsReaderScreen : SearchableSettings {
pref = readerPreferences.readerThreads(), pref = readerPreferences.readerThreads(),
title = stringResource(SYMR.strings.download_threads), title = stringResource(SYMR.strings.download_threads),
subtitle = stringResource(SYMR.strings.download_threads_summary), subtitle = stringResource(SYMR.strings.download_threads_summary),
entries = List(5) { it }.associateWith { it.toString() }, entries = List(5) { it }.associateWith { it.toString() }.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.cacheSize(), pref = readerPreferences.cacheSize(),
title = stringResource(SYMR.strings.reader_cache_size), title = stringResource(SYMR.strings.reader_cache_size),
subtitle = stringResource(SYMR.strings.reader_cache_size_summary), subtitle = stringResource(SYMR.strings.reader_cache_size_summary),
entries = mapOf( entries = persistentMapOf(
"50" to "50 MB", "50" to "50 MB",
"75" to "75 MB", "75" to "75 MB",
"100" to "100 MB", "100" to "100 MB",
@ -511,7 +520,7 @@ object SettingsReaderScreen : SearchableSettings {
val pageLayout by readerPreferences.pageLayout().collectAsState() val pageLayout by readerPreferences.pageLayout().collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(SYMR.strings.pref_category_fork), title = stringResource(SYMR.strings.pref_category_fork),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.readerInstantRetry(), pref = readerPreferences.readerInstantRetry(),
title = stringResource(SYMR.strings.skip_queue_on_retry), title = stringResource(SYMR.strings.skip_queue_on_retry),
@ -530,8 +539,9 @@ object SettingsReaderScreen : SearchableSettings {
pref = readerPreferences.readerBottomButtons(), pref = readerPreferences.readerBottomButtons(),
title = stringResource(SYMR.strings.reader_bottom_buttons), title = stringResource(SYMR.strings.reader_bottom_buttons),
subtitle = stringResource(SYMR.strings.reader_bottom_buttons_summary), subtitle = stringResource(SYMR.strings.reader_bottom_buttons_summary),
entries = ReaderBottomButton.values() entries = ReaderBottomButton.entries
.associate { it.value to stringResource(it.stringRes) }, .associate { it.value to stringResource(it.stringRes) }
.toImmutableMap(),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPreferences.pageLayout(), pref = readerPreferences.pageLayout(),
@ -539,7 +549,8 @@ object SettingsReaderScreen : SearchableSettings {
subtitle = stringResource(SYMR.strings.automatic_can_still_switch), subtitle = stringResource(SYMR.strings.automatic_can_still_switch),
entries = ReaderPreferences.PageLayouts entries = ReaderPreferences.PageLayouts
.mapIndexed { index, it -> index + 1 to stringResource(it) } .mapIndexed { index, it -> index + 1 to stringResource(it) }
.toMap(), .toMap()
.toImmutableMap(),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.invertDoublePages(), pref = readerPreferences.invertDoublePages(),
@ -552,7 +563,8 @@ object SettingsReaderScreen : SearchableSettings {
subtitle = stringResource(SYMR.strings.pref_center_margin_summary), subtitle = stringResource(SYMR.strings.pref_center_margin_summary),
entries = ReaderPreferences.CenterMarginTypes entries = ReaderPreferences.CenterMarginTypes
.mapIndexed { index, it -> index + 1 to stringResource(it) } .mapIndexed { index, it -> index + 1 to stringResource(it) }
.toMap(), .toMap()
.toImmutableMap(),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.cacheArchiveMangaOnDisk(), pref = readerPreferences.cacheArchiveMangaOnDisk(),

View File

@ -51,6 +51,8 @@ import eu.kanade.tachiyomi.ui.category.biometric.BiometricTimesScreen
import eu.kanade.tachiyomi.util.storage.CbzCrypto import eu.kanade.tachiyomi.util.storage.CbzCrypto
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableMap
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
@ -101,7 +103,8 @@ object SettingsSecurityScreen : SearchableSettings {
0 -> stringResource(MR.strings.lock_always) 0 -> stringResource(MR.strings.lock_always)
else -> pluralStringResource(MR.plurals.lock_after_mins, count = it, it) else -> pluralStringResource(MR.plurals.lock_after_mins, count = it, it)
} }
}, }
.toImmutableMap(),
onValueChanged = { onValueChanged = {
(context as FragmentActivity).authenticate( (context as FragmentActivity).authenticate(
title = context.stringResource(MR.strings.lock_when_idle), title = context.stringResource(MR.strings.lock_when_idle),
@ -116,7 +119,8 @@ object SettingsSecurityScreen : SearchableSettings {
pref = securityPreferences.secureScreen(), pref = securityPreferences.secureScreen(),
title = stringResource(MR.strings.secure_screen), title = stringResource(MR.strings.secure_screen),
entries = SecurityPreferences.SecureScreenMode.entries entries = SecurityPreferences.SecureScreenMode.entries
.associateWith { stringResource(it.titleRes) }, .associateWith { stringResource(it.titleRes) }
.toImmutableMap(),
), ),
// SY --> // SY -->
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
@ -129,7 +133,8 @@ object SettingsSecurityScreen : SearchableSettings {
pref = securityPreferences.encryptionType(), pref = securityPreferences.encryptionType(),
title = stringResource(SYMR.strings.encryption_type), title = stringResource(SYMR.strings.encryption_type),
entries = SecurityPreferences.EncryptionType.entries entries = SecurityPreferences.EncryptionType.entries
.associateWith { stringResource(it.titleRes) }, .associateWith { stringResource(it.titleRes) }
.toImmutableMap(),
enabled = passwordProtectDownloads, enabled = passwordProtectDownloads,
), ),
@ -358,7 +363,7 @@ object SettingsSecurityScreen : SearchableSettings {
// SY <-- // SY <--
} }
private val LockAfterValues = listOf( private val LockAfterValues = persistentListOf(
0, // Always 0, // Always
1, 1,
2, 2,

View File

@ -51,6 +51,8 @@ import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeListApi
import eu.kanade.tachiyomi.data.track.shikimori.ShikimoriApi import eu.kanade.tachiyomi.data.track.shikimori.ShikimoriApi
import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.launchIO
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.lang.withUIContext
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
@ -125,7 +127,7 @@ object SettingsTrackingScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(MR.strings.services), title = stringResource(MR.strings.services),
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TrackerPreference( Preference.PreferenceItem.TrackerPreference(
title = trackerManager.myAnimeList.name, title = trackerManager.myAnimeList.name,
tracker = trackerManager.myAnimeList, tracker = trackerManager.myAnimeList,
@ -167,7 +169,8 @@ object SettingsTrackingScreen : SearchableSettings {
), ),
Preference.PreferenceGroup( Preference.PreferenceGroup(
title = stringResource(MR.strings.enhanced_services), title = stringResource(MR.strings.enhanced_services),
preferenceItems = enhancedTrackers.first preferenceItems = (
enhancedTrackers.first
.map { service -> .map { service ->
Preference.PreferenceItem.TrackerPreference( Preference.PreferenceItem.TrackerPreference(
title = service.name, title = service.name,
@ -175,7 +178,8 @@ object SettingsTrackingScreen : SearchableSettings {
login = { (service as EnhancedTracker).loginNoop() }, login = { (service as EnhancedTracker).loginNoop() },
logout = service::logout, logout = service::logout,
) )
} + listOf(Preference.PreferenceItem.InfoPreference(enhancedTrackerInfo)), } + listOf(Preference.PreferenceItem.InfoPreference(enhancedTrackerInfo))
).toImmutableList(),
), ),
) )
} }

View File

@ -36,6 +36,7 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.PersistentSet import kotlinx.collections.immutable.PersistentSet
import kotlinx.collections.immutable.minus import kotlinx.collections.immutable.minus
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.plus import kotlinx.collections.immutable.plus
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
@ -175,7 +176,7 @@ private class CreateBackupScreenModel : StateScreenModel<CreateBackupScreenModel
) )
} }
private val BackupChoices = mapOf( private val BackupChoices = persistentMapOf(
BackupCreateFlags.BACKUP_CATEGORY to MR.strings.categories, BackupCreateFlags.BACKUP_CATEGORY to MR.strings.categories,
BackupCreateFlags.BACKUP_CHAPTER to MR.strings.chapters, BackupCreateFlags.BACKUP_CHAPTER to MR.strings.chapters,
BackupCreateFlags.BACKUP_TRACK to MR.strings.track, BackupCreateFlags.BACKUP_TRACK to MR.strings.track,

View File

@ -0,0 +1,117 @@
package eu.kanade.presentation.more.settings.screen.data
import android.text.format.Formatter
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import eu.kanade.tachiyomi.util.storage.DiskUtil
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource
import java.io.File
@Composable
fun StorageInfo(
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val storages = remember { DiskUtil.getExternalStorages(context) }
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
storages.forEach {
StorageInfo(it)
}
}
}
@Composable
private fun StorageInfo(
file: File,
) {
val context = LocalContext.current
val layoutDirection = LocalLayoutDirection.current
val available = remember(file) { DiskUtil.getAvailableStorageSpace(file) }
val availableText = remember(available) { Formatter.formatFileSize(context, available) }
val total = remember(file) { DiskUtil.getTotalStorageSpace(file) }
val totalText = remember(total) { Formatter.formatFileSize(context, total) }
val cornerRadius = CornerRadius(100f, 100f)
val usedBarColor = MaterialTheme.colorScheme.primary
val totalBarColor = MaterialTheme.colorScheme.surfaceVariant
Column(
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
text = file.absolutePath,
fontWeight = FontWeight.Medium,
)
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(12.dp),
) {
drawRoundRect(
color = totalBarColor,
cornerRadius = cornerRadius,
)
drawPath(
path = Path().apply {
val pathSize = Size(
width = (1 - (available / total.toFloat())) * size.width,
height = size.height,
)
addRoundRect(
if (layoutDirection == LayoutDirection.Ltr) {
RoundRect(
rect = Rect(
offset = Offset(0f, 0f),
size = pathSize,
),
topLeft = cornerRadius,
bottomLeft = cornerRadius,
)
} else {
RoundRect(
rect = Rect(
offset = Offset(size.width - pathSize.width, 0f),
size = pathSize,
),
topRight = cornerRadius,
bottomRight = cornerRadius,
)
},
)
},
color = usedBarColor,
)
}
Text(
text = stringResource(MR.strings.available_disk_space_info, availableText, totalText),
)
}
}

View File

@ -15,6 +15,8 @@ import eu.kanade.presentation.more.settings.screen.about.AboutScreen
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.WebViewUtil import eu.kanade.tachiyomi.util.system.WebViewUtil
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.guava.await import kotlinx.coroutines.guava.await
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -47,7 +49,7 @@ class DebugInfoScreen : Screen() {
private fun getAppInfoGroup(): Preference.PreferenceGroup { private fun getAppInfoGroup(): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = "App info", title = "App info",
preferenceItems = listOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = "Version", title = "Version",
subtitle = AboutScreen.getVersionName(false), subtitle = AboutScreen.getVersionName(false),
@ -96,8 +98,8 @@ class DebugInfoScreen : Screen() {
} }
private fun getDeviceInfoGroup(): Preference.PreferenceGroup { private fun getDeviceInfoGroup(): Preference.PreferenceGroup {
val items = buildList { val items = persistentListOf<Preference.PreferenceItem<out Any>>().mutate {
add( it.add(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = "Model", title = "Model",
subtitle = "${Build.MANUFACTURER} ${Build.MODEL} (${Build.DEVICE})", subtitle = "${Build.MANUFACTURER} ${Build.MODEL} (${Build.DEVICE})",
@ -105,14 +107,14 @@ class DebugInfoScreen : Screen() {
) )
if (DeviceUtil.oneUiVersion != null) { if (DeviceUtil.oneUiVersion != null) {
add( it.add(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = "OneUI version", title = "OneUI version",
subtitle = "${DeviceUtil.oneUiVersion}", subtitle = "${DeviceUtil.oneUiVersion}",
), ),
) )
} else if (DeviceUtil.miuiMajorVersion != null) { } else if (DeviceUtil.miuiMajorVersion != null) {
add( it.add(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = "MIUI version", title = "MIUI version",
subtitle = "${DeviceUtil.miuiMajorVersion}", subtitle = "${DeviceUtil.miuiMajorVersion}",
@ -127,7 +129,7 @@ class DebugInfoScreen : Screen() {
} else { } else {
Build.VERSION.RELEASE Build.VERSION.RELEASE
} }
add( it.add(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = "Android version", title = "Android version",
subtitle = "$androidVersion (${Build.DISPLAY})", subtitle = "$androidVersion (${Build.DISPLAY})",

View File

@ -37,6 +37,7 @@ import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.data.database.models.toDomainChapter import eu.kanade.tachiyomi.data.database.models.toDomainChapter
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import kotlinx.collections.immutable.persistentMapOf
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.service.calculateChapterGap import tachiyomi.domain.chapter.service.calculateChapterGap
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -234,7 +235,7 @@ private fun ChapterText(
maxLines = 5, maxLines = 5,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
inlineContent = mapOf( inlineContent = persistentMapOf(
DownloadedIconContentId to InlineTextContent( DownloadedIconContentId to InlineTextContent(
Placeholder( Placeholder(
width = 22.sp, width = 22.sp,

View File

@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiTheme
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.ScrollbarLazyColumn
@ -233,7 +234,7 @@ private fun TrackStatusSelectorPreviews() {
TrackStatusSelector( TrackStatusSelector(
selection = 1, selection = 1,
onSelectionChange = {}, onSelectionChange = {},
selections = mapOf( selections = persistentMapOf(
// Anilist values // Anilist values
1 to MR.strings.reading, 1 to MR.strings.reading,
2 to MR.strings.plan_to_read, 2 to MR.strings.plan_to_read,

View File

@ -21,7 +21,6 @@ import okio.buffer
import okio.sink import okio.sink
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@ -33,15 +32,16 @@ import java.io.IOException
* *
* @param context the application context. * @param context the application context.
*/ */
class ChapterCache(private val context: Context) { class ChapterCache(
private val context: Context,
private val scope = CoroutineScope(Job() + Dispatchers.Main) private val json: Json,
// SY -->
/** Google Json class used for parsing JSON files. */ readerPreferences: ReaderPreferences
private val json: Json by injectLazy() //S Y <--
) {
// --> EH // --> EH
private val readerPreferences: ReaderPreferences by injectLazy() private val scope = CoroutineScope(Job() + Dispatchers.Main)
/** Cache class used for cache management. */ /** Cache class used for cache management. */
private var diskCache = setupDiskCache(readerPreferences.cacheSize().get().toLong()) private var diskCache = setupDiskCache(readerPreferences.cacheSize().get().toLong())

View File

@ -139,7 +139,7 @@ class AppModule(val app: Application) : InjektModule {
ProtoBuf ProtoBuf
} }
addSingletonFactory { ChapterCache(app) } addSingletonFactory { ChapterCache(app, get(), get()) }
addSingletonFactory { CoverCache(app) } addSingletonFactory { CoverCache(app) }
addSingletonFactory { NetworkHelper(app, get(), BuildConfig.DEBUG) } addSingletonFactory { NetworkHelper(app, get(), BuildConfig.DEBUG) }

View File

@ -3,13 +3,32 @@ package eu.kanade.tachiyomi.util.storage
import android.content.Context import android.content.Context
import android.media.MediaScannerConnection import android.media.MediaScannerConnection
import android.net.Uri import android.net.Uri
import android.os.Environment
import android.os.StatFs import android.os.StatFs
import androidx.core.content.ContextCompat
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.util.lang.Hash import eu.kanade.tachiyomi.util.lang.Hash
import java.io.File import java.io.File
object DiskUtil { object DiskUtil {
/**
* Returns the root folders of all the available external storages.
*/
fun getExternalStorages(context: Context): List<File> {
return ContextCompat.getExternalFilesDirs(context, null)
.filterNotNull()
.mapNotNull {
val file = File(it.absolutePath.substringBefore("/Android/"))
val state = Environment.getExternalStorageState(file)
if (state == Environment.MEDIA_MOUNTED || state == Environment.MEDIA_MOUNTED_READ_ONLY) {
file
} else {
null
}
}
}
fun hashKeyForDisk(key: String): String { fun hashKeyForDisk(key: String): String {
return Hash.md5(key) return Hash.md5(key)
} }

View File

@ -519,6 +519,7 @@
<string name="last_auto_backup_info">Last automatically backed up: %s</string> <string name="last_auto_backup_info">Last automatically backed up: %s</string>
<string name="label_data">Data</string> <string name="label_data">Data</string>
<string name="pref_storage_usage">Storage usage</string> <string name="pref_storage_usage">Storage usage</string>
<string name="available_disk_space_info">Available: %1$s / Total: %2$s</string>
<string name="pref_clear_chapter_cache">Clear chapter cache</string> <string name="pref_clear_chapter_cache">Clear chapter cache</string>
<string name="used_cache">Used: %1$s</string> <string name="used_cache">Used: %1$s</string>
<string name="cache_deleted">Cache cleared, %1$d files deleted</string> <string name="cache_deleted">Cache cleared, %1$d files deleted</string>

View File

@ -21,6 +21,7 @@ import androidx.compose.ui.text.PlaceholderVerticalAlign
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.collections.immutable.persistentMapOf
@Composable @Composable
fun BadgeGroup( fun BadgeGroup(
@ -66,7 +67,7 @@ fun Badge(
val text = buildAnnotatedString { val text = buildAnnotatedString {
appendInlineContent(iconContentPlaceholder) appendInlineContent(iconContentPlaceholder)
} }
val inlineContent = mapOf( val inlineContent = persistentMapOf(
Pair( Pair(
iconContentPlaceholder, iconContentPlaceholder,
InlineTextContent( InlineTextContent(