Color inversion in pages color filter #372

pull/377/head
Koitharu 3 years ago
parent b1187c611a
commit 8c5c7d6b04
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -24,6 +24,7 @@ import org.koitharu.kotatsu.core.db.migrations.Migration11To12
import org.koitharu.kotatsu.core.db.migrations.Migration12To13 import org.koitharu.kotatsu.core.db.migrations.Migration12To13
import org.koitharu.kotatsu.core.db.migrations.Migration13To14 import org.koitharu.kotatsu.core.db.migrations.Migration13To14
import org.koitharu.kotatsu.core.db.migrations.Migration14To15 import org.koitharu.kotatsu.core.db.migrations.Migration14To15
import org.koitharu.kotatsu.core.db.migrations.Migration15To16
import org.koitharu.kotatsu.core.db.migrations.Migration1To2 import org.koitharu.kotatsu.core.db.migrations.Migration1To2
import org.koitharu.kotatsu.core.db.migrations.Migration2To3 import org.koitharu.kotatsu.core.db.migrations.Migration2To3
import org.koitharu.kotatsu.core.db.migrations.Migration3To4 import org.koitharu.kotatsu.core.db.migrations.Migration3To4
@ -48,7 +49,7 @@ import org.koitharu.kotatsu.tracker.data.TrackEntity
import org.koitharu.kotatsu.tracker.data.TrackLogEntity import org.koitharu.kotatsu.tracker.data.TrackLogEntity
import org.koitharu.kotatsu.tracker.data.TracksDao import org.koitharu.kotatsu.tracker.data.TracksDao
const val DATABASE_VERSION = 15 const val DATABASE_VERSION = 16
@Database( @Database(
entities = [ entities = [
@ -100,6 +101,7 @@ val databaseMigrations: Array<Migration>
Migration12To13(), Migration12To13(),
Migration13To14(), Migration13To14(),
Migration14To15(), Migration14To15(),
Migration15To16(),
) )
fun MangaDatabase(context: Context): MangaDatabase = Room fun MangaDatabase(context: Context): MangaDatabase = Room

@ -23,4 +23,5 @@ data class MangaPrefsEntity(
@ColumnInfo(name = "mode") val mode: Int, @ColumnInfo(name = "mode") val mode: Int,
@ColumnInfo(name = "cf_brightness") val cfBrightness: Float, @ColumnInfo(name = "cf_brightness") val cfBrightness: Float,
@ColumnInfo(name = "cf_contrast") val cfContrast: Float, @ColumnInfo(name = "cf_contrast") val cfContrast: Float,
@ColumnInfo(name = "cf_invert") val cfInvert: Boolean,
) )

@ -0,0 +1,11 @@
package org.koitharu.kotatsu.core.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration15To16 : Migration(15, 16) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE preferences ADD COLUMN `cf_invert` INTEGER NOT NULL DEFAULT 0")
}
}

@ -5,14 +5,12 @@ import dagger.Reusable
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import okhttp3.OkHttpClient
import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity
import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntities
import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.db.entity.toEntity
import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toManga
import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.core.db.entity.toMangaTags
import org.koitharu.kotatsu.core.network.MangaHttpClient
import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
@ -22,7 +20,6 @@ import javax.inject.Inject
@Reusable @Reusable
class MangaDataRepository @Inject constructor( class MangaDataRepository @Inject constructor(
@MangaHttpClient private val okHttpClient: OkHttpClient,
private val db: MangaDatabase, private val db: MangaDatabase,
) { ) {
@ -42,6 +39,7 @@ class MangaDataRepository @Inject constructor(
entity.copy( entity.copy(
cfBrightness = colorFilter?.brightness ?: 0f, cfBrightness = colorFilter?.brightness ?: 0f,
cfContrast = colorFilter?.contrast ?: 0f, cfContrast = colorFilter?.contrast ?: 0f,
cfInvert = colorFilter?.isInverted ?: false,
), ),
) )
} }
@ -84,8 +82,8 @@ class MangaDataRepository @Inject constructor(
} }
private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? { private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? {
return if (cfBrightness != 0f || cfContrast != 0f) { return if (cfBrightness != 0f || cfContrast != 0f || cfInvert) {
ReaderColorFilter(cfBrightness, cfContrast) ReaderColorFilter(cfBrightness, cfContrast, cfInvert)
} else { } else {
null null
} }
@ -96,5 +94,6 @@ class MangaDataRepository @Inject constructor(
mode = -1, mode = -1,
cfBrightness = 0f, cfBrightness = 0f,
cfContrast = 0f, cfContrast = 0f,
cfInvert = false,
) )
} }

