mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Migrate ReaderColorFilterSettings to Compose
It'll eventually be a tab with the other settings again once the other tabs are also migrated over so it's just a single Compose sheet.
This commit is contained in:
		@@ -199,7 +199,6 @@ private fun ColumnScope.DisplayPage(
 | 
			
		||||
        val columns by columnPreference.collectAsState()
 | 
			
		||||
        SliderItem(
 | 
			
		||||
            label = stringResource(R.string.pref_library_columns),
 | 
			
		||||
            min = 0,
 | 
			
		||||
            max = 10,
 | 
			
		||||
            value = columns,
 | 
			
		||||
            valueText = if (columns > 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ import androidx.compose.runtime.compositionLocalOf
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.rememberCoroutineScope
 | 
			
		||||
import androidx.compose.runtime.structuralEqualityPolicy
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import eu.kanade.domain.track.service.TrackPreferences
 | 
			
		||||
import eu.kanade.domain.ui.UiPreferences
 | 
			
		||||
import eu.kanade.presentation.more.settings.widget.AppThemePreferenceWidget
 | 
			
		||||
@@ -24,10 +25,12 @@ import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget
 | 
			
		||||
import eu.kanade.presentation.util.collectAsState
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import tachiyomi.core.preference.PreferenceStore
 | 
			
		||||
import tachiyomi.presentation.core.components.SliderItem
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
val LocalPreferenceHighlighted = compositionLocalOf(structuralEqualityPolicy()) { false }
 | 
			
		||||
val LocalPreferenceMinHeight = compositionLocalOf(structuralEqualityPolicy()) { 56.dp }
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun StatusWrapper(
 | 
			
		||||
@@ -77,6 +80,21 @@ internal fun PreferenceItem(
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            is Preference.PreferenceItem.SliderPreference -> {
 | 
			
		||||
                // TODO: use different composable?
 | 
			
		||||
                SliderItem(
 | 
			
		||||
                    label = item.title,
 | 
			
		||||
                    min = item.min,
 | 
			
		||||
                    max = item.max,
 | 
			
		||||
                    value = item.value,
 | 
			
		||||
                    valueText = item.value.toString(),
 | 
			
		||||
                    onChange = {
 | 
			
		||||
                        scope.launch {
 | 
			
		||||
                            item.onValueChanged(it)
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            is Preference.PreferenceItem.ListPreference<*> -> {
 | 
			
		||||
                val value by item.pref.collectAsState()
 | 
			
		||||
                ListPreferenceWidget(
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.ui.graphics.vector.ImageVector
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import eu.kanade.domain.ui.model.AppTheme
 | 
			
		||||
import eu.kanade.presentation.more.settings.Preference.PreferenceItem
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackService
 | 
			
		||||
import tachiyomi.core.preference.Preference as PreferenceData
 | 
			
		||||
@@ -43,6 +44,20 @@ sealed class Preference {
 | 
			
		||||
            override val onValueChanged: suspend (newValue: Boolean) -> Boolean = { true },
 | 
			
		||||
        ) : PreferenceItem<Boolean>()
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * A [PreferenceItem] that provides a slider to select an integer number.
 | 
			
		||||
         */
 | 
			
		||||
        data class SliderPreference(
 | 
			
		||||
            val value: Int,
 | 
			
		||||
            val min: Int = 0,
 | 
			
		||||
            val max: Int,
 | 
			
		||||
            override val title: String = "",
 | 
			
		||||
            override val subtitle: String? = null,
 | 
			
		||||
            override val icon: ImageVector? = null,
 | 
			
		||||
            override val enabled: Boolean = true,
 | 
			
		||||
            override val onValueChanged: suspend (newValue: Int) -> Boolean = { true },
 | 
			
		||||
        ) : PreferenceItem<Int>()
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * A [PreferenceItem] that displays a list of entries as a dialog.
 | 
			
		||||
         */
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,7 @@ import androidx.compose.ui.text.style.TextOverflow
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import androidx.compose.ui.unit.sp
 | 
			
		||||
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
 | 
			
		||||
import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight
 | 
			
		||||
import kotlinx.coroutines.delay
 | 
			
		||||
import kotlin.time.Duration.Companion.seconds
 | 
			
		||||
 | 
			
		||||
@@ -44,10 +45,11 @@ internal fun BasePreferenceWidget(
 | 
			
		||||
    widget: @Composable (() -> Unit)? = null,
 | 
			
		||||
) {
 | 
			
		||||
    val highlighted = LocalPreferenceHighlighted.current
 | 
			
		||||
    val minHeight = LocalPreferenceMinHeight.current
 | 
			
		||||
    Row(
 | 
			
		||||
        modifier = modifier
 | 
			
		||||
            .highlightBackground(highlighted)
 | 
			
		||||
            .sizeIn(minHeight = 56.dp)
 | 
			
		||||
            .sizeIn(minHeight = minHeight)
 | 
			
		||||
            .clickable(enabled = onClick != null, onClick = { onClick?.invoke() })
 | 
			
		||||
            .fillMaxWidth(),
 | 
			
		||||
        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderColorFilterDialog
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsSheet
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
 | 
			
		||||
@@ -409,10 +410,20 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
 | 
			
		||||
        binding.dialogRoot.setComposeContent {
 | 
			
		||||
            val state by viewModel.state.collectAsState()
 | 
			
		||||
 | 
			
		||||
            val onDismissRequest = viewModel::closeDialog
 | 
			
		||||
            when (state.dialog) {
 | 
			
		||||
                is ReaderViewModel.Dialog.ColorFilter -> {
 | 
			
		||||
                    setMenuVisibility(false)
 | 
			
		||||
                    ReaderColorFilterDialog(
 | 
			
		||||
                        onDismissRequest = {
 | 
			
		||||
                            onDismissRequest()
 | 
			
		||||
                            setMenuVisibility(true)
 | 
			
		||||
                        },
 | 
			
		||||
                        readerPreferences = viewModel.readerPreferences,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                is ReaderViewModel.Dialog.Page -> ReaderPageDialog(
 | 
			
		||||
                    onDismissRequest = viewModel::closeDialog,
 | 
			
		||||
                    onDismissRequest = onDismissRequest,
 | 
			
		||||
                    onSetAsCover = viewModel::setAsCover,
 | 
			
		||||
                    onShare = viewModel::shareImage,
 | 
			
		||||
                    onSave = viewModel::saveImage,
 | 
			
		||||
@@ -548,11 +559,14 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
                if (readerSettingSheet?.isShowing == true) return@setOnClickListener
 | 
			
		||||
                readerSettingSheet = ReaderSettingsSheet(this@ReaderActivity).apply { show() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            setOnLongClickListener {
 | 
			
		||||
                if (readerSettingSheet?.isShowing == true) return@setOnLongClickListener false
 | 
			
		||||
                readerSettingSheet = ReaderSettingsSheet(this@ReaderActivity, showColorFilterSettings = true).apply { show() }
 | 
			
		||||
                true
 | 
			
		||||
        // Color filter sheet
 | 
			
		||||
        with(binding.actionColorSettings) {
 | 
			
		||||
            setTooltip(R.string.custom_filter)
 | 
			
		||||
 | 
			
		||||
            setOnClickListener {
 | 
			
		||||
                viewModel.openColorFilterDialog()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -92,9 +92,9 @@ class ReaderViewModel(
 | 
			
		||||
    private val downloadProvider: DownloadProvider = Injekt.get(),
 | 
			
		||||
    private val imageSaver: ImageSaver = Injekt.get(),
 | 
			
		||||
    preferences: BasePreferences = Injekt.get(),
 | 
			
		||||
    val readerPreferences: ReaderPreferences = Injekt.get(),
 | 
			
		||||
    private val basePreferences: BasePreferences = Injekt.get(),
 | 
			
		||||
    private val downloadPreferences: DownloadPreferences = Injekt.get(),
 | 
			
		||||
    private val readerPreferences: ReaderPreferences = Injekt.get(),
 | 
			
		||||
    private val trackPreferences: TrackPreferences = Injekt.get(),
 | 
			
		||||
    private val delayedTrackingStore: DelayedTrackingStore = Injekt.get(),
 | 
			
		||||
    private val getManga: GetManga = Injekt.get(),
 | 
			
		||||
@@ -723,6 +723,10 @@ class ReaderViewModel(
 | 
			
		||||
        mutableState.update { it.copy(dialog = Dialog.Page(page)) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun openColorFilterDialog() {
 | 
			
		||||
        mutableState.update { it.copy(dialog = Dialog.ColorFilter) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun closeDialog() {
 | 
			
		||||
        mutableState.update { it.copy(dialog = null) }
 | 
			
		||||
    }
 | 
			
		||||
@@ -925,6 +929,7 @@ class ReaderViewModel(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sealed class Dialog {
 | 
			
		||||
        object ColorFilter : Dialog()
 | 
			
		||||
        data class Page(val page: ReaderPage) : Dialog()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,164 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.setting
 | 
			
		||||
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.CompositionLocalProvider
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.ui.platform.LocalView
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import androidx.compose.ui.window.DialogWindowProvider
 | 
			
		||||
import androidx.core.graphics.alpha
 | 
			
		||||
import androidx.core.graphics.blue
 | 
			
		||||
import androidx.core.graphics.green
 | 
			
		||||
import androidx.core.graphics.red
 | 
			
		||||
import eu.kanade.presentation.components.AdaptiveSheet
 | 
			
		||||
import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight
 | 
			
		||||
import eu.kanade.presentation.more.settings.Preference
 | 
			
		||||
import eu.kanade.presentation.more.settings.PreferenceScreen
 | 
			
		||||
import eu.kanade.presentation.util.collectAsState
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import tachiyomi.core.preference.getAndSet
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun ReaderColorFilterDialog(
 | 
			
		||||
    onDismissRequest: () -> Unit,
 | 
			
		||||
    readerPreferences: ReaderPreferences,
 | 
			
		||||
) {
 | 
			
		||||
    val colorFilterModes = buildList {
 | 
			
		||||
        addAll(
 | 
			
		||||
            listOf(
 | 
			
		||||
                R.string.label_default,
 | 
			
		||||
                R.string.filter_mode_multiply,
 | 
			
		||||
                R.string.filter_mode_screen,
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
 | 
			
		||||
            addAll(
 | 
			
		||||
                listOf(
 | 
			
		||||
                    R.string.filter_mode_overlay,
 | 
			
		||||
                    R.string.filter_mode_lighten,
 | 
			
		||||
                    R.string.filter_mode_darken,
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }.map { stringResource(it) }
 | 
			
		||||
 | 
			
		||||
    val customBrightness by readerPreferences.customBrightness().collectAsState()
 | 
			
		||||
    val customBrightnessValue by readerPreferences.customBrightnessValue().collectAsState()
 | 
			
		||||
    val colorFilter by readerPreferences.colorFilter().collectAsState()
 | 
			
		||||
    val colorFilterValue by readerPreferences.colorFilterValue().collectAsState()
 | 
			
		||||
    val colorFilterMode by readerPreferences.colorFilterMode().collectAsState()
 | 
			
		||||
 | 
			
		||||
    AdaptiveSheet(
 | 
			
		||||
        onDismissRequest = onDismissRequest,
 | 
			
		||||
    ) {
 | 
			
		||||
        (LocalView.current.parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
 | 
			
		||||
 | 
			
		||||
        CompositionLocalProvider(
 | 
			
		||||
            LocalPreferenceMinHeight provides 48.dp,
 | 
			
		||||
        ) {
 | 
			
		||||
            PreferenceScreen(
 | 
			
		||||
                items = listOfNotNull(
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = readerPreferences.customBrightness(),
 | 
			
		||||
                        title = stringResource(R.string.pref_custom_brightness),
 | 
			
		||||
                    ),
 | 
			
		||||
                    /**
 | 
			
		||||
                     * Sets the brightness of the screen. Range is [-75, 100].
 | 
			
		||||
                     * From -75 to -1 a semi-transparent black view is shown at the top with the minimum brightness.
 | 
			
		||||
                     * From 1 to 100 it sets that value as brightness.
 | 
			
		||||
                     * 0 sets system brightness and hides the overlay.
 | 
			
		||||
                     */
 | 
			
		||||
                    Preference.PreferenceItem.SliderPreference(
 | 
			
		||||
                        value = customBrightnessValue,
 | 
			
		||||
                        title = stringResource(R.string.pref_custom_brightness),
 | 
			
		||||
                        min = -75,
 | 
			
		||||
                        max = 100,
 | 
			
		||||
                        onValueChanged = {
 | 
			
		||||
                            readerPreferences.customBrightnessValue().set(it)
 | 
			
		||||
                            true
 | 
			
		||||
                        },
 | 
			
		||||
                    ).takeIf { customBrightness },
 | 
			
		||||
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = readerPreferences.colorFilter(),
 | 
			
		||||
                        title = stringResource(R.string.pref_custom_color_filter),
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.SliderPreference(
 | 
			
		||||
                        value = colorFilterValue.red,
 | 
			
		||||
                        title = stringResource(R.string.color_filter_r_value),
 | 
			
		||||
                        max = 255,
 | 
			
		||||
                        onValueChanged = { newRValue ->
 | 
			
		||||
                            readerPreferences.colorFilterValue().getAndSet {
 | 
			
		||||
                                getColorValue(it, newRValue, RED_MASK, 16)
 | 
			
		||||
                            }
 | 
			
		||||
                            true
 | 
			
		||||
                        },
 | 
			
		||||
                    ).takeIf { colorFilter },
 | 
			
		||||
                    Preference.PreferenceItem.SliderPreference(
 | 
			
		||||
                        value = colorFilterValue.green,
 | 
			
		||||
                        title = stringResource(R.string.color_filter_g_value),
 | 
			
		||||
                        max = 255,
 | 
			
		||||
                        onValueChanged = { newRValue ->
 | 
			
		||||
                            readerPreferences.colorFilterValue().getAndSet {
 | 
			
		||||
                                getColorValue(it, newRValue, GREEN_MASK, 8)
 | 
			
		||||
                            }
 | 
			
		||||
                            true
 | 
			
		||||
                        },
 | 
			
		||||
                    ).takeIf { colorFilter },
 | 
			
		||||
                    Preference.PreferenceItem.SliderPreference(
 | 
			
		||||
                        value = colorFilterValue.blue,
 | 
			
		||||
                        title = stringResource(R.string.color_filter_b_value),
 | 
			
		||||
                        max = 255,
 | 
			
		||||
                        onValueChanged = { newRValue ->
 | 
			
		||||
                            readerPreferences.colorFilterValue().getAndSet {
 | 
			
		||||
                                getColorValue(it, newRValue, BLUE_MASK, 0)
 | 
			
		||||
                            }
 | 
			
		||||
                            true
 | 
			
		||||
                        },
 | 
			
		||||
                    ).takeIf { colorFilter },
 | 
			
		||||
                    Preference.PreferenceItem.SliderPreference(
 | 
			
		||||
                        value = colorFilterValue.alpha,
 | 
			
		||||
                        title = stringResource(R.string.color_filter_a_value),
 | 
			
		||||
                        max = 255,
 | 
			
		||||
                        onValueChanged = { newRValue ->
 | 
			
		||||
                            readerPreferences.colorFilterValue().getAndSet {
 | 
			
		||||
                                getColorValue(it, newRValue, ALPHA_MASK, 24)
 | 
			
		||||
                            }
 | 
			
		||||
                            true
 | 
			
		||||
                        },
 | 
			
		||||
                    ).takeIf { colorFilter },
 | 
			
		||||
                    Preference.PreferenceItem.BasicListPreference(
 | 
			
		||||
                        value = colorFilterMode.toString(),
 | 
			
		||||
                        title = stringResource(R.string.pref_color_filter_mode),
 | 
			
		||||
                        entries = colorFilterModes
 | 
			
		||||
                            .mapIndexed { index, mode -> index.toString() to mode }
 | 
			
		||||
                            .toMap(),
 | 
			
		||||
                        onValueChanged = { newValue ->
 | 
			
		||||
                            readerPreferences.colorFilterMode().set(newValue.toInt())
 | 
			
		||||
                            true
 | 
			
		||||
                        },
 | 
			
		||||
                    ).takeIf { colorFilter },
 | 
			
		||||
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = readerPreferences.grayscale(),
 | 
			
		||||
                        title = stringResource(R.string.pref_grayscale),
 | 
			
		||||
                    ),
 | 
			
		||||
                    Preference.PreferenceItem.SwitchPreference(
 | 
			
		||||
                        pref = readerPreferences.invertedColors(),
 | 
			
		||||
                        title = stringResource(R.string.pref_inverted_colors),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private fun getColorValue(currentColor: Int, color: Int, mask: Long, bitShift: Int): Int {
 | 
			
		||||
    return (color shl bitShift) or (currentColor and mask.inv().toInt())
 | 
			
		||||
}
 | 
			
		||||
private const val ALPHA_MASK: Long = 0xFF000000
 | 
			
		||||
private const val RED_MASK: Long = 0x00FF0000
 | 
			
		||||
private const val GREEN_MASK: Long = 0x0000FF00
 | 
			
		||||
private const val BLUE_MASK: Long = 0x000000FF
 | 
			
		||||
@@ -1,202 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.setting
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.util.AttributeSet
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import androidx.annotation.ColorInt
 | 
			
		||||
import androidx.core.graphics.alpha
 | 
			
		||||
import androidx.core.graphics.blue
 | 
			
		||||
import androidx.core.graphics.green
 | 
			
		||||
import androidx.core.graphics.red
 | 
			
		||||
import androidx.core.widget.NestedScrollView
 | 
			
		||||
import androidx.lifecycle.lifecycleScope
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.ReaderColorFilterSettingsBinding
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.bindToPreference
 | 
			
		||||
import kotlinx.coroutines.flow.launchIn
 | 
			
		||||
import kotlinx.coroutines.flow.onEach
 | 
			
		||||
import kotlinx.coroutines.flow.sample
 | 
			
		||||
import tachiyomi.core.preference.getAndSet
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Color filter sheet to toggle custom filter and brightness overlay.
 | 
			
		||||
 */
 | 
			
		||||
class ReaderColorFilterSettings @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
 | 
			
		||||
    NestedScrollView(context, attrs) {
 | 
			
		||||
 | 
			
		||||
    private val readerPreferences: ReaderPreferences by injectLazy()
 | 
			
		||||
 | 
			
		||||
    private val binding = ReaderColorFilterSettingsBinding.inflate(LayoutInflater.from(context), this, false)
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        addView(binding.root)
 | 
			
		||||
 | 
			
		||||
        readerPreferences.colorFilter().changes()
 | 
			
		||||
            .onEach(::setColorFilter)
 | 
			
		||||
            .launchIn((context as ReaderActivity).lifecycleScope)
 | 
			
		||||
 | 
			
		||||
        readerPreferences.colorFilterMode().changes()
 | 
			
		||||
            .onEach { setColorFilter(readerPreferences.colorFilter().get()) }
 | 
			
		||||
            .launchIn(context.lifecycleScope)
 | 
			
		||||
 | 
			
		||||
        readerPreferences.customBrightness().changes()
 | 
			
		||||
            .onEach(::setCustomBrightness)
 | 
			
		||||
            .launchIn(context.lifecycleScope)
 | 
			
		||||
 | 
			
		||||
        // Get color and update values
 | 
			
		||||
        val color = readerPreferences.colorFilterValue().get()
 | 
			
		||||
        val brightness = readerPreferences.customBrightnessValue().get()
 | 
			
		||||
 | 
			
		||||
        val argb = setValues(color)
 | 
			
		||||
 | 
			
		||||
        // Set brightness value
 | 
			
		||||
        binding.txtBrightnessSeekbarValue.text = brightness.toString()
 | 
			
		||||
        binding.sliderBrightness.value = brightness.toFloat()
 | 
			
		||||
 | 
			
		||||
        // Initialize seekBar progress
 | 
			
		||||
        binding.sliderColorFilterAlpha.value = argb[0].toFloat()
 | 
			
		||||
        binding.sliderColorFilterRed.value = argb[1].toFloat()
 | 
			
		||||
        binding.sliderColorFilterGreen.value = argb[2].toFloat()
 | 
			
		||||
        binding.sliderColorFilterBlue.value = argb[3].toFloat()
 | 
			
		||||
 | 
			
		||||
        // Set listeners
 | 
			
		||||
        binding.switchColorFilter.bindToPreference(readerPreferences.colorFilter())
 | 
			
		||||
        binding.customBrightness.bindToPreference(readerPreferences.customBrightness())
 | 
			
		||||
        binding.colorFilterMode.bindToPreference(readerPreferences.colorFilterMode())
 | 
			
		||||
        binding.grayscale.bindToPreference(readerPreferences.grayscale())
 | 
			
		||||
        binding.invertedColors.bindToPreference(readerPreferences.invertedColors())
 | 
			
		||||
 | 
			
		||||
        binding.sliderColorFilterAlpha.addOnChangeListener { _, value, fromUser ->
 | 
			
		||||
            if (fromUser) {
 | 
			
		||||
                setColorValue(value.toInt(), ALPHA_MASK, 24)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        binding.sliderColorFilterRed.addOnChangeListener { _, value, fromUser ->
 | 
			
		||||
            if (fromUser) {
 | 
			
		||||
                setColorValue(value.toInt(), RED_MASK, 16)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        binding.sliderColorFilterGreen.addOnChangeListener { _, value, fromUser ->
 | 
			
		||||
            if (fromUser) {
 | 
			
		||||
                setColorValue(value.toInt(), GREEN_MASK, 8)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        binding.sliderColorFilterBlue.addOnChangeListener { _, value, fromUser ->
 | 
			
		||||
            if (fromUser) {
 | 
			
		||||
                setColorValue(value.toInt(), BLUE_MASK, 0)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        binding.sliderBrightness.addOnChangeListener { _, value, fromUser ->
 | 
			
		||||
            if (fromUser) {
 | 
			
		||||
                readerPreferences.customBrightnessValue().set(value.toInt())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set enabled status of seekBars belonging to color filter
 | 
			
		||||
     * @param enabled determines if seekBar gets enabled
 | 
			
		||||
     */
 | 
			
		||||
    private fun setColorFilterSeekBar(enabled: Boolean) {
 | 
			
		||||
        binding.sliderColorFilterRed.isEnabled = enabled
 | 
			
		||||
        binding.sliderColorFilterGreen.isEnabled = enabled
 | 
			
		||||
        binding.sliderColorFilterBlue.isEnabled = enabled
 | 
			
		||||
        binding.sliderColorFilterAlpha.isEnabled = enabled
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set enabled status of seekBars belonging to custom brightness
 | 
			
		||||
     * @param enabled value which determines if seekBar gets enabled
 | 
			
		||||
     */
 | 
			
		||||
    private fun setCustomBrightnessSeekBar(enabled: Boolean) {
 | 
			
		||||
        binding.sliderBrightness.isEnabled = enabled
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the text value's of color filter
 | 
			
		||||
     * @param color integer containing color information
 | 
			
		||||
     */
 | 
			
		||||
    private fun setValues(color: Int): Array<Int> {
 | 
			
		||||
        val alpha = color.alpha
 | 
			
		||||
        val red = color.red
 | 
			
		||||
        val green = color.green
 | 
			
		||||
        val blue = color.blue
 | 
			
		||||
 | 
			
		||||
        // Initialize values
 | 
			
		||||
        binding.txtColorFilterAlphaValue.text = "$alpha"
 | 
			
		||||
        binding.txtColorFilterRedValue.text = "$red"
 | 
			
		||||
        binding.txtColorFilterGreenValue.text = "$green"
 | 
			
		||||
        binding.txtColorFilterBlueValue.text = "$blue"
 | 
			
		||||
 | 
			
		||||
        return arrayOf(alpha, red, green, blue)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Manages the custom brightness value subscription
 | 
			
		||||
     * @param enabled determines if the subscription get (un)subscribed
 | 
			
		||||
     */
 | 
			
		||||
    private fun setCustomBrightness(enabled: Boolean) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            readerPreferences.customBrightnessValue().changes()
 | 
			
		||||
                .sample(100)
 | 
			
		||||
                .onEach(::setCustomBrightnessValue)
 | 
			
		||||
                .launchIn((context as ReaderActivity).lifecycleScope)
 | 
			
		||||
        } else {
 | 
			
		||||
            setCustomBrightnessValue(0, true)
 | 
			
		||||
        }
 | 
			
		||||
        setCustomBrightnessSeekBar(enabled)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the brightness of the screen. Range is [-75, 100].
 | 
			
		||||
     * From -75 to -1 a semi-transparent black view is shown at the top with the minimum brightness.
 | 
			
		||||
     * From 1 to 100 it sets that value as brightness.
 | 
			
		||||
     * 0 sets system brightness and hides the overlay.
 | 
			
		||||
     */
 | 
			
		||||
    private fun setCustomBrightnessValue(value: Int, isDisabled: Boolean = false) {
 | 
			
		||||
        if (!isDisabled) {
 | 
			
		||||
            binding.txtBrightnessSeekbarValue.text = value.toString()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Manages the color filter value subscription
 | 
			
		||||
     * @param enabled determines if the subscription get (un)subscribed
 | 
			
		||||
     */
 | 
			
		||||
    private fun setColorFilter(enabled: Boolean) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            readerPreferences.colorFilterValue().changes()
 | 
			
		||||
                .sample(100)
 | 
			
		||||
                .onEach(::setColorFilterValue)
 | 
			
		||||
                .launchIn((context as ReaderActivity).lifecycleScope)
 | 
			
		||||
        }
 | 
			
		||||
        setColorFilterSeekBar(enabled)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the color filter overlay of the screen. Determined by HEX of integer
 | 
			
		||||
     * @param color hex of color.
 | 
			
		||||
     */
 | 
			
		||||
    private fun setColorFilterValue(@ColorInt color: Int) {
 | 
			
		||||
        setValues(color)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the color value in preference
 | 
			
		||||
     * @param color value of color range [0,255]
 | 
			
		||||
     * @param mask contains hex mask of chosen color
 | 
			
		||||
     * @param bitShift amounts of bits that gets shifted to receive value
 | 
			
		||||
     */
 | 
			
		||||
    private fun setColorValue(color: Int, mask: Long, bitShift: Int) {
 | 
			
		||||
        readerPreferences.colorFilterValue().getAndSet { currentColor ->
 | 
			
		||||
            (color shl bitShift) or (currentColor and mask.inv().toInt())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private const val ALPHA_MASK: Long = 0xFF000000
 | 
			
		||||
private const val RED_MASK: Long = 0x00FF0000
 | 
			
		||||
private const val GREEN_MASK: Long = 0x0000FF00
 | 
			
		||||
private const val BLUE_MASK: Long = 0x000000FF
 | 
			
		||||
@@ -1,46 +1,30 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.setting
 | 
			
		||||
 | 
			
		||||
import android.animation.ValueAnimator
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import com.google.android.material.tabs.TabLayout
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.CommonTabbedSheetBinding
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
 | 
			
		||||
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
 | 
			
		||||
import eu.kanade.tachiyomi.widget.listener.SimpleTabSelectedListener
 | 
			
		||||
import eu.kanade.tachiyomi.widget.sheet.BaseBottomSheetDialog
 | 
			
		||||
 | 
			
		||||
class ReaderSettingsSheet(
 | 
			
		||||
    private val activity: ReaderActivity,
 | 
			
		||||
    private val showColorFilterSettings: Boolean = false,
 | 
			
		||||
) : BaseBottomSheetDialog(activity) {
 | 
			
		||||
 | 
			
		||||
    private val tabs = listOf(
 | 
			
		||||
        ReaderReadingModeSettings(activity) to R.string.pref_category_reading_mode,
 | 
			
		||||
        ReaderGeneralSettings(activity) to R.string.pref_category_general,
 | 
			
		||||
        ReaderColorFilterSettings(activity) to R.string.custom_filter,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private val backgroundDimAnimator by lazy {
 | 
			
		||||
        val sheetBackgroundDim = window?.attributes?.dimAmount ?: 0.25f
 | 
			
		||||
        ValueAnimator.ofFloat(sheetBackgroundDim, 0f).also { valueAnimator ->
 | 
			
		||||
            valueAnimator.duration = 250
 | 
			
		||||
            valueAnimator.addUpdateListener {
 | 
			
		||||
                window?.setDimAmount(it.animatedValue as Float)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private lateinit var binding: CommonTabbedSheetBinding
 | 
			
		||||
 | 
			
		||||
    override fun createView(inflater: LayoutInflater): View {
 | 
			
		||||
        binding = CommonTabbedSheetBinding.inflate(activity.layoutInflater)
 | 
			
		||||
 | 
			
		||||
        val adapter = Adapter()
 | 
			
		||||
        binding.pager.offscreenPageLimit = 2
 | 
			
		||||
        binding.pager.adapter = adapter
 | 
			
		||||
        binding.tabs.setupWithViewPager(binding.pager)
 | 
			
		||||
 | 
			
		||||
@@ -52,35 +36,6 @@ class ReaderSettingsSheet(
 | 
			
		||||
 | 
			
		||||
        behavior.isFitToContents = false
 | 
			
		||||
        behavior.halfExpandedRatio = 0.25f
 | 
			
		||||
 | 
			
		||||
        val filterTabIndex = tabs.indexOfFirst { it.first is ReaderColorFilterSettings }
 | 
			
		||||
        binding.tabs.addOnTabSelectedListener(
 | 
			
		||||
            object : SimpleTabSelectedListener() {
 | 
			
		||||
                override fun onTabSelected(tab: TabLayout.Tab?) {
 | 
			
		||||
                    val isFilterTab = tab?.position == filterTabIndex
 | 
			
		||||
 | 
			
		||||
                    // Remove dimmed backdrop so color filter changes can be previewed
 | 
			
		||||
                    backgroundDimAnimator.run {
 | 
			
		||||
                        if (isFilterTab) {
 | 
			
		||||
                            if (animatedFraction < 1f) {
 | 
			
		||||
                                start()
 | 
			
		||||
                            }
 | 
			
		||||
                        } else if (animatedFraction > 0f) {
 | 
			
		||||
                            reverse()
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Hide toolbars
 | 
			
		||||
                    if (activity.menuVisible != !isFilterTab) {
 | 
			
		||||
                        activity.setMenuVisibility(!isFilterTab)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if (showColorFilterSettings) {
 | 
			
		||||
            binding.tabs.getTabAt(filterTabIndex)?.select()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private inner class Adapter : ViewPagerAdapter() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.widget.listener
 | 
			
		||||
 | 
			
		||||
import com.google.android.material.tabs.TabLayout
 | 
			
		||||
 | 
			
		||||
open class SimpleTabSelectedListener : TabLayout.OnTabSelectedListener {
 | 
			
		||||
    override fun onTabSelected(tab: TabLayout.Tab?) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onTabUnselected(tab: TabLayout.Tab?) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onTabReselected(tab: TabLayout.Tab?) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -119,12 +119,25 @@
 | 
			
		||||
                    android:background="?attr/selectableItemBackgroundBorderless"
 | 
			
		||||
                    android:contentDescription="@string/action_settings"
 | 
			
		||||
                    android:padding="@dimen/screen_edge_margin"
 | 
			
		||||
                    app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
                    app:layout_constraintEnd_toStartOf="@+id/action_color_settings"
 | 
			
		||||
                    app:layout_constraintStart_toEndOf="@id/action_rotation"
 | 
			
		||||
                    app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
                    app:srcCompat="@drawable/ic_settings_24dp"
 | 
			
		||||
                    app:tint="?attr/colorOnSurface" />
 | 
			
		||||
 | 
			
		||||
                <ImageButton
 | 
			
		||||
                    android:id="@+id/action_color_settings"
 | 
			
		||||
                    android:layout_width="wrap_content"
 | 
			
		||||
                    android:layout_height="match_parent"
 | 
			
		||||
                    android:background="?attr/selectableItemBackgroundBorderless"
 | 
			
		||||
                    android:contentDescription="@string/custom_filter"
 | 
			
		||||
                    android:padding="@dimen/screen_edge_margin"
 | 
			
		||||
                    app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
                    app:layout_constraintStart_toEndOf="@id/action_settings"
 | 
			
		||||
                    app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
                    app:srcCompat="@drawable/ic_brightness_5_24dp"
 | 
			
		||||
                    app:tint="?attr/colorOnSurface" />
 | 
			
		||||
 | 
			
		||||
            </androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,269 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
    <androidx.constraintlayout.widget.ConstraintLayout
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
        <!-- Brightness -->
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.materialswitch.MaterialSwitch
 | 
			
		||||
            android:id="@+id/custom_brightness"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingHorizontal="16dp"
 | 
			
		||||
            android:paddingVertical="16dp"
 | 
			
		||||
            android:text="@string/pref_custom_brightness"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="parent" />
 | 
			
		||||
 | 
			
		||||
        <!-- Brightness value -->
 | 
			
		||||
 | 
			
		||||
        <androidx.appcompat.widget.AppCompatImageView
 | 
			
		||||
            android:id="@+id/txt_brightness_seekbar_icon"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingStart="16dp"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            android:tint="?attr/colorOnBackground"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_brightness"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_brightness"
 | 
			
		||||
            app:srcCompat="@drawable/ic_brightness_5_24dp" />
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.slider.Slider
 | 
			
		||||
            android:id="@+id/slider_brightness"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="8dp"
 | 
			
		||||
            android:layout_marginEnd="8dp"
 | 
			
		||||
            android:padding="8dp"
 | 
			
		||||
            android:valueFrom="-75.0"
 | 
			
		||||
            android:valueTo="100.0"
 | 
			
		||||
            android:stepSize="1.0"
 | 
			
		||||
            app:layout_constraintEnd_toStartOf="@id/txt_brightness_seekbar_value"
 | 
			
		||||
            app:layout_constraintStart_toEndOf="@id/txt_brightness_seekbar_icon"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/custom_brightness" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_brightness_seekbar_value"
 | 
			
		||||
            android:layout_width="30dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginEnd="16dp"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_brightness"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_brightness"
 | 
			
		||||
            tools:text="50" />
 | 
			
		||||
 | 
			
		||||
        <!-- Color filter -->
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.materialswitch.MaterialSwitch
 | 
			
		||||
            android:id="@+id/switch_color_filter"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingHorizontal="16dp"
 | 
			
		||||
            android:paddingVertical="16dp"
 | 
			
		||||
            android:text="@string/pref_custom_color_filter"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@+id/slider_brightness" />
 | 
			
		||||
 | 
			
		||||
        <!-- Red filter -->
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_red_symbol"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingStart="16dp"
 | 
			
		||||
            android:text="@string/color_filter_r_value"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_red"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_red" />
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.slider.Slider
 | 
			
		||||
            android:id="@+id/slider_color_filter_red"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="8dp"
 | 
			
		||||
            android:layout_marginEnd="8dp"
 | 
			
		||||
            android:stepSize="1.0"
 | 
			
		||||
            android:valueTo="255.0"
 | 
			
		||||
            android:padding="8dp"
 | 
			
		||||
            app:layout_constraintEnd_toStartOf="@id/txt_color_filter_red_value"
 | 
			
		||||
            app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/switch_color_filter" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_red_value"
 | 
			
		||||
            android:layout_width="30dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_alignParentEnd="true"
 | 
			
		||||
            android:layout_marginEnd="16dp"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_red"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_red"
 | 
			
		||||
            tools:text="255" />
 | 
			
		||||
 | 
			
		||||
        <!-- Green filter -->
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_green_symbol"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingStart="16dp"
 | 
			
		||||
            android:text="@string/color_filter_g_value"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_green"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_green" />
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.slider.Slider
 | 
			
		||||
            android:id="@+id/slider_color_filter_green"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="8dp"
 | 
			
		||||
            android:layout_marginEnd="8dp"
 | 
			
		||||
            android:stepSize="1.0"
 | 
			
		||||
            android:valueTo="255.0"
 | 
			
		||||
            android:padding="8dp"
 | 
			
		||||
            app:layout_constraintEnd_toStartOf="@id/txt_color_filter_green_value"
 | 
			
		||||
            app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/slider_color_filter_red" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_green_value"
 | 
			
		||||
            android:layout_width="30dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_alignParentEnd="true"
 | 
			
		||||
            android:layout_marginEnd="16dp"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_green"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_green"
 | 
			
		||||
            tools:text="255" />
 | 
			
		||||
 | 
			
		||||
        <!-- Blue filter -->
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_blue_symbol"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingStart="16dp"
 | 
			
		||||
            android:text="@string/color_filter_b_value"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_blue"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_blue" />
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.slider.Slider
 | 
			
		||||
            android:id="@+id/slider_color_filter_blue"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="8dp"
 | 
			
		||||
            android:layout_marginEnd="8dp"
 | 
			
		||||
            android:stepSize="1.0"
 | 
			
		||||
            android:valueTo="255.0"
 | 
			
		||||
            android:padding="8dp"
 | 
			
		||||
            app:layout_constraintEnd_toStartOf="@id/txt_color_filter_blue_value"
 | 
			
		||||
            app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/slider_color_filter_green" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_blue_value"
 | 
			
		||||
            android:layout_width="30dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_alignParentEnd="true"
 | 
			
		||||
            android:layout_marginEnd="16dp"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_blue"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_blue"
 | 
			
		||||
            tools:text="255" />
 | 
			
		||||
 | 
			
		||||
        <!-- Alpha filter -->
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_alpha_symbol"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingStart="16dp"
 | 
			
		||||
            android:text="@string/color_filter_a_value"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_alpha"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_alpha" />
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.slider.Slider
 | 
			
		||||
            android:id="@+id/slider_color_filter_alpha"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="8dp"
 | 
			
		||||
            android:layout_marginEnd="8dp"
 | 
			
		||||
            android:stepSize="1.0"
 | 
			
		||||
            android:valueTo="255.0"
 | 
			
		||||
            android:padding="8dp"
 | 
			
		||||
            app:layout_constraintEnd_toStartOf="@id/txt_color_filter_alpha_value"
 | 
			
		||||
            app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/slider_color_filter_blue" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/txt_color_filter_alpha_value"
 | 
			
		||||
            android:layout_width="30dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_alignParentEnd="true"
 | 
			
		||||
            android:layout_marginEnd="16dp"
 | 
			
		||||
            android:textAppearance="?attr/textAppearanceTitleSmall"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="@id/slider_color_filter_alpha"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/slider_color_filter_alpha"
 | 
			
		||||
            tools:text="255" />
 | 
			
		||||
 | 
			
		||||
        <!-- Filter mode -->
 | 
			
		||||
 | 
			
		||||
        <eu.kanade.tachiyomi.widget.MaterialSpinnerView
 | 
			
		||||
            android:id="@+id/color_filter_mode"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:entries="@array/color_filter_modes"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/slider_color_filter_alpha"
 | 
			
		||||
            app:title="@string/pref_color_filter_mode" />
 | 
			
		||||
 | 
			
		||||
        <!-- Grayscale -->
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.materialswitch.MaterialSwitch
 | 
			
		||||
            android:id="@+id/grayscale"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingHorizontal="16dp"
 | 
			
		||||
            android:paddingVertical="16dp"
 | 
			
		||||
            android:text="@string/pref_grayscale"
 | 
			
		||||
            android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/color_filter_mode" />
 | 
			
		||||
 | 
			
		||||
        <com.google.android.material.materialswitch.MaterialSwitch
 | 
			
		||||
            android:id="@+id/inverted_colors"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:paddingHorizontal="16dp"
 | 
			
		||||
            android:paddingVertical="16dp"
 | 
			
		||||
            android:text="@string/pref_inverted_colors"
 | 
			
		||||
            android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@id/grayscale" />
 | 
			
		||||
 | 
			
		||||
        <androidx.constraintlayout.widget.Barrier
 | 
			
		||||
            android:id="@+id/color_filter_symbols_barrier"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            app:barrierDirection="end"
 | 
			
		||||
            app:constraint_referenced_ids="txt_color_filter_alpha_symbol,txt_color_filter_blue_symbol,txt_color_filter_red_symbol,txt_color_filter_green_symbol" />
 | 
			
		||||
 | 
			
		||||
    </androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
 | 
			
		||||
</androidx.core.widget.NestedScrollView>
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<resources>
 | 
			
		||||
 | 
			
		||||
    <string-array name="color_filter_modes">
 | 
			
		||||
        <item>@string/label_default</item>
 | 
			
		||||
        <item>@string/filter_mode_multiply</item>
 | 
			
		||||
        <item>@string/filter_mode_screen</item>
 | 
			
		||||
 | 
			
		||||
        <!-- Attributes specific for SDK 28 and up  -->
 | 
			
		||||
        <item>@string/filter_mode_overlay</item>
 | 
			
		||||
        <item>@string/filter_mode_lighten</item>
 | 
			
		||||
        <item>@string/filter_mode_darken</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
 | 
			
		||||
</resources>
 | 
			
		||||
@@ -67,12 +67,6 @@
 | 
			
		||||
        <item>@string/rotation_reverse_portrait</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
 | 
			
		||||
    <string-array name="color_filter_modes">
 | 
			
		||||
        <item>@string/label_default</item>
 | 
			
		||||
        <item>@string/filter_mode_multiply</item>
 | 
			
		||||
        <item>@string/filter_mode_screen</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
 | 
			
		||||
    <string-array name="invert_tapping_mode">
 | 
			
		||||
        <item>@string/tapping_inverted_none</item>
 | 
			
		||||
        <item>@string/tapping_inverted_horizontal</item>
 | 
			
		||||
 
 | 
			
		||||
@@ -140,7 +140,7 @@ fun RadioItem(
 | 
			
		||||
@Composable
 | 
			
		||||
fun SliderItem(
 | 
			
		||||
    label: String,
 | 
			
		||||
    min: Int,
 | 
			
		||||
    min: Int = 0,
 | 
			
		||||
    max: Int,
 | 
			
		||||
    value: Int,
 | 
			
		||||
    valueText: String,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user