mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Minor settings cleanup
- Fix dark mode setting title - Enforce usages of translated strings for screen titles - Use LocalUriHandler where applicable instead of Android context
This commit is contained in:
		@@ -369,7 +369,7 @@ private fun ExtensionItemActions(
 | 
			
		||||
            IconButton(onClick = { onClickItemCancel(extension) }) {
 | 
			
		||||
                Icon(
 | 
			
		||||
                    imageVector = Icons.Default.Close,
 | 
			
		||||
                    contentDescription = stringResource(id = R.string.action_cancel),
 | 
			
		||||
                    contentDescription = stringResource(R.string.action_cancel),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -88,7 +88,7 @@ fun EmptyScreen(
 | 
			
		||||
                    actions.forEach {
 | 
			
		||||
                        ActionButton(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            title = stringResource(id = it.stringResId),
 | 
			
		||||
                            title = stringResource(it.stringResId),
 | 
			
		||||
                            icon = it.icon,
 | 
			
		||||
                            onClick = it.onClick,
 | 
			
		||||
                        )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.layout.RowScope
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import eu.kanade.presentation.components.AppBar
 | 
			
		||||
import eu.kanade.presentation.components.Scaffold
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun PreferenceScaffold(
 | 
			
		||||
    title: String,
 | 
			
		||||
    @StringRes titleRes: Int,
 | 
			
		||||
    actions: @Composable RowScope.() -> Unit = {},
 | 
			
		||||
    onBackPressed: () -> Unit = {},
 | 
			
		||||
    itemsProvider: @Composable () -> List<Preference>,
 | 
			
		||||
@@ -15,7 +17,7 @@ fun PreferenceScaffold(
 | 
			
		||||
    Scaffold(
 | 
			
		||||
        topBar = { scrollBehavior ->
 | 
			
		||||
            AppBar(
 | 
			
		||||
                title = title,
 | 
			
		||||
                title = stringResource(titleRes),
 | 
			
		||||
                navigateUp = onBackPressed,
 | 
			
		||||
                actions = actions,
 | 
			
		||||
                scrollBehavior = scrollBehavior,
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,6 @@ fun getCategoriesLabel(
 | 
			
		||||
        allExcluded -> stringResource(R.string.all)
 | 
			
		||||
        else -> excludedCategories.joinToString { it.visualName(context) }
 | 
			
		||||
    }
 | 
			
		||||
    return stringResource(id = R.string.include, includedItemsText) + "\n" +
 | 
			
		||||
        stringResource(id = R.string.exclude, excludedItemsText)
 | 
			
		||||
    return stringResource(R.string.include, includedItemsText) + "\n" +
 | 
			
		||||
        stringResource(R.string.exclude, excludedItemsText)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.layout.RowScope
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
@@ -10,9 +11,11 @@ import eu.kanade.presentation.more.settings.PreferenceScaffold
 | 
			
		||||
import eu.kanade.presentation.util.LocalBackPress
 | 
			
		||||
 | 
			
		||||
interface SearchableSettings : Screen {
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    fun getTitle(): String
 | 
			
		||||
    @StringRes
 | 
			
		||||
    fun getTitleRes(): Int
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    fun getPreferences(): List<Preference>
 | 
			
		||||
@@ -25,7 +28,7 @@ interface SearchableSettings : Screen {
 | 
			
		||||
    override fun Content() {
 | 
			
		||||
        val handleBack = LocalBackPress.currentOrThrow
 | 
			
		||||
        PreferenceScaffold(
 | 
			
		||||
            title = getTitle(),
 | 
			
		||||
            titleRes = getTitleRes(),
 | 
			
		||||
            onBackPressed = handleBack::invoke,
 | 
			
		||||
            actions = { AppBarAction() },
 | 
			
		||||
            itemsProvider = { getPreferences() },
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import android.content.Intent
 | 
			
		||||
import android.provider.Settings
 | 
			
		||||
import android.webkit.WebStorage
 | 
			
		||||
import android.webkit.WebView
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.material3.AlertDialog
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.material3.TextButton
 | 
			
		||||
@@ -18,6 +19,7 @@ import androidx.compose.runtime.rememberCoroutineScope
 | 
			
		||||
import androidx.compose.runtime.saveable.rememberSaveable
 | 
			
		||||
import androidx.compose.runtime.setValue
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.platform.LocalUriHandler
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.core.net.toUri
 | 
			
		||||
import cafe.adriel.voyager.navigator.LocalNavigator
 | 
			
		||||
@@ -54,7 +56,6 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.isDevFlavor
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.isPackageInstalled
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.openInBrowser
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.powerManager
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.setDefaultSettings
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toast
 | 
			
		||||
@@ -67,7 +68,8 @@ import java.io.File
 | 
			
		||||
class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_advanced)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_advanced
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -79,13 +81,13 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
        return listOf(
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = basePreferences.acraEnabled(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_enable_acra),
 | 
			
		||||
                subtitle = stringResource(id = R.string.pref_acra_summary),
 | 
			
		||||
                title = stringResource(R.string.pref_enable_acra),
 | 
			
		||||
                subtitle = stringResource(R.string.pref_acra_summary),
 | 
			
		||||
                enabled = !isDevFlavor,
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                title = stringResource(id = R.string.pref_dump_crash_logs),
 | 
			
		||||
                subtitle = stringResource(id = R.string.pref_dump_crash_logs_summary),
 | 
			
		||||
                title = stringResource(R.string.pref_dump_crash_logs),
 | 
			
		||||
                subtitle = stringResource(R.string.pref_dump_crash_logs_summary),
 | 
			
		||||
                onClick = {
 | 
			
		||||
                    scope.launchNonCancellable {
 | 
			
		||||
                        CrashLogUtil(context).dumpLogs()
 | 
			
		||||
@@ -94,8 +96,8 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = networkPreferences.verboseLogging(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_verbose_logging),
 | 
			
		||||
                subtitle = stringResource(id = R.string.pref_verbose_logging_summary),
 | 
			
		||||
                title = stringResource(R.string.pref_verbose_logging),
 | 
			
		||||
                subtitle = stringResource(R.string.pref_verbose_logging_summary),
 | 
			
		||||
                onValueChanged = {
 | 
			
		||||
                    context.toast(R.string.requires_app_restart)
 | 
			
		||||
                    true
 | 
			
		||||
@@ -113,12 +115,14 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
    @Composable
 | 
			
		||||
    private fun getBackgroundActivityGroup(): Preference.PreferenceGroup {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        val uriHandler = LocalUriHandler.current
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.label_background_activity),
 | 
			
		||||
            title = stringResource(R.string.label_background_activity),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_disable_battery_optimization),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_disable_battery_optimization_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_disable_battery_optimization),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_disable_battery_optimization_summary),
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        val packageName: String = context.packageName
 | 
			
		||||
                        if (!context.powerManager.isIgnoringBatteryOptimizations(packageName)) {
 | 
			
		||||
@@ -140,8 +144,8 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = "Don't kill my app!",
 | 
			
		||||
                    subtitle = stringResource(id = R.string.about_dont_kill_my_app),
 | 
			
		||||
                    onClick = { context.openInBrowser("https://dontkillmyapp.com/") },
 | 
			
		||||
                    subtitle = stringResource(R.string.about_dont_kill_my_app),
 | 
			
		||||
                    onClick = { uriHandler.openUri("https://dontkillmyapp.com/") },
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
@@ -159,11 +163,11 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
        val readableSize = remember(readableSizeSema) { chapterCache.readableSize }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.label_data),
 | 
			
		||||
            title = stringResource(R.string.label_data),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_clear_chapter_cache),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.used_cache, readableSize),
 | 
			
		||||
                    title = stringResource(R.string.pref_clear_chapter_cache),
 | 
			
		||||
                    subtitle = stringResource(R.string.used_cache, readableSize),
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        scope.launchNonCancellable {
 | 
			
		||||
                            try {
 | 
			
		||||
@@ -181,11 +185,11 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = libraryPreferences.autoClearChapterCache(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_auto_clear_chapter_cache),
 | 
			
		||||
                    title = stringResource(R.string.pref_auto_clear_chapter_cache),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_clear_database),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_clear_database_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_clear_database),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_clear_database_summary),
 | 
			
		||||
                    onClick = { navigator.push(ClearDatabaseScreen()) },
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
@@ -203,17 +207,17 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
        val userAgent by userAgentPref.collectAsState()
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.label_network),
 | 
			
		||||
            title = stringResource(R.string.label_network),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_clear_cookies),
 | 
			
		||||
                    title = stringResource(R.string.pref_clear_cookies),
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        networkHelper.cookieManager.removeAll()
 | 
			
		||||
                        context.toast(R.string.cookies_cleared)
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_clear_webview_data),
 | 
			
		||||
                    title = stringResource(R.string.pref_clear_webview_data),
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        try {
 | 
			
		||||
                            WebView(context).run {
 | 
			
		||||
@@ -234,9 +238,9 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = networkPreferences.dohProvider(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_dns_over_https),
 | 
			
		||||
                    title = stringResource(R.string.pref_dns_over_https),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        -1 to stringResource(id = R.string.disabled),
 | 
			
		||||
                        -1 to stringResource(R.string.disabled),
 | 
			
		||||
                        PREF_DOH_CLOUDFLARE to "Cloudflare",
 | 
			
		||||
                        PREF_DOH_GOOGLE to "Google",
 | 
			
		||||
                        PREF_DOH_ADGUARD to "AdGuard",
 | 
			
		||||
@@ -256,7 +260,7 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.EditTextPreference(
 | 
			
		||||
                    pref = userAgentPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_user_agent_string),
 | 
			
		||||
                    title = stringResource(R.string.pref_user_agent_string),
 | 
			
		||||
                    onValueChanged = {
 | 
			
		||||
                        if (it.isBlank()) {
 | 
			
		||||
                            context.toast(R.string.error_user_agent_string_blank)
 | 
			
		||||
@@ -267,7 +271,7 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_reset_user_agent_string),
 | 
			
		||||
                    title = stringResource(R.string.pref_reset_user_agent_string),
 | 
			
		||||
                    enabled = remember(userAgent) { userAgent != userAgentPref.defaultValue() },
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        userAgentPref.delete()
 | 
			
		||||
@@ -285,21 +289,21 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
        val trackManager = remember { Injekt.get<TrackManager>() }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.label_library),
 | 
			
		||||
            title = stringResource(R.string.label_library),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_refresh_library_covers),
 | 
			
		||||
                    title = stringResource(R.string.pref_refresh_library_covers),
 | 
			
		||||
                    onClick = { LibraryUpdateService.start(context, target = LibraryUpdateService.Target.COVERS) },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_refresh_library_tracking),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_refresh_library_tracking_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_refresh_library_tracking),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_refresh_library_tracking_summary),
 | 
			
		||||
                    enabled = trackManager.hasLoggedServices(),
 | 
			
		||||
                    onClick = { LibraryUpdateService.start(context, target = LibraryUpdateService.Target.TRACKING) },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_reset_viewer_flags),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_reset_viewer_flags_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_reset_viewer_flags),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_reset_viewer_flags_summary),
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        scope.launchNonCancellable {
 | 
			
		||||
                            val success = Injekt.get<MangaRepository>().resetViewerFlags()
 | 
			
		||||
@@ -323,36 +327,38 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
        basePreferences: BasePreferences,
 | 
			
		||||
    ): Preference.PreferenceGroup {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        val uriHandler = LocalUriHandler.current
 | 
			
		||||
        var shizukuMissing by rememberSaveable { mutableStateOf(false) }
 | 
			
		||||
 | 
			
		||||
        if (shizukuMissing) {
 | 
			
		||||
            val dismiss = { shizukuMissing = false }
 | 
			
		||||
            AlertDialog(
 | 
			
		||||
                onDismissRequest = dismiss,
 | 
			
		||||
                title = { Text(text = stringResource(id = R.string.ext_installer_shizuku)) },
 | 
			
		||||
                text = { Text(text = stringResource(id = R.string.ext_installer_shizuku_unavailable_dialog)) },
 | 
			
		||||
                title = { Text(text = stringResource(R.string.ext_installer_shizuku)) },
 | 
			
		||||
                text = { Text(text = stringResource(R.string.ext_installer_shizuku_unavailable_dialog)) },
 | 
			
		||||
                dismissButton = {
 | 
			
		||||
                    TextButton(onClick = dismiss) {
 | 
			
		||||
                        Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                        Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                confirmButton = {
 | 
			
		||||
                    TextButton(
 | 
			
		||||
                        onClick = {
 | 
			
		||||
                            dismiss()
 | 
			
		||||
                            context.openInBrowser("https://shizuku.rikka.app/download")
 | 
			
		||||
                            uriHandler.openUri("https://shizuku.rikka.app/download")
 | 
			
		||||
                        },
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                        Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.label_extensions),
 | 
			
		||||
            title = stringResource(R.string.label_extensions),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = basePreferences.extensionInstaller(),
 | 
			
		||||
                    title = stringResource(id = R.string.ext_installer_pref),
 | 
			
		||||
                    title = stringResource(R.string.ext_installer_pref),
 | 
			
		||||
                    entries = PreferenceValues.ExtensionInstaller.values()
 | 
			
		||||
                        .run {
 | 
			
		||||
                            if (DeviceUtil.isMiui) {
 | 
			
		||||
@@ -360,7 +366,7 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                            } else {
 | 
			
		||||
                                toList()
 | 
			
		||||
                            }
 | 
			
		||||
                        }.associateWith { stringResource(id = it.titleResId) },
 | 
			
		||||
                        }.associateWith { stringResource(it.titleResId) },
 | 
			
		||||
                    onValueChanged = {
 | 
			
		||||
                        if (it == PreferenceValues.ExtensionInstaller.SHIZUKU &&
 | 
			
		||||
                            !(context.isPackageInstalled("moe.shizuku.privileged.api") || Sui.isSui())
 | 
			
		||||
@@ -381,12 +387,12 @@ class SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        val uiPreferences = remember { Injekt.get<UiPreferences>() }
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_category_display),
 | 
			
		||||
            title = stringResource(R.string.pref_category_display),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = uiPreferences.tabletUiMode(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_tablet_ui_mode),
 | 
			
		||||
                    entries = TabletUiMode.values().associateWith { stringResource(id = it.titleResId) },
 | 
			
		||||
                    title = stringResource(R.string.pref_tablet_ui_mode),
 | 
			
		||||
                    entries = TabletUiMode.values().associateWith { stringResource(it.titleResId) },
 | 
			
		||||
                    onValueChanged = {
 | 
			
		||||
                        context.toast(R.string.requires_app_restart)
 | 
			
		||||
                        true
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
import android.app.Activity
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.LaunchedEffect
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
@@ -28,53 +29,67 @@ class SettingsAppearanceScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_appearance)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_appearance
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        val uiPreferences = remember { Injekt.get<UiPreferences>() }
 | 
			
		||||
 | 
			
		||||
        return listOf(
 | 
			
		||||
            getThemeGroup(context = context, uiPreferences = uiPreferences),
 | 
			
		||||
            getNavigationGroup(context = context, uiPreferences = uiPreferences),
 | 
			
		||||
            getTimestampGroup(uiPreferences = uiPreferences),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    private fun getThemeGroup(
 | 
			
		||||
        context: Context,
 | 
			
		||||
        uiPreferences: UiPreferences,
 | 
			
		||||
    ): Preference.PreferenceGroup {
 | 
			
		||||
        val themeModePref = uiPreferences.themeMode()
 | 
			
		||||
        val themeMode by themeModePref.collectAsState()
 | 
			
		||||
        val appThemePref = uiPreferences.appTheme()
 | 
			
		||||
        val amoledPref = uiPreferences.themeDarkAmoled()
 | 
			
		||||
 | 
			
		||||
        val themeMode by themeModePref.collectAsState()
 | 
			
		||||
 | 
			
		||||
        LaunchedEffect(Unit) {
 | 
			
		||||
            merge(appThemePref.changes(), amoledPref.changes())
 | 
			
		||||
                .drop(2)
 | 
			
		||||
                .collectLatest { (context as? Activity)?.let { ActivityCompat.recreate(it) } }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return listOf(
 | 
			
		||||
            Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                pref = themeModePref,
 | 
			
		||||
                title = stringResource(id = R.string.pref_category_theme),
 | 
			
		||||
                subtitle = "%s",
 | 
			
		||||
                entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 | 
			
		||||
                    mapOf(
 | 
			
		||||
                        ThemeMode.SYSTEM to stringResource(id = R.string.theme_system),
 | 
			
		||||
                        ThemeMode.LIGHT to stringResource(id = R.string.theme_light),
 | 
			
		||||
                        ThemeMode.DARK to stringResource(id = R.string.theme_dark),
 | 
			
		||||
                    )
 | 
			
		||||
                } else {
 | 
			
		||||
                    mapOf(
 | 
			
		||||
                        ThemeMode.LIGHT to stringResource(id = R.string.theme_light),
 | 
			
		||||
                        ThemeMode.DARK to stringResource(id = R.string.theme_dark),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(R.string.pref_category_theme),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = themeModePref,
 | 
			
		||||
                    title = stringResource(R.string.pref_theme_mode),
 | 
			
		||||
                    subtitle = "%s",
 | 
			
		||||
                    entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 | 
			
		||||
                        mapOf(
 | 
			
		||||
                            ThemeMode.SYSTEM to stringResource(R.string.theme_system),
 | 
			
		||||
                            ThemeMode.LIGHT to stringResource(R.string.theme_light),
 | 
			
		||||
                            ThemeMode.DARK to stringResource(R.string.theme_dark),
 | 
			
		||||
                        )
 | 
			
		||||
                    } else {
 | 
			
		||||
                        mapOf(
 | 
			
		||||
                            ThemeMode.LIGHT to stringResource(R.string.theme_light),
 | 
			
		||||
                            ThemeMode.DARK to stringResource(R.string.theme_dark),
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.AppThemePreference(
 | 
			
		||||
                    title = stringResource(R.string.pref_app_theme),
 | 
			
		||||
                    pref = appThemePref,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = amoledPref,
 | 
			
		||||
                    title = stringResource(R.string.pref_dark_theme_pure_black),
 | 
			
		||||
                    enabled = themeMode != ThemeMode.LIGHT,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.AppThemePreference(
 | 
			
		||||
                title = stringResource(id = R.string.pref_app_theme),
 | 
			
		||||
                pref = appThemePref,
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = amoledPref,
 | 
			
		||||
                title = stringResource(id = R.string.pref_dark_theme_pure_black),
 | 
			
		||||
                enabled = themeMode != ThemeMode.LIGHT,
 | 
			
		||||
            ),
 | 
			
		||||
            getNavigationGroup(context = context, uiPreferences = uiPreferences),
 | 
			
		||||
            getTimestampGroup(uiPreferences = uiPreferences),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -84,17 +99,17 @@ class SettingsAppearanceScreen : SearchableSettings {
 | 
			
		||||
        uiPreferences: UiPreferences,
 | 
			
		||||
    ): Preference.PreferenceGroup {
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_category_navigation),
 | 
			
		||||
            title = stringResource(R.string.pref_category_navigation),
 | 
			
		||||
            enabled = remember(context) { context.isTablet() },
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = uiPreferences.sideNavIconAlignment(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_side_nav_icon_alignment),
 | 
			
		||||
                    title = stringResource(R.string.pref_side_nav_icon_alignment),
 | 
			
		||||
                    subtitle = "%s",
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        0 to stringResource(id = R.string.alignment_top),
 | 
			
		||||
                        1 to stringResource(id = R.string.alignment_center),
 | 
			
		||||
                        2 to stringResource(id = R.string.alignment_bottom),
 | 
			
		||||
                        0 to stringResource(R.string.alignment_top),
 | 
			
		||||
                        1 to stringResource(R.string.alignment_center),
 | 
			
		||||
                        2 to stringResource(R.string.alignment_bottom),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
@@ -105,26 +120,26 @@ class SettingsAppearanceScreen : SearchableSettings {
 | 
			
		||||
    private fun getTimestampGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup {
 | 
			
		||||
        val now = remember { Date().time }
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_category_timestamps),
 | 
			
		||||
            title = stringResource(R.string.pref_category_timestamps),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = uiPreferences.relativeTime(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_relative_format),
 | 
			
		||||
                    title = stringResource(R.string.pref_relative_format),
 | 
			
		||||
                    subtitle = "%s",
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        0 to stringResource(id = R.string.off),
 | 
			
		||||
                        2 to stringResource(id = R.string.pref_relative_time_short),
 | 
			
		||||
                        7 to stringResource(id = R.string.pref_relative_time_long),
 | 
			
		||||
                        0 to stringResource(R.string.off),
 | 
			
		||||
                        2 to stringResource(R.string.pref_relative_time_short),
 | 
			
		||||
                        7 to stringResource(R.string.pref_relative_time_long),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = uiPreferences.dateFormat(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_date_format),
 | 
			
		||||
                    title = stringResource(R.string.pref_date_format),
 | 
			
		||||
                    subtitle = "%s",
 | 
			
		||||
                    entries = DateFormats
 | 
			
		||||
                        .associateWith {
 | 
			
		||||
                            val formattedDate = UiPreferences.dateFormat(it).format(now)
 | 
			
		||||
                            "${it.ifEmpty { stringResource(id = R.string.label_default) }} ($formattedDate)"
 | 
			
		||||
                            "${it.ifEmpty { stringResource(R.string.label_default) }} ($formattedDate)"
 | 
			
		||||
                        },
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import android.net.Uri
 | 
			
		||||
import android.widget.Toast
 | 
			
		||||
import androidx.activity.compose.rememberLauncherForActivityResult
 | 
			
		||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.clickable
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
@@ -53,9 +54,11 @@ import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.label_backup)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.label_backup
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -110,8 +113,8 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceItem.TextPreference(
 | 
			
		||||
            title = stringResource(id = R.string.pref_create_backup),
 | 
			
		||||
            subtitle = stringResource(id = R.string.pref_create_backup_summ),
 | 
			
		||||
            title = stringResource(R.string.pref_create_backup),
 | 
			
		||||
            subtitle = stringResource(R.string.pref_create_backup_summ),
 | 
			
		||||
            onClick = {
 | 
			
		||||
                scope.launch {
 | 
			
		||||
                    if (!BackupCreatorJob.isManualJobRunning(context)) {
 | 
			
		||||
@@ -135,7 +138,7 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
        val flags = remember { mutableStateListOf<Int>() }
 | 
			
		||||
        AlertDialog(
 | 
			
		||||
            onDismissRequest = onDismissRequest,
 | 
			
		||||
            title = { Text(text = stringResource(id = R.string.backup_choice)) },
 | 
			
		||||
            title = { Text(text = stringResource(R.string.backup_choice)) },
 | 
			
		||||
            text = {
 | 
			
		||||
                val choices = remember {
 | 
			
		||||
                    mapOf(
 | 
			
		||||
@@ -148,13 +151,13 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                Column {
 | 
			
		||||
                    CreateBackupDialogItem(
 | 
			
		||||
                        isSelected = true,
 | 
			
		||||
                        title = stringResource(id = R.string.manga),
 | 
			
		||||
                        title = stringResource(R.string.manga),
 | 
			
		||||
                    )
 | 
			
		||||
                    choices.forEach { (k, v) ->
 | 
			
		||||
                        val isSelected = flags.contains(k)
 | 
			
		||||
                        CreateBackupDialogItem(
 | 
			
		||||
                            isSelected = isSelected,
 | 
			
		||||
                            title = stringResource(id = v),
 | 
			
		||||
                            title = stringResource(v),
 | 
			
		||||
                            modifier = Modifier.clickable {
 | 
			
		||||
                                if (isSelected) {
 | 
			
		||||
                                    flags.remove(k)
 | 
			
		||||
@@ -168,7 +171,7 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
            },
 | 
			
		||||
            dismissButton = {
 | 
			
		||||
                TextButton(onClick = onDismissRequest) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            confirmButton = {
 | 
			
		||||
@@ -178,7 +181,7 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                        onConfirm(flag)
 | 
			
		||||
                    },
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
@@ -218,7 +221,7 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                    val clipboard = LocalClipboardManager.current
 | 
			
		||||
                    AlertDialog(
 | 
			
		||||
                        onDismissRequest = onDismissRequest,
 | 
			
		||||
                        title = { Text(text = stringResource(id = R.string.invalid_backup_file)) },
 | 
			
		||||
                        title = { Text(text = stringResource(R.string.invalid_backup_file)) },
 | 
			
		||||
                        text = { Text(text = err.message) },
 | 
			
		||||
                        dismissButton = {
 | 
			
		||||
                            TextButton(
 | 
			
		||||
@@ -228,12 +231,12 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                                    onDismissRequest()
 | 
			
		||||
                                },
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Text(text = stringResource(id = R.string.copy))
 | 
			
		||||
                                Text(text = stringResource(R.string.copy))
 | 
			
		||||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                        confirmButton = {
 | 
			
		||||
                            TextButton(onClick = onDismissRequest) {
 | 
			
		||||
                                Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                                Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                    )
 | 
			
		||||
@@ -241,9 +244,9 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                is MissingRestoreComponents -> {
 | 
			
		||||
                    AlertDialog(
 | 
			
		||||
                        onDismissRequest = onDismissRequest,
 | 
			
		||||
                        title = { Text(text = stringResource(id = R.string.pref_restore_backup)) },
 | 
			
		||||
                        title = { Text(text = stringResource(R.string.pref_restore_backup)) },
 | 
			
		||||
                        text = {
 | 
			
		||||
                            var msg = stringResource(id = R.string.backup_restore_content_full)
 | 
			
		||||
                            var msg = stringResource(R.string.backup_restore_content_full)
 | 
			
		||||
                            if (err.sources.isNotEmpty()) {
 | 
			
		||||
                                msg += "\n\n${stringResource(R.string.backup_restore_missing_sources)}\n${err.sources.joinToString("\n") { "- $it" }}"
 | 
			
		||||
                            }
 | 
			
		||||
@@ -259,7 +262,7 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                                    onDismissRequest()
 | 
			
		||||
                                },
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Text(text = stringResource(id = R.string.action_restore))
 | 
			
		||||
                                Text(text = stringResource(R.string.action_restore))
 | 
			
		||||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                    )
 | 
			
		||||
@@ -287,8 +290,8 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceItem.TextPreference(
 | 
			
		||||
            title = stringResource(id = R.string.pref_restore_backup),
 | 
			
		||||
            subtitle = stringResource(id = R.string.pref_restore_backup_summ),
 | 
			
		||||
            title = stringResource(R.string.pref_restore_backup),
 | 
			
		||||
            subtitle = stringResource(R.string.pref_restore_backup_summ),
 | 
			
		||||
            onClick = {
 | 
			
		||||
                if (!BackupRestoreService.isRunning(context)) {
 | 
			
		||||
                    if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
 | 
			
		||||
@@ -324,17 +327,17 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_backup_service_category),
 | 
			
		||||
            title = stringResource(R.string.pref_backup_service_category),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = backupPreferences.backupInterval(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_backup_interval),
 | 
			
		||||
                    title = stringResource(R.string.pref_backup_interval),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        6 to stringResource(id = R.string.update_6hour),
 | 
			
		||||
                        12 to stringResource(id = R.string.update_12hour),
 | 
			
		||||
                        24 to stringResource(id = R.string.update_24hour),
 | 
			
		||||
                        48 to stringResource(id = R.string.update_48hour),
 | 
			
		||||
                        168 to stringResource(id = R.string.update_weekly),
 | 
			
		||||
                        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 = {
 | 
			
		||||
                        BackupCreatorJob.setupTask(context, it)
 | 
			
		||||
@@ -342,7 +345,7 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.pref_backup_directory),
 | 
			
		||||
                    title = stringResource(R.string.pref_backup_directory),
 | 
			
		||||
                    subtitle = remember(backupDir) {
 | 
			
		||||
                        UniFile.fromUri(context, backupDir.toUri()).filePath!! + "/automatic"
 | 
			
		||||
                    },
 | 
			
		||||
@@ -350,10 +353,10 @@ class SettingsBackupScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = backupPreferences.numberOfBackups(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_backup_slots),
 | 
			
		||||
                    title = stringResource(R.string.pref_backup_slots),
 | 
			
		||||
                    entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.infoPreference(stringResource(id = R.string.backup_info)),
 | 
			
		||||
                Preference.infoPreference(stringResource(R.string.backup_info)),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
@@ -16,9 +17,11 @@ import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class SettingsBrowseScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.browse)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.browse
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -27,21 +30,21 @@ class SettingsBrowseScreen : SearchableSettings {
 | 
			
		||||
        val preferences = remember { Injekt.get<BasePreferences>() }
 | 
			
		||||
        return listOf(
 | 
			
		||||
            Preference.PreferenceGroup(
 | 
			
		||||
                title = stringResource(id = R.string.label_sources),
 | 
			
		||||
                title = stringResource(R.string.label_sources),
 | 
			
		||||
                preferenceItems = listOf(
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = sourcePreferences.duplicatePinnedSources(),
 | 
			
		||||
                        title = stringResource(id = R.string.pref_duplicate_pinned_sources),
 | 
			
		||||
                        subtitle = stringResource(id = R.string.pref_duplicate_pinned_sources_summary),
 | 
			
		||||
                        title = stringResource(R.string.pref_duplicate_pinned_sources),
 | 
			
		||||
                        subtitle = stringResource(R.string.pref_duplicate_pinned_sources_summary),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceGroup(
 | 
			
		||||
                title = stringResource(id = R.string.label_extensions),
 | 
			
		||||
                title = stringResource(R.string.label_extensions),
 | 
			
		||||
                preferenceItems = listOf(
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = preferences.automaticExtUpdates(),
 | 
			
		||||
                        title = stringResource(id = R.string.pref_enable_automatic_extension_updates),
 | 
			
		||||
                        title = stringResource(R.string.pref_enable_automatic_extension_updates),
 | 
			
		||||
                        onValueChanged = {
 | 
			
		||||
                            ExtensionUpdateJob.setupTask(context, it)
 | 
			
		||||
                            true
 | 
			
		||||
@@ -50,28 +53,28 @@ class SettingsBrowseScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceGroup(
 | 
			
		||||
                title = stringResource(id = R.string.action_global_search),
 | 
			
		||||
                title = stringResource(R.string.action_global_search),
 | 
			
		||||
                preferenceItems = listOf(
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = sourcePreferences.searchPinnedSourcesOnly(),
 | 
			
		||||
                        title = stringResource(id = R.string.pref_search_pinned_sources_only),
 | 
			
		||||
                        title = stringResource(R.string.pref_search_pinned_sources_only),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceGroup(
 | 
			
		||||
                title = stringResource(id = R.string.pref_category_nsfw_content),
 | 
			
		||||
                title = stringResource(R.string.pref_category_nsfw_content),
 | 
			
		||||
                preferenceItems = listOf(
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = sourcePreferences.showNsfwSource(),
 | 
			
		||||
                        title = stringResource(id = R.string.pref_show_nsfw_source),
 | 
			
		||||
                        subtitle = stringResource(id = R.string.requires_app_restart),
 | 
			
		||||
                        title = stringResource(R.string.pref_show_nsfw_source),
 | 
			
		||||
                        subtitle = stringResource(R.string.requires_app_restart),
 | 
			
		||||
                        onValueChanged = {
 | 
			
		||||
                            (context as FragmentActivity).authenticate(
 | 
			
		||||
                                title = context.getString(R.string.pref_category_nsfw_content),
 | 
			
		||||
                            )
 | 
			
		||||
                        },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.infoPreference(stringResource(id = R.string.parental_controls_info)),
 | 
			
		||||
                    Preference.infoPreference(stringResource(R.string.parental_controls_info)),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import android.content.Intent
 | 
			
		||||
import android.os.Environment
 | 
			
		||||
import androidx.activity.compose.rememberLauncherForActivityResult
 | 
			
		||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
@@ -33,9 +34,11 @@ import uy.kohesive.injekt.api.get
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_downloads)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_downloads
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -47,16 +50,16 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
            getDownloadLocationPreference(downloadPreferences = downloadPreferences),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = downloadPreferences.downloadOnlyOverWifi(),
 | 
			
		||||
                title = stringResource(id = R.string.connected_to_wifi),
 | 
			
		||||
                title = stringResource(R.string.connected_to_wifi),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = downloadPreferences.saveChaptersAsCBZ(),
 | 
			
		||||
                title = stringResource(id = R.string.save_chapter_as_cbz),
 | 
			
		||||
                title = stringResource(R.string.save_chapter_as_cbz),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = downloadPreferences.splitTallImages(),
 | 
			
		||||
                title = stringResource(id = R.string.split_tall_images),
 | 
			
		||||
                subtitle = stringResource(id = R.string.split_tall_images_summary),
 | 
			
		||||
                title = stringResource(R.string.split_tall_images),
 | 
			
		||||
                subtitle = stringResource(R.string.split_tall_images_summary),
 | 
			
		||||
            ),
 | 
			
		||||
            getDeleteChaptersGroup(
 | 
			
		||||
                downloadPreferences = downloadPreferences,
 | 
			
		||||
@@ -97,13 +100,13 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceItem.ListPreference(
 | 
			
		||||
            pref = currentDirPref,
 | 
			
		||||
            title = stringResource(id = R.string.pref_download_directory),
 | 
			
		||||
            title = stringResource(R.string.pref_download_directory),
 | 
			
		||||
            subtitle = remember(currentDir) {
 | 
			
		||||
                UniFile.fromUri(context, currentDir.toUri()).filePath!!
 | 
			
		||||
            },
 | 
			
		||||
            entries = mapOf(
 | 
			
		||||
                defaultDirPair,
 | 
			
		||||
                customDirEntryKey to stringResource(id = R.string.custom_dir),
 | 
			
		||||
                customDirEntryKey to stringResource(R.string.custom_dir),
 | 
			
		||||
            ),
 | 
			
		||||
            onValueChanged = {
 | 
			
		||||
                val default = it == defaultDirPair.first
 | 
			
		||||
@@ -117,7 +120,7 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    private fun rememberDefaultDownloadDir(): Pair<String, String> {
 | 
			
		||||
        val appName = stringResource(id = R.string.app_name)
 | 
			
		||||
        val appName = stringResource(R.string.app_name)
 | 
			
		||||
        return remember {
 | 
			
		||||
            val file = UniFile.fromFile(
 | 
			
		||||
                File(
 | 
			
		||||
@@ -135,27 +138,27 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
        categories: List<Category>,
 | 
			
		||||
    ): Preference.PreferenceGroup {
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_category_delete_chapters),
 | 
			
		||||
            title = stringResource(R.string.pref_category_delete_chapters),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = downloadPreferences.removeAfterMarkedAsRead(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_remove_after_marked_as_read),
 | 
			
		||||
                    title = stringResource(R.string.pref_remove_after_marked_as_read),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = downloadPreferences.removeAfterReadSlots(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_remove_after_read),
 | 
			
		||||
                    title = stringResource(R.string.pref_remove_after_read),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        -1 to stringResource(id = R.string.disabled),
 | 
			
		||||
                        0 to stringResource(id = R.string.last_read_chapter),
 | 
			
		||||
                        1 to stringResource(id = R.string.second_to_last),
 | 
			
		||||
                        2 to stringResource(id = R.string.third_to_last),
 | 
			
		||||
                        3 to stringResource(id = R.string.fourth_to_last),
 | 
			
		||||
                        4 to stringResource(id = R.string.fifth_to_last),
 | 
			
		||||
                        -1 to stringResource(R.string.disabled),
 | 
			
		||||
                        0 to stringResource(R.string.last_read_chapter),
 | 
			
		||||
                        1 to stringResource(R.string.second_to_last),
 | 
			
		||||
                        2 to stringResource(R.string.third_to_last),
 | 
			
		||||
                        3 to stringResource(R.string.fourth_to_last),
 | 
			
		||||
                        4 to stringResource(R.string.fifth_to_last),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = downloadPreferences.removeBookmarkedChapters(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_remove_bookmarked_chapters),
 | 
			
		||||
                    title = stringResource(R.string.pref_remove_bookmarked_chapters),
 | 
			
		||||
                ),
 | 
			
		||||
                getExcludedCategoriesPreference(
 | 
			
		||||
                    downloadPreferences = downloadPreferences,
 | 
			
		||||
@@ -170,7 +173,7 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
        downloadPreferences: DownloadPreferences,
 | 
			
		||||
        categories: () -> List<Category>,
 | 
			
		||||
    ): Preference.PreferenceItem.MultiSelectListPreference {
 | 
			
		||||
        val none = stringResource(id = R.string.none)
 | 
			
		||||
        val none = stringResource(R.string.none)
 | 
			
		||||
        val pref = downloadPreferences.removeExcludeCategories()
 | 
			
		||||
        val entries = categories().associate { it.id.toString() to it.visualName }
 | 
			
		||||
        val subtitle by produceState(initialValue = "") {
 | 
			
		||||
@@ -186,7 +189,7 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
        }
 | 
			
		||||
        return Preference.PreferenceItem.MultiSelectListPreference(
 | 
			
		||||
            pref = pref,
 | 
			
		||||
            title = stringResource(id = R.string.pref_remove_exclude_categories),
 | 
			
		||||
            title = stringResource(R.string.pref_remove_exclude_categories),
 | 
			
		||||
            subtitle = subtitle,
 | 
			
		||||
            entries = entries,
 | 
			
		||||
        )
 | 
			
		||||
@@ -208,8 +211,8 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
        var showDialog by rememberSaveable { mutableStateOf(false) }
 | 
			
		||||
        if (showDialog) {
 | 
			
		||||
            TriStateListDialog(
 | 
			
		||||
                title = stringResource(id = R.string.categories),
 | 
			
		||||
                message = stringResource(id = R.string.pref_download_new_categories_details),
 | 
			
		||||
                title = stringResource(R.string.categories),
 | 
			
		||||
                message = stringResource(R.string.pref_download_new_categories_details),
 | 
			
		||||
                items = allCategories,
 | 
			
		||||
                initialChecked = included.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
 | 
			
		||||
                initialInversed = excluded.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
 | 
			
		||||
@@ -224,14 +227,14 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_download_new),
 | 
			
		||||
            title = stringResource(R.string.pref_download_new),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = downloadNewChaptersPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_download_new),
 | 
			
		||||
                    title = stringResource(R.string.pref_download_new),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.categories),
 | 
			
		||||
                    title = stringResource(R.string.categories),
 | 
			
		||||
                    subtitle = getCategoriesLabel(
 | 
			
		||||
                        allCategories = allCategories,
 | 
			
		||||
                        included = included,
 | 
			
		||||
@@ -249,20 +252,20 @@ class SettingsDownloadScreen : SearchableSettings {
 | 
			
		||||
        downloadPreferences: DownloadPreferences,
 | 
			
		||||
    ): Preference.PreferenceGroup {
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.download_ahead),
 | 
			
		||||
            title = stringResource(R.string.download_ahead),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = downloadPreferences.autoDownloadWhileReading(),
 | 
			
		||||
                    title = stringResource(id = R.string.auto_download_while_reading),
 | 
			
		||||
                    title = stringResource(R.string.auto_download_while_reading),
 | 
			
		||||
                    entries = listOf(0, 2, 3, 5, 10).associateWith {
 | 
			
		||||
                        if (it == 0) {
 | 
			
		||||
                            stringResource(id = R.string.disabled)
 | 
			
		||||
                            stringResource(R.string.disabled)
 | 
			
		||||
                        } else {
 | 
			
		||||
                            pluralStringResource(id = R.plurals.next_unread_chapters, count = it, it)
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.infoPreference(stringResource(id = R.string.download_ahead_info)),
 | 
			
		||||
                Preference.infoPreference(stringResource(R.string.download_ahead_info)),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.provider.Settings
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.appcompat.app.AppCompatDelegate
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
@@ -21,9 +22,11 @@ import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class SettingsGeneralScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_general)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_general
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -33,14 +36,14 @@ class SettingsGeneralScreen : SearchableSettings {
 | 
			
		||||
            add(
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = libraryPrefs.showUpdatesNavBadge(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_library_update_show_tab_badge),
 | 
			
		||||
                    title = stringResource(R.string.pref_library_update_show_tab_badge),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            add(
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = prefs.confirmExit(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_confirm_exit),
 | 
			
		||||
                    title = stringResource(R.string.pref_confirm_exit),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +51,7 @@ class SettingsGeneralScreen : SearchableSettings {
 | 
			
		||||
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 | 
			
		||||
                add(
 | 
			
		||||
                    Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                        title = stringResource(id = R.string.pref_manage_notifications),
 | 
			
		||||
                        title = stringResource(R.string.pref_manage_notifications),
 | 
			
		||||
                        onClick = {
 | 
			
		||||
                            val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
 | 
			
		||||
                                putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
 | 
			
		||||
@@ -64,7 +67,7 @@ class SettingsGeneralScreen : SearchableSettings {
 | 
			
		||||
            add(
 | 
			
		||||
                Preference.PreferenceItem.BasicListPreference(
 | 
			
		||||
                    value = currentLanguage,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_app_language),
 | 
			
		||||
                    title = stringResource(R.string.pref_app_language),
 | 
			
		||||
                    subtitle = "%s",
 | 
			
		||||
                    entries = langs,
 | 
			
		||||
                    onValueChanged = { newValue ->
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
@@ -58,7 +59,8 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_library)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_library
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -123,14 +125,14 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
        // For default category
 | 
			
		||||
        val ids = listOf(libraryPreferences.defaultCategory().defaultValue()) +
 | 
			
		||||
            allCategories.map { it.id.toInt() }
 | 
			
		||||
        val labels = listOf(stringResource(id = R.string.default_category_summary)) +
 | 
			
		||||
        val labels = listOf(stringResource(R.string.default_category_summary)) +
 | 
			
		||||
            allCategories.map { it.visualName(context) }
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.categories),
 | 
			
		||||
            title = stringResource(R.string.categories),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.action_edit_categories),
 | 
			
		||||
                    title = stringResource(R.string.action_edit_categories),
 | 
			
		||||
                    subtitle = pluralStringResource(
 | 
			
		||||
                        id = R.plurals.num_categories,
 | 
			
		||||
                        count = userCategoriesCount,
 | 
			
		||||
@@ -140,13 +142,13 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = libraryPreferences.defaultCategory(),
 | 
			
		||||
                    title = stringResource(id = R.string.default_category),
 | 
			
		||||
                    subtitle = selectedCategory?.visualName ?: stringResource(id = R.string.default_category_summary),
 | 
			
		||||
                    title = stringResource(R.string.default_category),
 | 
			
		||||
                    subtitle = selectedCategory?.visualName ?: stringResource(R.string.default_category_summary),
 | 
			
		||||
                    entries = ids.zip(labels).toMap(),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = libraryPreferences.categorizedDisplaySettings(),
 | 
			
		||||
                    title = stringResource(id = R.string.categorized_display_settings),
 | 
			
		||||
                    title = stringResource(R.string.categorized_display_settings),
 | 
			
		||||
                    onValueChanged = {
 | 
			
		||||
                        if (!it) {
 | 
			
		||||
                            scope.launch {
 | 
			
		||||
@@ -176,34 +178,34 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
        val libraryUpdateInterval by libraryUpdateIntervalPref.collectAsState()
 | 
			
		||||
 | 
			
		||||
        val deviceRestrictionEntries = mapOf(
 | 
			
		||||
            DEVICE_ONLY_ON_WIFI to stringResource(id = R.string.connected_to_wifi),
 | 
			
		||||
            DEVICE_NETWORK_NOT_METERED to stringResource(id = R.string.network_not_metered),
 | 
			
		||||
            DEVICE_CHARGING to stringResource(id = R.string.charging),
 | 
			
		||||
            DEVICE_BATTERY_NOT_LOW to stringResource(id = R.string.battery_not_low),
 | 
			
		||||
            DEVICE_ONLY_ON_WIFI to stringResource(R.string.connected_to_wifi),
 | 
			
		||||
            DEVICE_NETWORK_NOT_METERED to stringResource(R.string.network_not_metered),
 | 
			
		||||
            DEVICE_CHARGING to stringResource(R.string.charging),
 | 
			
		||||
            DEVICE_BATTERY_NOT_LOW to stringResource(R.string.battery_not_low),
 | 
			
		||||
        )
 | 
			
		||||
        val deviceRestrictions = libraryUpdateDeviceRestrictionPref.collectAsState()
 | 
			
		||||
            .value
 | 
			
		||||
            .sorted()
 | 
			
		||||
            .map { deviceRestrictionEntries.getOrElse(it) { it } }
 | 
			
		||||
            .let { if (it.isEmpty()) stringResource(id = R.string.none) else it.joinToString() }
 | 
			
		||||
            .let { if (it.isEmpty()) stringResource(R.string.none) else it.joinToString() }
 | 
			
		||||
 | 
			
		||||
        val mangaRestrictionEntries = mapOf(
 | 
			
		||||
            MANGA_HAS_UNREAD to stringResource(id = R.string.pref_update_only_completely_read),
 | 
			
		||||
            MANGA_NON_READ to stringResource(id = R.string.pref_update_only_started),
 | 
			
		||||
            MANGA_NON_COMPLETED to stringResource(id = R.string.pref_update_only_non_completed),
 | 
			
		||||
            MANGA_HAS_UNREAD to stringResource(R.string.pref_update_only_completely_read),
 | 
			
		||||
            MANGA_NON_READ to stringResource(R.string.pref_update_only_started),
 | 
			
		||||
            MANGA_NON_COMPLETED to stringResource(R.string.pref_update_only_non_completed),
 | 
			
		||||
        )
 | 
			
		||||
        val mangaRestrictions = libraryUpdateMangaRestrictionPref.collectAsState()
 | 
			
		||||
            .value
 | 
			
		||||
            .map { mangaRestrictionEntries.getOrElse(it) { it } }
 | 
			
		||||
            .let { if (it.isEmpty()) stringResource(id = R.string.none) else it.joinToString() }
 | 
			
		||||
            .let { if (it.isEmpty()) stringResource(R.string.none) else it.joinToString() }
 | 
			
		||||
 | 
			
		||||
        val included by libraryUpdateCategoriesPref.collectAsState()
 | 
			
		||||
        val excluded by libraryUpdateCategoriesExcludePref.collectAsState()
 | 
			
		||||
        var showDialog by rememberSaveable { mutableStateOf(false) }
 | 
			
		||||
        if (showDialog) {
 | 
			
		||||
            TriStateListDialog(
 | 
			
		||||
                title = stringResource(id = R.string.categories),
 | 
			
		||||
                message = stringResource(id = R.string.pref_library_update_categories_details),
 | 
			
		||||
                title = stringResource(R.string.categories),
 | 
			
		||||
                message = stringResource(R.string.pref_library_update_categories_details),
 | 
			
		||||
                items = allCategories,
 | 
			
		||||
                initialChecked = included.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
 | 
			
		||||
                initialInversed = excluded.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
 | 
			
		||||
@@ -217,19 +219,19 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_category_library_update),
 | 
			
		||||
            title = stringResource(R.string.pref_category_library_update),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = libraryUpdateIntervalPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_library_update_interval),
 | 
			
		||||
                    title = stringResource(R.string.pref_library_update_interval),
 | 
			
		||||
                    subtitle = "%s",
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        0 to stringResource(id = R.string.update_never),
 | 
			
		||||
                        12 to stringResource(id = R.string.update_12hour),
 | 
			
		||||
                        24 to stringResource(id = R.string.update_24hour),
 | 
			
		||||
                        48 to stringResource(id = R.string.update_48hour),
 | 
			
		||||
                        72 to stringResource(id = R.string.update_72hour),
 | 
			
		||||
                        168 to stringResource(id = R.string.update_weekly),
 | 
			
		||||
                        0 to stringResource(R.string.update_never),
 | 
			
		||||
                        12 to stringResource(R.string.update_12hour),
 | 
			
		||||
                        24 to stringResource(R.string.update_24hour),
 | 
			
		||||
                        48 to stringResource(R.string.update_48hour),
 | 
			
		||||
                        72 to stringResource(R.string.update_72hour),
 | 
			
		||||
                        168 to stringResource(R.string.update_weekly),
 | 
			
		||||
                    ),
 | 
			
		||||
                    onValueChanged = {
 | 
			
		||||
                        LibraryUpdateJob.setupTask(context, it)
 | 
			
		||||
@@ -239,8 +241,8 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
                Preference.PreferenceItem.MultiSelectListPreference(
 | 
			
		||||
                    pref = libraryUpdateDeviceRestrictionPref,
 | 
			
		||||
                    enabled = libraryUpdateInterval > 0,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_library_update_restriction),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.restrictions, deviceRestrictions),
 | 
			
		||||
                    title = stringResource(R.string.pref_library_update_restriction),
 | 
			
		||||
                    subtitle = stringResource(R.string.restrictions, deviceRestrictions),
 | 
			
		||||
                    entries = deviceRestrictionEntries,
 | 
			
		||||
                    onValueChanged = {
 | 
			
		||||
                        // Post to event looper to allow the preference to be updated.
 | 
			
		||||
@@ -250,12 +252,12 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.MultiSelectListPreference(
 | 
			
		||||
                    pref = libraryUpdateMangaRestrictionPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_library_update_manga_restriction),
 | 
			
		||||
                    title = stringResource(R.string.pref_library_update_manga_restriction),
 | 
			
		||||
                    subtitle = mangaRestrictions,
 | 
			
		||||
                    entries = mangaRestrictionEntries,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(id = R.string.categories),
 | 
			
		||||
                    title = stringResource(R.string.categories),
 | 
			
		||||
                    subtitle = getCategoriesLabel(
 | 
			
		||||
                        allCategories = allCategories,
 | 
			
		||||
                        included = included,
 | 
			
		||||
@@ -265,14 +267,14 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = libraryPreferences.autoUpdateMetadata(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_library_update_refresh_metadata),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_library_update_refresh_metadata_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_library_update_refresh_metadata),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_library_update_refresh_metadata_summary),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = libraryPreferences.autoUpdateTrackers(),
 | 
			
		||||
                    enabled = Injekt.get<TrackManager>().hasLoggedServices(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_library_update_refresh_trackers),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_library_update_refresh_trackers_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_library_update_refresh_trackers),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
@@ -291,7 +293,7 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
        AlertDialog(
 | 
			
		||||
            onDismissRequest = onDismissRequest,
 | 
			
		||||
            title = { Text(text = stringResource(id = R.string.pref_library_columns)) },
 | 
			
		||||
            title = { Text(text = stringResource(R.string.pref_library_columns)) },
 | 
			
		||||
            text = {
 | 
			
		||||
                Row {
 | 
			
		||||
                    Column(
 | 
			
		||||
@@ -299,7 +301,7 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
                        horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(
 | 
			
		||||
                            text = stringResource(id = R.string.portrait),
 | 
			
		||||
                            text = stringResource(R.string.portrait),
 | 
			
		||||
                            style = MaterialTheme.typography.labelMedium,
 | 
			
		||||
                        )
 | 
			
		||||
                        NumberPicker(
 | 
			
		||||
@@ -320,7 +322,7 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
                        horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(
 | 
			
		||||
                            text = stringResource(id = R.string.landscape),
 | 
			
		||||
                            text = stringResource(R.string.landscape),
 | 
			
		||||
                            style = MaterialTheme.typography.labelMedium,
 | 
			
		||||
                        )
 | 
			
		||||
                        NumberPicker(
 | 
			
		||||
@@ -339,12 +341,12 @@ class SettingsLibraryScreen : SearchableSettings {
 | 
			
		||||
            },
 | 
			
		||||
            dismissButton = {
 | 
			
		||||
                TextButton(onClick = onDismissRequest) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            confirmButton = {
 | 
			
		||||
                TextButton(onClick = { onValueChanged(portraitValue, landscapeValue) }) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.material.icons.Icons
 | 
			
		||||
import androidx.compose.material.icons.outlined.ChromeReaderMode
 | 
			
		||||
import androidx.compose.material.icons.outlined.Code
 | 
			
		||||
@@ -26,9 +27,11 @@ import eu.kanade.presentation.util.LocalBackPress
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
 | 
			
		||||
object SettingsMainScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.label_settings)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.label_settings
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    @NonRestartableComposable
 | 
			
		||||
@@ -93,7 +96,7 @@ object SettingsMainScreen : SearchableSettings {
 | 
			
		||||
        val navigator = LocalNavigator.currentOrThrow
 | 
			
		||||
        val backPress = LocalBackPress.currentOrThrow
 | 
			
		||||
        PreferenceScaffold(
 | 
			
		||||
            title = getTitle(),
 | 
			
		||||
            titleRes = getTitleRes(),
 | 
			
		||||
            actions = {
 | 
			
		||||
                AppBarActions(
 | 
			
		||||
                    listOf(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
@@ -20,9 +21,11 @@ import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_reader)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_reader
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -30,38 +33,38 @@ class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
        return listOf(
 | 
			
		||||
            Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                pref = readerPref.defaultReadingMode(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_viewer_type),
 | 
			
		||||
                title = stringResource(R.string.pref_viewer_type),
 | 
			
		||||
                entries = ReadingModeType.values().drop(1)
 | 
			
		||||
                    .associate { it.flagValue to stringResource(id = it.stringRes) },
 | 
			
		||||
                    .associate { it.flagValue to stringResource(it.stringRes) },
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                pref = readerPref.doubleTapAnimSpeed(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_double_tap_anim_speed),
 | 
			
		||||
                title = stringResource(R.string.pref_double_tap_anim_speed),
 | 
			
		||||
                entries = mapOf(
 | 
			
		||||
                    1 to stringResource(id = R.string.double_tap_anim_speed_0),
 | 
			
		||||
                    500 to stringResource(id = R.string.double_tap_anim_speed_normal),
 | 
			
		||||
                    250 to stringResource(id = R.string.double_tap_anim_speed_fast),
 | 
			
		||||
                    1 to stringResource(R.string.double_tap_anim_speed_0),
 | 
			
		||||
                    500 to stringResource(R.string.double_tap_anim_speed_normal),
 | 
			
		||||
                    250 to stringResource(R.string.double_tap_anim_speed_fast),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = readerPref.showReadingMode(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_show_reading_mode),
 | 
			
		||||
                subtitle = stringResource(id = R.string.pref_show_reading_mode_summary),
 | 
			
		||||
                title = stringResource(R.string.pref_show_reading_mode),
 | 
			
		||||
                subtitle = stringResource(R.string.pref_show_reading_mode_summary),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = readerPref.showNavigationOverlayOnStart(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_show_navigation_mode),
 | 
			
		||||
                subtitle = stringResource(id = R.string.pref_show_navigation_mode_summary),
 | 
			
		||||
                title = stringResource(R.string.pref_show_navigation_mode),
 | 
			
		||||
                subtitle = stringResource(R.string.pref_show_navigation_mode_summary),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = readerPref.trueColor(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_true_color),
 | 
			
		||||
                subtitle = stringResource(id = R.string.pref_true_color_summary),
 | 
			
		||||
                title = stringResource(R.string.pref_true_color),
 | 
			
		||||
                subtitle = stringResource(R.string.pref_true_color_summary),
 | 
			
		||||
                enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O,
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = readerPref.pageTransitions(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_page_transitions),
 | 
			
		||||
                title = stringResource(R.string.pref_page_transitions),
 | 
			
		||||
            ),
 | 
			
		||||
            getDisplayGroup(readerPreferences = readerPref),
 | 
			
		||||
            getPagedGroup(readerPreferences = readerPref),
 | 
			
		||||
@@ -76,42 +79,42 @@ class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
        val fullscreenPref = readerPreferences.fullscreen()
 | 
			
		||||
        val fullscreen by fullscreenPref.collectAsState()
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_category_display),
 | 
			
		||||
            title = stringResource(R.string.pref_category_display),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.defaultOrientationType(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_rotation_type),
 | 
			
		||||
                    title = stringResource(R.string.pref_rotation_type),
 | 
			
		||||
                    entries = OrientationType.values().drop(1)
 | 
			
		||||
                        .associate { it.flagValue to stringResource(id = it.stringRes) },
 | 
			
		||||
                        .associate { it.flagValue to stringResource(it.stringRes) },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.readerTheme(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_reader_theme),
 | 
			
		||||
                    title = stringResource(R.string.pref_reader_theme),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        1 to stringResource(id = R.string.black_background),
 | 
			
		||||
                        2 to stringResource(id = R.string.gray_background),
 | 
			
		||||
                        0 to stringResource(id = R.string.white_background),
 | 
			
		||||
                        3 to stringResource(id = R.string.automatic_background),
 | 
			
		||||
                        1 to stringResource(R.string.black_background),
 | 
			
		||||
                        2 to stringResource(R.string.gray_background),
 | 
			
		||||
                        0 to stringResource(R.string.white_background),
 | 
			
		||||
                        3 to stringResource(R.string.automatic_background),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = fullscreenPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_fullscreen),
 | 
			
		||||
                    title = stringResource(R.string.pref_fullscreen),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.cutoutShort(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_cutout_short),
 | 
			
		||||
                    title = stringResource(R.string.pref_cutout_short),
 | 
			
		||||
                    enabled = fullscreen &&
 | 
			
		||||
                        Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
 | 
			
		||||
                        LocalView.current.rootWindowInsets?.displayCutout != null, // has cutout
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.keepScreenOn(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_keep_screen_on),
 | 
			
		||||
                    title = stringResource(R.string.pref_keep_screen_on),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.showPageNumber(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_show_page_number),
 | 
			
		||||
                    title = stringResource(R.string.pref_show_page_number),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
@@ -128,71 +131,71 @@ class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
        val dualPageSplit by dualPageSplitPref.collectAsState()
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pager_viewer),
 | 
			
		||||
            title = stringResource(R.string.pager_viewer),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = navModePref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_viewer_nav),
 | 
			
		||||
                    title = stringResource(R.string.pref_viewer_nav),
 | 
			
		||||
                    entries = stringArrayResource(id = R.array.pager_nav).let {
 | 
			
		||||
                        it.indices.zip(it).toMap()
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.pagerNavInverted(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_read_with_tapping_inverted),
 | 
			
		||||
                    title = stringResource(R.string.pref_read_with_tapping_inverted),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        TappingInvertMode.NONE to stringResource(id = R.string.none),
 | 
			
		||||
                        TappingInvertMode.HORIZONTAL to stringResource(id = R.string.tapping_inverted_horizontal),
 | 
			
		||||
                        TappingInvertMode.VERTICAL to stringResource(id = R.string.tapping_inverted_vertical),
 | 
			
		||||
                        TappingInvertMode.BOTH to stringResource(id = R.string.tapping_inverted_both),
 | 
			
		||||
                        TappingInvertMode.NONE to stringResource(R.string.none),
 | 
			
		||||
                        TappingInvertMode.HORIZONTAL to stringResource(R.string.tapping_inverted_horizontal),
 | 
			
		||||
                        TappingInvertMode.VERTICAL to stringResource(R.string.tapping_inverted_vertical),
 | 
			
		||||
                        TappingInvertMode.BOTH to stringResource(R.string.tapping_inverted_both),
 | 
			
		||||
                    ),
 | 
			
		||||
                    enabled = navMode != 5,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.navigateToPan(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_navigate_pan),
 | 
			
		||||
                    title = stringResource(R.string.pref_navigate_pan),
 | 
			
		||||
                    enabled = navMode != 5,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = imageScaleTypePref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_image_scale_type),
 | 
			
		||||
                    title = stringResource(R.string.pref_image_scale_type),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        1 to stringResource(id = R.string.scale_type_fit_screen),
 | 
			
		||||
                        2 to stringResource(id = R.string.scale_type_stretch),
 | 
			
		||||
                        3 to stringResource(id = R.string.scale_type_fit_width),
 | 
			
		||||
                        4 to stringResource(id = R.string.scale_type_fit_height),
 | 
			
		||||
                        5 to stringResource(id = R.string.scale_type_original_size),
 | 
			
		||||
                        6 to stringResource(id = R.string.scale_type_smart_fit),
 | 
			
		||||
                        1 to stringResource(R.string.scale_type_fit_screen),
 | 
			
		||||
                        2 to stringResource(R.string.scale_type_stretch),
 | 
			
		||||
                        3 to stringResource(R.string.scale_type_fit_width),
 | 
			
		||||
                        4 to stringResource(R.string.scale_type_fit_height),
 | 
			
		||||
                        5 to stringResource(R.string.scale_type_original_size),
 | 
			
		||||
                        6 to stringResource(R.string.scale_type_smart_fit),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.landscapeZoom(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_landscape_zoom),
 | 
			
		||||
                    title = stringResource(R.string.pref_landscape_zoom),
 | 
			
		||||
                    enabled = imageScaleType == 1,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.zoomStart(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_zoom_start),
 | 
			
		||||
                    title = stringResource(R.string.pref_zoom_start),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        1 to stringResource(id = R.string.zoom_start_automatic),
 | 
			
		||||
                        2 to stringResource(id = R.string.zoom_start_left),
 | 
			
		||||
                        3 to stringResource(id = R.string.zoom_start_right),
 | 
			
		||||
                        4 to stringResource(id = R.string.zoom_start_center),
 | 
			
		||||
                        1 to stringResource(R.string.zoom_start_automatic),
 | 
			
		||||
                        2 to stringResource(R.string.zoom_start_left),
 | 
			
		||||
                        3 to stringResource(R.string.zoom_start_right),
 | 
			
		||||
                        4 to stringResource(R.string.zoom_start_center),
 | 
			
		||||
                    ),
 | 
			
		||||
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.cropBorders(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_crop_borders),
 | 
			
		||||
                    title = stringResource(R.string.pref_crop_borders),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = dualPageSplitPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_dual_page_split),
 | 
			
		||||
                    title = stringResource(R.string.pref_dual_page_split),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.dualPageInvertPaged(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_dual_page_invert),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_dual_page_invert_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_dual_page_invert),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_dual_page_invert_summary),
 | 
			
		||||
                    enabled = dualPageSplit,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
@@ -208,66 +211,66 @@ class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
        val dualPageSplit by dualPageSplitPref.collectAsState()
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.webtoon_viewer),
 | 
			
		||||
            title = stringResource(R.string.webtoon_viewer),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = navModePref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_viewer_nav),
 | 
			
		||||
                    title = stringResource(R.string.pref_viewer_nav),
 | 
			
		||||
                    entries = stringArrayResource(id = R.array.webtoon_nav).let {
 | 
			
		||||
                        it.indices.zip(it).toMap()
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.webtoonNavInverted(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_read_with_tapping_inverted),
 | 
			
		||||
                    title = stringResource(R.string.pref_read_with_tapping_inverted),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        TappingInvertMode.NONE to stringResource(id = R.string.none),
 | 
			
		||||
                        TappingInvertMode.HORIZONTAL to stringResource(id = R.string.tapping_inverted_horizontal),
 | 
			
		||||
                        TappingInvertMode.VERTICAL to stringResource(id = R.string.tapping_inverted_vertical),
 | 
			
		||||
                        TappingInvertMode.BOTH to stringResource(id = R.string.tapping_inverted_both),
 | 
			
		||||
                        TappingInvertMode.NONE to stringResource(R.string.none),
 | 
			
		||||
                        TappingInvertMode.HORIZONTAL to stringResource(R.string.tapping_inverted_horizontal),
 | 
			
		||||
                        TappingInvertMode.VERTICAL to stringResource(R.string.tapping_inverted_vertical),
 | 
			
		||||
                        TappingInvertMode.BOTH to stringResource(R.string.tapping_inverted_both),
 | 
			
		||||
                    ),
 | 
			
		||||
                    enabled = navMode != 5,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.webtoonSidePadding(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_webtoon_side_padding),
 | 
			
		||||
                    title = stringResource(R.string.pref_webtoon_side_padding),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        0 to stringResource(id = R.string.webtoon_side_padding_0),
 | 
			
		||||
                        5 to stringResource(id = R.string.webtoon_side_padding_5),
 | 
			
		||||
                        10 to stringResource(id = R.string.webtoon_side_padding_10),
 | 
			
		||||
                        15 to stringResource(id = R.string.webtoon_side_padding_15),
 | 
			
		||||
                        20 to stringResource(id = R.string.webtoon_side_padding_20),
 | 
			
		||||
                        25 to stringResource(id = R.string.webtoon_side_padding_25),
 | 
			
		||||
                        0 to stringResource(R.string.webtoon_side_padding_0),
 | 
			
		||||
                        5 to stringResource(R.string.webtoon_side_padding_5),
 | 
			
		||||
                        10 to stringResource(R.string.webtoon_side_padding_10),
 | 
			
		||||
                        15 to stringResource(R.string.webtoon_side_padding_15),
 | 
			
		||||
                        20 to stringResource(R.string.webtoon_side_padding_20),
 | 
			
		||||
                        25 to stringResource(R.string.webtoon_side_padding_25),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                    pref = readerPreferences.readerHideThreshold(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_hide_threshold),
 | 
			
		||||
                    title = stringResource(R.string.pref_hide_threshold),
 | 
			
		||||
                    entries = mapOf(
 | 
			
		||||
                        ReaderHideThreshold.HIGHEST to stringResource(id = R.string.pref_highest),
 | 
			
		||||
                        ReaderHideThreshold.HIGH to stringResource(id = R.string.pref_high),
 | 
			
		||||
                        ReaderHideThreshold.LOW to stringResource(id = R.string.pref_low),
 | 
			
		||||
                        ReaderHideThreshold.LOWEST to stringResource(id = R.string.pref_lowest),
 | 
			
		||||
                        ReaderHideThreshold.HIGHEST to stringResource(R.string.pref_highest),
 | 
			
		||||
                        ReaderHideThreshold.HIGH to stringResource(R.string.pref_high),
 | 
			
		||||
                        ReaderHideThreshold.LOW to stringResource(R.string.pref_low),
 | 
			
		||||
                        ReaderHideThreshold.LOWEST to stringResource(R.string.pref_lowest),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.cropBordersWebtoon(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_crop_borders),
 | 
			
		||||
                    title = stringResource(R.string.pref_crop_borders),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = dualPageSplitPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_dual_page_split),
 | 
			
		||||
                    title = stringResource(R.string.pref_dual_page_split),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.dualPageInvertWebtoon(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_dual_page_invert),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.pref_dual_page_invert_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_dual_page_invert),
 | 
			
		||||
                    subtitle = stringResource(R.string.pref_dual_page_invert_summary),
 | 
			
		||||
                    enabled = dualPageSplit,
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.longStripSplitWebtoon(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_long_strip_split),
 | 
			
		||||
                    subtitle = stringResource(id = R.string.split_tall_images_summary),
 | 
			
		||||
                    title = stringResource(R.string.pref_long_strip_split),
 | 
			
		||||
                    subtitle = stringResource(R.string.split_tall_images_summary),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
@@ -278,15 +281,15 @@ class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
        val readWithVolumeKeysPref = readerPreferences.readWithVolumeKeys()
 | 
			
		||||
        val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState()
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_reader_navigation),
 | 
			
		||||
            title = stringResource(R.string.pref_reader_navigation),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readWithVolumeKeysPref,
 | 
			
		||||
                    title = stringResource(id = R.string.pref_read_with_volume_keys),
 | 
			
		||||
                    title = stringResource(R.string.pref_read_with_volume_keys),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.readWithVolumeKeysInverted(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_read_with_volume_keys_inverted),
 | 
			
		||||
                    title = stringResource(R.string.pref_read_with_volume_keys_inverted),
 | 
			
		||||
                    enabled = readWithVolumeKeys,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
@@ -296,15 +299,15 @@ class SettingsReaderScreen : SearchableSettings {
 | 
			
		||||
    @Composable
 | 
			
		||||
    private fun getActionsGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(id = R.string.pref_reader_actions),
 | 
			
		||||
            title = stringResource(R.string.pref_reader_actions),
 | 
			
		||||
            preferenceItems = listOf(
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.readWithLongTap(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_read_with_long_tap),
 | 
			
		||||
                    title = stringResource(R.string.pref_read_with_long_tap),
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                    pref = readerPreferences.folderPerManga(),
 | 
			
		||||
                    title = stringResource(id = R.string.pref_create_folder_per_manga),
 | 
			
		||||
                    title = stringResource(R.string.pref_create_folder_per_manga),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ class SettingsSearchScreen : Screen {
 | 
			
		||||
                                decorationBox = {
 | 
			
		||||
                                    if (textFieldValue.text.isEmpty()) {
 | 
			
		||||
                                        Text(
 | 
			
		||||
                                            text = stringResource(id = R.string.action_search_settings),
 | 
			
		||||
                                            text = stringResource(R.string.action_search_settings),
 | 
			
		||||
                                            color = MaterialTheme.colorScheme.onSurfaceVariant,
 | 
			
		||||
                                            style = MaterialTheme.typography.bodyLarge,
 | 
			
		||||
                                        )
 | 
			
		||||
@@ -218,7 +218,7 @@ private fun SearchResult(
 | 
			
		||||
                    /* Don't show anything just yet */
 | 
			
		||||
                }
 | 
			
		||||
                // No result
 | 
			
		||||
                it.isEmpty() -> item { EmptyScreen(stringResource(id = R.string.no_results_found)) }
 | 
			
		||||
                it.isEmpty() -> item { EmptyScreen(stringResource(R.string.no_results_found)) }
 | 
			
		||||
                // Show result list
 | 
			
		||||
                else -> items(
 | 
			
		||||
                    items = it,
 | 
			
		||||
@@ -256,7 +256,7 @@ private fun SearchResult(
 | 
			
		||||
private fun getIndex() = settingScreens
 | 
			
		||||
    .map { screen ->
 | 
			
		||||
        SettingsData(
 | 
			
		||||
            title = screen.getTitle(),
 | 
			
		||||
            title = stringResource(screen.getTitleRes()),
 | 
			
		||||
            route = screen,
 | 
			
		||||
            contents = screen.getPreferences(),
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.ReadOnlyComposable
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
@@ -21,7 +22,8 @@ class SettingsSecurityScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_security)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_security
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getPreferences(): List<Preference> {
 | 
			
		||||
@@ -36,7 +38,7 @@ class SettingsSecurityScreen : SearchableSettings {
 | 
			
		||||
        return listOf(
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = useAuthPref,
 | 
			
		||||
                title = stringResource(id = R.string.lock_with_biometrics),
 | 
			
		||||
                title = stringResource(R.string.lock_with_biometrics),
 | 
			
		||||
                enabled = authSupported,
 | 
			
		||||
                onValueChanged = {
 | 
			
		||||
                    (context as FragmentActivity).authenticate(
 | 
			
		||||
@@ -46,14 +48,14 @@ class SettingsSecurityScreen : SearchableSettings {
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                pref = securityPreferences.lockAppAfter(),
 | 
			
		||||
                title = stringResource(id = R.string.lock_when_idle),
 | 
			
		||||
                title = stringResource(R.string.lock_when_idle),
 | 
			
		||||
                subtitle = "%s",
 | 
			
		||||
                enabled = authSupported && useAuth,
 | 
			
		||||
                entries = LockAfterValues
 | 
			
		||||
                    .associateWith {
 | 
			
		||||
                        when (it) {
 | 
			
		||||
                            -1 -> stringResource(id = R.string.lock_never)
 | 
			
		||||
                            0 -> stringResource(id = R.string.lock_always)
 | 
			
		||||
                            -1 -> stringResource(R.string.lock_never)
 | 
			
		||||
                            0 -> stringResource(R.string.lock_always)
 | 
			
		||||
                            else -> pluralStringResource(id = R.plurals.lock_after_mins, count = it, it)
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
@@ -65,16 +67,16 @@ class SettingsSecurityScreen : SearchableSettings {
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = securityPreferences.hideNotificationContent(),
 | 
			
		||||
                title = stringResource(id = R.string.hide_notification_content),
 | 
			
		||||
                title = stringResource(R.string.hide_notification_content),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceItem.ListPreference(
 | 
			
		||||
                pref = securityPreferences.secureScreen(),
 | 
			
		||||
                title = stringResource(id = R.string.secure_screen),
 | 
			
		||||
                title = stringResource(R.string.secure_screen),
 | 
			
		||||
                subtitle = "%s",
 | 
			
		||||
                entries = SecurityPreferences.SecureScreenMode.values()
 | 
			
		||||
                    .associateWith { stringResource(id = it.titleResId) },
 | 
			
		||||
                    .associateWith { stringResource(it.titleResId) },
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.infoPreference(stringResource(id = R.string.secure_screen_summary)),
 | 
			
		||||
            Preference.infoPreference(stringResource(R.string.secure_screen_summary)),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ import androidx.compose.runtime.rememberCoroutineScope
 | 
			
		||||
import androidx.compose.runtime.setValue
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.platform.LocalUriHandler
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.text.input.ImeAction
 | 
			
		||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
 | 
			
		||||
@@ -57,17 +58,19 @@ import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
    @ReadOnlyComposable
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun getTitle(): String = stringResource(id = R.string.pref_category_tracking)
 | 
			
		||||
    @StringRes
 | 
			
		||||
    override fun getTitleRes() = R.string.pref_category_tracking
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun RowScope.AppBarAction() {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        IconButton(onClick = { context.openInBrowser("https://tachiyomi.org/help/guides/tracking/") }) {
 | 
			
		||||
        val uriHandler = LocalUriHandler.current
 | 
			
		||||
        IconButton(onClick = { uriHandler.openUri("https://tachiyomi.org/help/guides/tracking/") }) {
 | 
			
		||||
            Icon(
 | 
			
		||||
                imageVector = Icons.Default.HelpOutline,
 | 
			
		||||
                contentDescription = stringResource(id = R.string.tracking_guide),
 | 
			
		||||
                contentDescription = stringResource(R.string.tracking_guide),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -100,55 +103,55 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
        return listOf(
 | 
			
		||||
            Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                pref = trackPreferences.autoUpdateTrack(),
 | 
			
		||||
                title = stringResource(id = R.string.pref_auto_update_manga_sync),
 | 
			
		||||
                title = stringResource(R.string.pref_auto_update_manga_sync),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceGroup(
 | 
			
		||||
                title = stringResource(id = R.string.services),
 | 
			
		||||
                title = stringResource(R.string.services),
 | 
			
		||||
                preferenceItems = listOf(
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.myAnimeList.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.myAnimeList.nameRes()),
 | 
			
		||||
                        service = trackManager.myAnimeList,
 | 
			
		||||
                        login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) },
 | 
			
		||||
                        logout = { dialog = LogoutDialog(trackManager.myAnimeList) },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.aniList.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.aniList.nameRes()),
 | 
			
		||||
                        service = trackManager.aniList,
 | 
			
		||||
                        login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) },
 | 
			
		||||
                        logout = { dialog = LogoutDialog(trackManager.aniList) },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.kitsu.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.kitsu.nameRes()),
 | 
			
		||||
                        service = trackManager.kitsu,
 | 
			
		||||
                        login = { dialog = LoginDialog(trackManager.kitsu, R.string.email) },
 | 
			
		||||
                        logout = { dialog = LogoutDialog(trackManager.kitsu) },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.mangaUpdates.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.mangaUpdates.nameRes()),
 | 
			
		||||
                        service = trackManager.mangaUpdates,
 | 
			
		||||
                        login = { dialog = LoginDialog(trackManager.mangaUpdates, R.string.username) },
 | 
			
		||||
                        logout = { dialog = LogoutDialog(trackManager.mangaUpdates) },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.shikimori.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.shikimori.nameRes()),
 | 
			
		||||
                        service = trackManager.shikimori,
 | 
			
		||||
                        login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) },
 | 
			
		||||
                        logout = { dialog = LogoutDialog(trackManager.shikimori) },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.bangumi.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.bangumi.nameRes()),
 | 
			
		||||
                        service = trackManager.bangumi,
 | 
			
		||||
                        login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
 | 
			
		||||
                        logout = { dialog = LogoutDialog(trackManager.bangumi) },
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.infoPreference(stringResource(id = R.string.tracking_info)),
 | 
			
		||||
                    Preference.infoPreference(stringResource(R.string.tracking_info)),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            Preference.PreferenceGroup(
 | 
			
		||||
                title = stringResource(id = R.string.enhanced_services),
 | 
			
		||||
                title = stringResource(R.string.enhanced_services),
 | 
			
		||||
                preferenceItems = listOf(
 | 
			
		||||
                    Preference.PreferenceItem.TrackingPreference(
 | 
			
		||||
                        title = stringResource(id = trackManager.komga.nameRes()),
 | 
			
		||||
                        title = stringResource(trackManager.komga.nameRes()),
 | 
			
		||||
                        service = trackManager.komga,
 | 
			
		||||
                        login = {
 | 
			
		||||
                            val sourceManager = Injekt.get<SourceManager>()
 | 
			
		||||
@@ -164,7 +167,7 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
                        },
 | 
			
		||||
                        logout = trackManager.komga::logout,
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.infoPreference(stringResource(id = R.string.enhanced_tracking_info)),
 | 
			
		||||
                    Preference.infoPreference(stringResource(R.string.enhanced_tracking_info)),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
@@ -186,14 +189,14 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
 | 
			
		||||
        AlertDialog(
 | 
			
		||||
            onDismissRequest = onDismissRequest,
 | 
			
		||||
            title = { Text(text = stringResource(id = R.string.login_title, stringResource(id = service.nameRes()))) },
 | 
			
		||||
            title = { Text(text = stringResource(R.string.login_title, stringResource(service.nameRes()))) },
 | 
			
		||||
            text = {
 | 
			
		||||
                Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
 | 
			
		||||
                    OutlinedTextField(
 | 
			
		||||
                        modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                        value = username,
 | 
			
		||||
                        onValueChange = { username = it },
 | 
			
		||||
                        label = { Text(text = stringResource(id = uNameStringRes)) },
 | 
			
		||||
                        label = { Text(text = stringResource(uNameStringRes)) },
 | 
			
		||||
                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
 | 
			
		||||
                        singleLine = true,
 | 
			
		||||
                        isError = inputError && username.text.isEmpty(),
 | 
			
		||||
@@ -204,7 +207,7 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
                        modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                        value = password,
 | 
			
		||||
                        onValueChange = { password = it },
 | 
			
		||||
                        label = { Text(text = stringResource(id = R.string.password)) },
 | 
			
		||||
                        label = { Text(text = stringResource(R.string.password)) },
 | 
			
		||||
                        trailingIcon = {
 | 
			
		||||
                            IconButton(onClick = { hidePassword = !hidePassword }) {
 | 
			
		||||
                                Icon(
 | 
			
		||||
@@ -253,13 +256,13 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
                        },
 | 
			
		||||
                    ) {
 | 
			
		||||
                        val id = if (processing) R.string.loading else R.string.login
 | 
			
		||||
                        Text(text = stringResource(id = id))
 | 
			
		||||
                        Text(text = stringResource(id))
 | 
			
		||||
                    }
 | 
			
		||||
                    TextButton(
 | 
			
		||||
                        modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                        onClick = onDismissRequest,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                        Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
@@ -293,7 +296,7 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
            onDismissRequest = onDismissRequest,
 | 
			
		||||
            title = {
 | 
			
		||||
                Text(
 | 
			
		||||
                    text = stringResource(id = R.string.logout_title, stringResource(id = service.nameRes())),
 | 
			
		||||
                    text = stringResource(R.string.logout_title, stringResource(service.nameRes())),
 | 
			
		||||
                    textAlign = TextAlign.Center,
 | 
			
		||||
                    modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                )
 | 
			
		||||
@@ -304,7 +307,7 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
                        modifier = Modifier.weight(1f),
 | 
			
		||||
                        onClick = onDismissRequest,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                        Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                    }
 | 
			
		||||
                    Button(
 | 
			
		||||
                        modifier = Modifier.weight(1f),
 | 
			
		||||
@@ -318,7 +321,7 @@ class SettingsTrackingScreen : SearchableSettings {
 | 
			
		||||
                            contentColor = MaterialTheme.colorScheme.onError,
 | 
			
		||||
                        ),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(text = stringResource(id = R.string.logout))
 | 
			
		||||
                        Text(text = stringResource(R.string.logout))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,7 @@ private fun AppThemesList(
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Text(
 | 
			
		||||
                    text = stringResource(id = appTheme.titleResId!!),
 | 
			
		||||
                    text = stringResource(appTheme.titleResId!!),
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .fillMaxWidth()
 | 
			
		||||
                        .padding(top = 8.dp)
 | 
			
		||||
 
 | 
			
		||||
@@ -66,12 +66,12 @@ fun EditTextPreferenceWidget(
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            dismissButton = {
 | 
			
		||||
                TextButton(onClick = onDismissRequest) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ fun <T> ListPreferenceWidget(
 | 
			
		||||
            },
 | 
			
		||||
            confirmButton = {
 | 
			
		||||
                TextButton(onClick = { showDialog(false) }) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -86,12 +86,12 @@ fun MultiSelectListPreferenceWidget(
 | 
			
		||||
                        showDialog(false)
 | 
			
		||||
                    },
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            dismissButton = {
 | 
			
		||||
                TextButton(onClick = { showDialog(false) }) {
 | 
			
		||||
                    Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                    Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -117,7 +117,7 @@ fun <T> TriStateListDialog(
 | 
			
		||||
        },
 | 
			
		||||
        dismissButton = {
 | 
			
		||||
            TextButton(onClick = onDismissRequest) {
 | 
			
		||||
                Text(text = stringResource(id = android.R.string.cancel))
 | 
			
		||||
                Text(text = stringResource(android.R.string.cancel))
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        confirmButton = {
 | 
			
		||||
@@ -132,7 +132,7 @@ fun <T> TriStateListDialog(
 | 
			
		||||
                    onValueChanged(included, excluded)
 | 
			
		||||
                },
 | 
			
		||||
            ) {
 | 
			
		||||
                Text(text = stringResource(id = android.R.string.ok))
 | 
			
		||||
                Text(text = stringResource(android.R.string.ok))
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user