@ -6,19 +6,52 @@ import android.graphics.ColorMatrixColorFilter
class ReaderColorFilter( class ReaderColorFilter(
val brightness: Float, val brightness: Float,
val contrast: Float, val contrast: Float,
val isInverted: Boolean,
) { ) {
val isEmpty: Boolean val isEmpty: Boolean
get() = brightness == 0f && contrast == 0f get() = !isInverted && brightness == 0f && contrast == 0f
fun toColorFilter(): ColorMatrixColorFilter { fun toColorFilter(): ColorMatrixColorFilter {
val cm = ColorMatrix() val cm = ColorMatrix()
val scale = brightness + 1f if (isInverted) {
cm.setScale(scale, scale, scale, 1f) cm.inverted()
}
cm.setBrightness(brightness)
cm.setContrast(contrast) cm.setContrast(contrast)
return ColorMatrixColorFilter(cm) return ColorMatrixColorFilter(cm)
} }
private fun ColorMatrix.setBrightness(brightness: Float) {
val scale = brightness + 1f
val matrix = ColorMatrix()
matrix.setScale(scale, scale, scale, 1f)
postConcat(matrix)
}
private fun ColorMatrix.setContrast(contrast: Float) {
val scale = contrast + 1f
val translate = (-.5f * scale + .5f) * 255f
val array = floatArrayOf(
scale, 0f, 0f, 0f, translate,
0f, scale, 0f, 0f, translate,
0f, 0f, scale, 0f, translate,
0f, 0f, 0f, 1f, 0f,
)
val matrix = ColorMatrix(array)
postConcat(matrix)
}
private fun ColorMatrix.inverted() {
val matrix = floatArrayOf(
-1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
)
set(matrix)
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false
@ -27,26 +60,13 @@ class ReaderColorFilter(
if (brightness != other.brightness) return false if (brightness != other.brightness) return false
if (contrast != other.contrast) return false if (contrast != other.contrast) return false
return isInverted == other.isInverted
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = brightness.hashCode() var result = brightness.hashCode()
result = 31 * result + contrast.hashCode() result = 31 * result + contrast.hashCode()
result = 31 * result + isInverted.hashCode()
return result return result
} }
private fun ColorMatrix.setContrast(contrast: Float) {
val scale = contrast + 1f
val translate = (-.5f * scale + .5f) * 255f
val array = floatArrayOf(
scale, 0f, 0f, 0f, translate,
0f, scale, 0f, 0f, translate,
0f, 0f, scale, 0f, translate,
0f, 0f, 0f, 1f, 0f,
)
val matrix = ColorMatrix(array)
postConcat(matrix)
}
} }

@ -6,6 +6,7 @@ import android.content.res.Resources
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@ -26,6 +27,7 @@ import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.indicator import org.koitharu.kotatsu.core.util.ext.indicator
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setChecked
import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.core.util.ext.setValueRounded
import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
@ -39,7 +41,7 @@ import com.google.android.material.R as materialR
class ColorFilterConfigActivity : class ColorFilterConfigActivity :
BaseActivity<ActivityColorFilterBinding>(), BaseActivity<ActivityColorFilterBinding>(),
Slider.OnChangeListener, Slider.OnChangeListener,
View.OnClickListener { View.OnClickListener, CompoundButton.OnCheckedChangeListener {
@Inject @Inject
lateinit var coil: ImageLoader lateinit var coil: ImageLoader
@ -58,6 +60,7 @@ class ColorFilterConfigActivity :
val formatter = PercentLabelFormatter(resources) val formatter = PercentLabelFormatter(resources)
viewBinding.sliderContrast.setLabelFormatter(formatter) viewBinding.sliderContrast.setLabelFormatter(formatter)
viewBinding.sliderBrightness.setLabelFormatter(formatter) viewBinding.sliderBrightness.setLabelFormatter(formatter)
viewBinding.switchInvert.setOnCheckedChangeListener(this)
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)
viewBinding.buttonReset.setOnClickListener(this) viewBinding.buttonReset.setOnClickListener(this)
@ -80,6 +83,10 @@ class ColorFilterConfigActivity :
} }
} }
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
viewModel.setInversion(isChecked)
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_done -> viewModel.save() R.id.button_done -> viewModel.save()
@ -103,13 +110,14 @@ class ColorFilterConfigActivity :
private fun onColorFilterChanged(readerColorFilter: ReaderColorFilter?) { private fun onColorFilterChanged(readerColorFilter: ReaderColorFilter?) {
viewBinding.sliderBrightness.setValueRounded(readerColorFilter?.brightness ?: 0f) viewBinding.sliderBrightness.setValueRounded(readerColorFilter?.brightness ?: 0f)
viewBinding.sliderContrast.setValueRounded(readerColorFilter?.contrast ?: 0f) viewBinding.sliderContrast.setValueRounded(readerColorFilter?.contrast ?: 0f)
viewBinding.switchInvert.setChecked(readerColorFilter?.isInverted ?: false, false)
viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter() viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter()
} }
private fun onPreviewChanged(preview: MangaPage?) { private fun onPreviewChanged(preview: MangaPage?) {
if (preview == null) return if (preview == null) return
ImageRequest.Builder(this@ColorFilterConfigActivity) ImageRequest.Builder(this@ColorFilterConfigActivity)
.data(preview.url) .data(preview)
.scale(Scale.FILL) .scale(Scale.FILL)
.decodeRegion() .decodeRegion()
.tag(preview.source) .tag(preview.source)
@ -117,7 +125,7 @@ class ColorFilterConfigActivity :
.error(R.drawable.ic_error_placeholder) .error(R.drawable.ic_error_placeholder)
.size(ViewSizeResolver(viewBinding.imageViewBefore)) .size(ViewSizeResolver(viewBinding.imageViewBefore))
.allowRgb565(false) .allowRgb565(false)
.target(ShadowViewTarget(viewBinding.imageViewBefore, viewBinding.imageViewAfter)) .target(DoubleViewTarget(viewBinding.imageViewBefore, viewBinding.imageViewAfter))
.enqueueWith(coil) .enqueueWith(coil)
} }

