diff --git a/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt b/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt deleted file mode 100644 index b945906a4..000000000 --- a/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt +++ /dev/null @@ -1,27 +0,0 @@ -package eu.kanade.presentation.reader - -import androidx.annotation.IntRange -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.graphicsLayer -import kotlin.math.abs - -@Composable -fun BrightnessOverlay( - @IntRange(from = -100, to = 100) value: Int, -) { - if (value >= 0) return - - Canvas( - modifier = Modifier - .fillMaxSize() - .graphicsLayer { - alpha = abs(value) / 100f - }, - ) { - drawRect(Color.Black) - } -} diff --git a/app/src/main/java/eu/kanade/presentation/reader/ReaderContentOverlay.kt b/app/src/main/java/eu/kanade/presentation/reader/ReaderContentOverlay.kt new file mode 100644 index 000000000..a1ef26222 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/reader/ReaderContentOverlay.kt @@ -0,0 +1,43 @@ +package eu.kanade.presentation.reader + +import androidx.annotation.ColorInt +import androidx.annotation.IntRange +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import kotlin.math.abs + +@Composable +fun ReaderContentOverlay( + @IntRange(from = -100, to = 100) brightness: Int, + @ColorInt color: Int?, + colorBlendMode: BlendMode? = BlendMode.SrcOver, +) { + if (brightness < 0) { + Canvas( + modifier = Modifier + .fillMaxSize() + .graphicsLayer { + alpha = abs(brightness) / 100f + }, + ) { + drawRect(Color.Black) + } + } + + if (color != null) { + Canvas( + modifier = Modifier + .fillMaxSize(), + ) { + drawRect( + color = Color(color), + blendMode = colorBlendMode, + ) + } + } +} diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt index 1e7324956..1c5a9c6fb 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.reader.settings -import android.os.Build import androidx.compose.foundation.layout.ColumnScope import androidx.compose.material3.FilterChip import androidx.compose.material3.Text @@ -10,6 +9,7 @@ import androidx.core.graphics.alpha import androidx.core.graphics.blue import androidx.core.graphics.green import androidx.core.graphics.red +import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.Companion.ColorFilterMode import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import tachiyomi.core.preference.getAndSet import tachiyomi.i18n.MR @@ -21,25 +21,6 @@ import tachiyomi.presentation.core.util.collectAsState @Composable internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) { - val colorFilterModes = buildList { - addAll( - listOf( - MR.strings.label_default, - MR.strings.filter_mode_multiply, - MR.strings.filter_mode_screen, - ), - ) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - addAll( - listOf( - MR.strings.filter_mode_overlay, - MR.strings.filter_mode_lighten, - MR.strings.filter_mode_darken, - ), - ) - } - }.map { stringResource(it) } - val customBrightness by screenModel.preferences.customBrightness().collectAsState() CheckboxItem( label = stringResource(MR.strings.pref_custom_brightness), @@ -118,11 +99,11 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) val colorFilterMode by screenModel.preferences.colorFilterMode().collectAsState() SettingsChipRow(MR.strings.pref_color_filter_mode) { - colorFilterModes.mapIndexed { index, it -> + ColorFilterMode.mapIndexed { index, it -> FilterChip( selected = colorFilterMode == index, onClick = { screenModel.preferences.colorFilterMode().set(index) }, - label = { Text(it) }, + label = { Text(stringResource(it.first)) }, ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index c70ac7998..701c804f3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -34,17 +34,16 @@ import androidx.core.transition.doOnEnd import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.google.android.material.elevation.SurfaceColors import com.google.android.material.transition.platform.MaterialContainerTransform import dev.chrisbanes.insetter.applyInsetter import eu.kanade.domain.base.BasePreferences -import eu.kanade.presentation.reader.BrightnessOverlay import eu.kanade.presentation.reader.DisplayRefreshHost import eu.kanade.presentation.reader.OrientationSelectDialog import eu.kanade.presentation.reader.PageIndicatorText +import eu.kanade.presentation.reader.ReaderContentOverlay import eu.kanade.presentation.reader.ReaderPageActionsDialog import eu.kanade.presentation.reader.ReadingModeSelectDialog import eu.kanade.presentation.reader.appbars.ReaderAppBars @@ -337,11 +336,24 @@ class ReaderActivity : BaseActivity() { val isFullscreen by readerPreferences.fullscreen().collectAsState() val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState() + val colorOverlayEnabled by readerPreferences.colorFilter().collectAsState() + val colorOverlay by readerPreferences.colorFilterValue().collectAsState() + val colorOverlayMode by readerPreferences.colorFilterMode().collectAsState() + val colorOverlayBlendMode = remember(colorOverlayMode) { + ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second + } + val cropBorderPaged by readerPreferences.cropBorders().collectAsState() val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState() val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode()) val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon + ReaderContentOverlay( + brightness = state.brightnessOverlayValue, + color = colorOverlay.takeIf { colorOverlayEnabled }, + colorBlendMode = colorOverlayBlendMode, + ) + ReaderAppBars( visible = state.menuVisible, fullscreen = isFullscreen, @@ -385,10 +397,6 @@ class ReaderActivity : BaseActivity() { onClickSettings = viewModel::openSettingsDialog, ) - BrightnessOverlay( - value = state.brightnessOverlayValue, - ) - if (flashOnPageChange) { DisplayRefreshHost( hostState = displayRefreshHost, @@ -812,24 +820,8 @@ class ReaderActivity : BaseActivity() { .onEach(::setCustomBrightness) .launchIn(lifecycleScope) - readerPreferences.colorFilter().changes() - .onEach(::setColorFilter) - .launchIn(lifecycleScope) - - readerPreferences.colorFilterMode().changes() - .onEach { setColorFilter(readerPreferences.colorFilter().get()) } - .launchIn(lifecycleScope) - - merge( - readerPreferences.grayscale().changes(), - readerPreferences.invertedColors().changes(), - ) - .onEach { - setLayerPaint( - readerPreferences.grayscale().get(), - readerPreferences.invertedColors().get(), - ) - } + merge(readerPreferences.grayscale().changes(), readerPreferences.invertedColors().changes()) + .onEach { setLayerPaint(readerPreferences.grayscale().get(), readerPreferences.invertedColors().get()) } .launchIn(lifecycleScope) readerPreferences.fullscreen().changes() @@ -899,20 +891,6 @@ class ReaderActivity : BaseActivity() { } } - /** - * Sets the color filter overlay according to [enabled]. - */ - private fun setColorFilter(enabled: Boolean) { - if (enabled) { - readerPreferences.colorFilterValue().changes() - .sample(100) - .onEach(::setColorFilterValue) - .launchIn(lifecycleScope) - } else { - binding.colorOverlay.isVisible = false - } - } - /** * Sets the brightness of the screen. Range is [-75, 100]. * From -75 to -1 a semi-transparent black view is overlaid with the minimum brightness. @@ -934,15 +912,6 @@ class ReaderActivity : BaseActivity() { viewModel.setBrightnessOverlayValue(value) } - - /** - * Sets the color filter [value]. - */ - private fun setColorFilterValue(value: Int) { - binding.colorOverlay.isVisible = true - binding.colorOverlay.setFilterColor(value, readerPreferences.colorFilterMode().get()) - } - private fun setLayerPaint(grayscale: Boolean, invertedColors: Boolean) { val paint = if (grayscale || invertedColors) getCombinedPaint(grayscale, invertedColors) else null binding.viewerContainer.setLayerType(LAYER_TYPE_HARDWARE, paint) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterView.kt deleted file mode 100644 index 6266ab239..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterView.kt +++ /dev/null @@ -1,36 +0,0 @@ -package eu.kanade.tachiyomi.ui.reader - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.PorterDuff -import android.util.AttributeSet -import android.view.View -import androidx.core.graphics.toXfermode - -class ReaderColorFilterView( - context: Context, - attrs: AttributeSet? = null, -) : View(context, attrs) { - - private val colorFilterPaint: Paint = Paint() - - fun setFilterColor(color: Int, filterMode: Int) { - colorFilterPaint.color = color - colorFilterPaint.xfermode = when (filterMode) { - 1 -> PorterDuff.Mode.MULTIPLY - 2 -> PorterDuff.Mode.SCREEN - 3 -> PorterDuff.Mode.OVERLAY - 4 -> PorterDuff.Mode.LIGHTEN - 5 -> PorterDuff.Mode.DARKEN - else -> PorterDuff.Mode.SRC_OVER - }.toXfermode() - - invalidate() - } - - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - canvas.drawPaint(colorFilterPaint) - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt index 59ab00d00..95faea7d1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt @@ -1,5 +1,7 @@ package eu.kanade.tachiyomi.ui.reader.setting +import android.os.Build +import androidx.compose.ui.graphics.BlendMode import dev.icerock.moko.resources.StringResource import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.getEnum @@ -217,5 +219,24 @@ class ReaderPreferences( MR.strings.zoom_start_right, MR.strings.zoom_start_center, ) + + val ColorFilterMode = buildList { + addAll( + listOf( + MR.strings.label_default to BlendMode.SrcOver, + MR.strings.filter_mode_multiply to BlendMode.Modulate, + MR.strings.filter_mode_screen to BlendMode.Screen, + ), + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + addAll( + listOf( + MR.strings.filter_mode_overlay to BlendMode.Overlay, + MR.strings.filter_mode_lighten to BlendMode.Lighten, + MR.strings.filter_mode_darken to BlendMode.Darken, + ), + ) + } + } } } diff --git a/app/src/main/res/layout/reader_activity.xml b/app/src/main/res/layout/reader_activity.xml index 331e89649..2969e103b 100644 --- a/app/src/main/res/layout/reader_activity.xml +++ b/app/src/main/res/layout/reader_activity.xml @@ -22,12 +22,6 @@ - -