@ -55,12 +55,32 @@ class ColorFilterConfigViewModel @Inject constructor(
fun setBrightness(brightness: Float) { fun setBrightness(brightness: Float) {
val cf = colorFilter.value val cf = colorFilter.value
colorFilter.value = ReaderColorFilter(brightness, cf?.contrast ?: 0f).takeUnless { it.isEmpty } colorFilter.value = ReaderColorFilter(
brightness = brightness,
contrast = cf?.contrast ?: 0f,
isInverted = cf?.isInverted ?: false,
).takeUnless { it.isEmpty }
} }
fun setContrast(contrast: Float) { fun setContrast(contrast: Float) {
val cf = colorFilter.value val cf = colorFilter.value
colorFilter.value = ReaderColorFilter(cf?.brightness ?: 0f, contrast).takeUnless { it.isEmpty } colorFilter.value = ReaderColorFilter(
brightness = cf?.brightness ?: 0f,
contrast = contrast,
isInverted = cf?.isInverted ?: false,
).takeUnless { it.isEmpty }
}
fun setInversion(invert: Boolean) {
val cf = colorFilter.value
if (invert == cf?.isInverted) {
return
}
colorFilter.value = ReaderColorFilter(
brightness = cf?.brightness ?: 0f,
contrast = cf?.contrast ?: 0f,
isInverted = invert,
).takeUnless { it.isEmpty }
} }
fun reset() { fun reset() {

@ -4,15 +4,15 @@ import android.graphics.drawable.Drawable
import android.widget.ImageView import android.widget.ImageView
import coil.target.ImageViewTarget import coil.target.ImageViewTarget
class ShadowViewTarget( class DoubleViewTarget(
view: ImageView, primaryView: ImageView,
private val shadowView: ImageView, private val secondaryView: ImageView,
) : ImageViewTarget(view) { ) : ImageViewTarget(primaryView) {
override var drawable: Drawable? override var drawable: Drawable?
get() = super.drawable get() = super.drawable
set(value) { set(value) {
super.drawable = value super.drawable = value
shadowView.setImageDrawable(value?.constantState?.newDrawable()) secondaryView.setImageDrawable(value?.constantState?.newDrawable())
} }
} }

@ -26,7 +26,7 @@ class ReaderSettings(
get() = settings.zoomMode get() = settings.zoomMode
val colorFilter: ReaderColorFilter? val colorFilter: ReaderColorFilter?
get() = colorFilterFlow.value get() = colorFilterFlow.value?.takeUnless { it.isEmpty }
val isPagesNumbersEnabled: Boolean val isPagesNumbersEnabled: Boolean
get() = settings.isPagesNumbersEnabled get() = settings.isPagesNumbersEnabled

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
tools:navigationIcon="@drawable/abc_ic_clear_material"
tools:title="@string/color_correction">
<Button
android:id="@+id/button_done"
style="@style/Widget.Material3.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="@dimen/toolbar_button_margin"
android:text="@string/done" />
<Button
android:id="@+id/button_reset"
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginHorizontal="@dimen/toolbar_button_margin"
android:text="@string/reset" />
</com.google.android.material.appbar.MaterialToolbar>
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:overScrollMode="ifContentScrolls">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/margin_normal">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_before"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="2dp"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="W,14:9"
app:layout_constraintEnd_toStartOf="@id/imageView_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="?shapeAppearanceCornerLarge"
app:strokeColor="?colorOutline"
app:strokeWidth="1dp"
tools:src="@tools:sample/backgrounds/scenic" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progress_before"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="@id/imageView_before"
app:layout_constraintEnd_toEndOf="@id/imageView_before"
app:layout_constraintStart_toStartOf="@id/imageView_before"
app:layout_constraintTop_toTopOf="@id/imageView_before" />
<ImageView
android:id="@+id/imageView_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:padding="@dimen/margin_normal"
android:src="@drawable/ic_arrow_forward"
app:layout_constraintBottom_toBottomOf="@id/imageView_before"
app:layout_constraintEnd_toEndOf="@id/guideline_vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/imageView_before" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_after"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="2dp"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="W,14:9"
app:layout_constraintEnd_toStartOf="@id/guideline_vertical"
app:layout_constraintStart_toEndOf="@id/imageView_arrow"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="?shapeAppearanceCornerLarge"
app:strokeColor="?colorOutline"
app:strokeWidth="1dp"
tools:src="@tools:sample/backgrounds/scenic" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progress_after"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="@id/imageView_after"
app:layout_constraintEnd_toEndOf="@id/imageView_after"
app:layout_constraintStart_toStartOf="@id/imageView_after"
app:layout_constraintTop_toTopOf="@id/imageView_after" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_invert"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:text="@string/invert_colors"
android:textAppearance="?textAppearanceTitleMedium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView_brightness"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_normal"
android:text="@string/brightness"
android:textAppearance="?textAppearanceTitleMedium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
app:layout_constraintTop_toBottomOf="@id/switch_invert" />
<com.google.android.material.slider.Slider
android:id="@+id/slider_brightness"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_small"
android:labelFor="@id/textView_brightness"
android:value="0.0"
android:valueFrom="-1.0"
android:valueTo="1.0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
app:layout_constraintTop_toBottomOf="@id/textView_brightness" />
<TextView
android:id="@+id/textView_contrast"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_small"
android:text="@string/contrast"
android:textAppearance="?textAppearanceTitleMedium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
app:layout_constraintTop_toBottomOf="@id/slider_brightness" />
<com.google.android.material.slider.Slider
android:id="@+id/slider_contrast"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_small"
android:value="0.0"
android:valueFrom="-1.0"
android:valueTo="1.0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
app:layout_constraintTop_toBottomOf="@id/textView_contrast" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_normal"
android:text="@string/color_correction_hint"
android:textAppearance="?textAppearanceBodySmall"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
app:layout_constraintTop_toBottomOf="@id/slider_contrast" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</LinearLayout>

@ -100,6 +100,17 @@
app:layout_constraintStart_toStartOf="@id/imageView_after" app:layout_constraintStart_toStartOf="@id/imageView_after"
app:layout_constraintTop_toTopOf="@id/imageView_after" /> app:layout_constraintTop_toTopOf="@id/imageView_after" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_invert"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/invert_colors"
android:textAppearance="?textAppearanceTitleMedium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView_before" />
<TextView <TextView
android:id="@+id/textView_brightness" android:id="@+id/textView_brightness"
android:layout_width="0dp" android:layout_width="0dp"
@ -109,7 +120,7 @@
android:textAppearance="?textAppearanceTitleMedium" android:textAppearance="?textAppearanceTitleMedium"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView_before" /> app:layout_constraintTop_toBottomOf="@id/switch_invert" />
<com.google.android.material.slider.Slider <com.google.android.material.slider.Slider
android:id="@+id/slider_brightness" android:id="@+id/slider_brightness"

@ -428,4 +428,5 @@
<string name="downloaded">Downloaded</string> <string name="downloaded">Downloaded</string>
<string name="images_proxy_title">Images optimization proxy</string> <string name="images_proxy_title">Images optimization proxy</string>
<string name="images_procy_description">Use the wsrv.nl service to reduce traffic usage and speed up image loading if possible</string> <string name="images_procy_description">Use the wsrv.nl service to reduce traffic usage and speed up image loading if possible</string>
<string name="invert_colors">Invert colors</string>
</resources> </resources>

Loading…
Cancel
Save