Grayscale color filter
This commit is contained in:
@@ -29,6 +29,7 @@ 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.Migration15To16
|
||||||
import org.koitharu.kotatsu.core.db.migrations.Migration16To17
|
import org.koitharu.kotatsu.core.db.migrations.Migration16To17
|
||||||
|
import org.koitharu.kotatsu.core.db.migrations.Migration17To18
|
||||||
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
|
||||||
@@ -53,7 +54,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 = 17
|
const val DATABASE_VERSION = 18
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [
|
entities = [
|
||||||
@@ -108,6 +109,7 @@ fun getDatabaseMigrations(context: Context): Array<Migration> = arrayOf(
|
|||||||
Migration14To15(),
|
Migration14To15(),
|
||||||
Migration15To16(),
|
Migration15To16(),
|
||||||
Migration16To17(context),
|
Migration16To17(context),
|
||||||
|
Migration17To18(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun MangaDatabase(context: Context): MangaDatabase = Room
|
fun MangaDatabase(context: Context): MangaDatabase = Room
|
||||||
|
|||||||
@@ -24,4 +24,5 @@ data class MangaPrefsEntity(
|
|||||||
@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,
|
@ColumnInfo(name = "cf_invert") val cfInvert: Boolean,
|
||||||
|
@ColumnInfo(name = "cf_grayscale") val cfGrayscale: Boolean,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.koitharu.kotatsu.core.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration17To18 : Migration(17, 18) {
|
||||||
|
|
||||||
|
override fun migrate(db: SupportSQLiteDatabase) {
|
||||||
|
db.execSQL("ALTER TABLE preferences ADD COLUMN `cf_grayscale` INTEGER NOT NULL DEFAULT 0")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -98,8 +98,8 @@ class MangaDataRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? {
|
private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? {
|
||||||
return if (cfBrightness != 0f || cfContrast != 0f || cfInvert) {
|
return if (cfBrightness != 0f || cfContrast != 0f || cfInvert || cfGrayscale) {
|
||||||
ReaderColorFilter(cfBrightness, cfContrast, cfInvert)
|
ReaderColorFilter(cfBrightness, cfContrast, cfInvert, cfGrayscale)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -111,5 +111,6 @@ class MangaDataRepository @Inject constructor(
|
|||||||
cfBrightness = 0f,
|
cfBrightness = 0f,
|
||||||
cfContrast = 0f,
|
cfContrast = 0f,
|
||||||
cfInvert = false,
|
cfInvert = false,
|
||||||
|
cfGrayscale = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,22 +301,19 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
|
|
||||||
var readerColorFilter: ReaderColorFilter?
|
var readerColorFilter: ReaderColorFilter?
|
||||||
get() {
|
get() {
|
||||||
if (!prefs.getBoolean(KEY_CF_ENABLED, false)) {
|
val brightness = prefs.getFloat(KEY_CF_BRIGHTNESS, ReaderColorFilter.EMPTY.brightness)
|
||||||
return null
|
val contrast = prefs.getFloat(KEY_CF_CONTRAST, ReaderColorFilter.EMPTY.contrast)
|
||||||
}
|
val inverted = prefs.getBoolean(KEY_CF_INVERTED, ReaderColorFilter.EMPTY.isInverted)
|
||||||
val brightness = prefs.getFloat(KEY_CF_BRIGHTNESS, 0f)
|
val grayscale = prefs.getBoolean(KEY_CF_GRAYSCALE, ReaderColorFilter.EMPTY.isGrayscale)
|
||||||
val contrast = prefs.getFloat(KEY_CF_CONTRAST, 0f)
|
return ReaderColorFilter(brightness, contrast, inverted, grayscale).takeUnless { it.isEmpty }
|
||||||
val inverted = prefs.getBoolean(KEY_CF_INVERTED, false)
|
|
||||||
return ReaderColorFilter(brightness, contrast, inverted)
|
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
prefs.edit {
|
prefs.edit {
|
||||||
putBoolean(KEY_CF_ENABLED, value != null)
|
val cf = value ?: ReaderColorFilter.EMPTY
|
||||||
if (value != null) {
|
putFloat(KEY_CF_BRIGHTNESS, cf.brightness)
|
||||||
putFloat(KEY_CF_BRIGHTNESS, value.brightness)
|
putFloat(KEY_CF_CONTRAST, cf.contrast)
|
||||||
putFloat(KEY_CF_CONTRAST, value.contrast)
|
putBoolean(KEY_CF_INVERTED, cf.isInverted)
|
||||||
putBoolean(KEY_CF_INVERTED, value.isInverted)
|
putBoolean(KEY_CF_GRAYSCALE, cf.isGrayscale)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,10 +570,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
const val KEY_32BIT_COLOR = "enhanced_colors"
|
const val KEY_32BIT_COLOR = "enhanced_colors"
|
||||||
const val KEY_SOURCES_ORDER = "sources_sort_order"
|
const val KEY_SOURCES_ORDER = "sources_sort_order"
|
||||||
const val KEY_SOURCES_CATALOG = "sources_catalog"
|
const val KEY_SOURCES_CATALOG = "sources_catalog"
|
||||||
const val KEY_CF_ENABLED = "cf_enabled"
|
|
||||||
const val KEY_CF_BRIGHTNESS = "cf_brightness"
|
const val KEY_CF_BRIGHTNESS = "cf_brightness"
|
||||||
const val KEY_CF_CONTRAST = "cf_contrast"
|
const val KEY_CF_CONTRAST = "cf_contrast"
|
||||||
const val KEY_CF_INVERTED = "cf_inverted"
|
const val KEY_CF_INVERTED = "cf_inverted"
|
||||||
|
const val KEY_CF_GRAYSCALE = "cf_grayscale"
|
||||||
|
|
||||||
// About
|
// About
|
||||||
const val KEY_APP_UPDATE = "app_update"
|
const val KEY_APP_UPDATE = "app_update"
|
||||||
|
|||||||
@@ -7,13 +7,17 @@ data class ReaderColorFilter(
|
|||||||
val brightness: Float,
|
val brightness: Float,
|
||||||
val contrast: Float,
|
val contrast: Float,
|
||||||
val isInverted: Boolean,
|
val isInverted: Boolean,
|
||||||
|
val isGrayscale: Boolean,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val isEmpty: Boolean
|
val isEmpty: Boolean
|
||||||
get() = !isInverted && brightness == 0f && contrast == 0f
|
get() = !isGrayscale && !isInverted && brightness == 0f && contrast == 0f
|
||||||
|
|
||||||
fun toColorFilter(): ColorMatrixColorFilter {
|
fun toColorFilter(): ColorMatrixColorFilter {
|
||||||
val cm = ColorMatrix()
|
val cm = ColorMatrix()
|
||||||
|
if (isGrayscale) {
|
||||||
|
cm.grayscale()
|
||||||
|
}
|
||||||
if (isInverted) {
|
if (isInverted) {
|
||||||
cm.inverted()
|
cm.inverted()
|
||||||
}
|
}
|
||||||
@@ -49,6 +53,20 @@ data class ReaderColorFilter(
|
|||||||
0.0f, 0.0f, -1.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,
|
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
)
|
)
|
||||||
set(matrix)
|
postConcat(ColorMatrix(matrix))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ColorMatrix.grayscale() {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val EMPTY = ReaderColorFilter(
|
||||||
|
brightness = 0.0f,
|
||||||
|
contrast = 0.0f,
|
||||||
|
isInverted = false,
|
||||||
|
isGrayscale = false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import coil.ImageLoader
|
|||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.size.Scale
|
import coil.size.Scale
|
||||||
import coil.size.ViewSizeResolver
|
import coil.size.ViewSizeResolver
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.slider.LabelFormatter
|
import com.google.android.material.slider.LabelFormatter
|
||||||
import com.google.android.material.slider.Slider
|
import com.google.android.material.slider.Slider
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -62,6 +63,7 @@ class ColorFilterConfigActivity :
|
|||||||
viewBinding.sliderContrast.setLabelFormatter(formatter)
|
viewBinding.sliderContrast.setLabelFormatter(formatter)
|
||||||
viewBinding.sliderBrightness.setLabelFormatter(formatter)
|
viewBinding.sliderBrightness.setLabelFormatter(formatter)
|
||||||
viewBinding.switchInvert.setOnCheckedChangeListener(this)
|
viewBinding.switchInvert.setOnCheckedChangeListener(this)
|
||||||
|
viewBinding.switchGrayscale.setOnCheckedChangeListener(this)
|
||||||
viewBinding.buttonDone.setOnClickListener(this)
|
viewBinding.buttonDone.setOnClickListener(this)
|
||||||
viewBinding.buttonReset.setOnClickListener(this)
|
viewBinding.buttonReset.setOnClickListener(this)
|
||||||
|
|
||||||
@@ -84,18 +86,16 @@ class ColorFilterConfigActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
|
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
|
||||||
viewModel.setInversion(isChecked)
|
when (buttonView.id) {
|
||||||
|
R.id.switch_invert -> viewModel.setInversion(isChecked)
|
||||||
|
R.id.switch_grayscale -> viewModel.setGrayscale(isChecked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.button_done -> if (viewBinding.checkBoxGlobal.isChecked) {
|
R.id.button_done -> showSaveConfirmation()
|
||||||
viewModel.saveGlobally()
|
|
||||||
} else {
|
|
||||||
viewModel.save()
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.button_reset -> viewModel.reset()
|
R.id.button_reset -> viewModel.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,10 +113,23 @@ class ColorFilterConfigActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showSaveConfirmation() {
|
||||||
|
MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle(R.string.apply)
|
||||||
|
.setMessage(R.string.color_correction_apply_text)
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.setPositiveButton(R.string.this_manga) { _, _ ->
|
||||||
|
viewModel.saveGlobally()
|
||||||
|
}.setNeutralButton(R.string.globally) { _, _ ->
|
||||||
|
viewModel.save()
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
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.switchInvert.setChecked(readerColorFilter?.isInverted ?: false, false)
|
||||||
|
viewBinding.switchGrayscale.setChecked(readerColorFilter?.isGrayscale ?: false, false)
|
||||||
viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter()
|
viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +151,8 @@ class ColorFilterConfigActivity :
|
|||||||
private fun onLoadingChanged(isLoading: Boolean) {
|
private fun onLoadingChanged(isLoading: Boolean) {
|
||||||
viewBinding.sliderContrast.isEnabled = !isLoading
|
viewBinding.sliderContrast.isEnabled = !isLoading
|
||||||
viewBinding.sliderBrightness.isEnabled = !isLoading
|
viewBinding.sliderBrightness.isEnabled = !isLoading
|
||||||
|
viewBinding.switchInvert.isEnabled = !isLoading
|
||||||
|
viewBinding.switchGrayscale.isEnabled = !isLoading
|
||||||
viewBinding.buttonDone.isEnabled = !isLoading
|
viewBinding.buttonDone.isEnabled = !isLoading
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.koitharu.kotatsu.reader.ui.colorfilter
|
package org.koitharu.kotatsu.reader.ui.colorfilter
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
@@ -8,7 +7,7 @@ import org.koitharu.kotatsu.R
|
|||||||
import org.koitharu.kotatsu.core.util.ext.call
|
import org.koitharu.kotatsu.core.util.ext.call
|
||||||
|
|
||||||
class ColorFilterConfigBackPressedDispatcher(
|
class ColorFilterConfigBackPressedDispatcher(
|
||||||
private val context: Context,
|
private val activity: ColorFilterConfigActivity,
|
||||||
private val viewModel: ColorFilterConfigViewModel,
|
private val viewModel: ColorFilterConfigViewModel,
|
||||||
) : OnBackPressedCallback(true), DialogInterface.OnClickListener {
|
) : OnBackPressedCallback(true), DialogInterface.OnClickListener {
|
||||||
|
|
||||||
@@ -24,12 +23,12 @@ class ColorFilterConfigBackPressedDispatcher(
|
|||||||
when (which) {
|
when (which) {
|
||||||
DialogInterface.BUTTON_NEGATIVE -> viewModel.onDismiss.call(Unit)
|
DialogInterface.BUTTON_NEGATIVE -> viewModel.onDismiss.call(Unit)
|
||||||
DialogInterface.BUTTON_NEUTRAL -> dialog.dismiss()
|
DialogInterface.BUTTON_NEUTRAL -> dialog.dismiss()
|
||||||
DialogInterface.BUTTON_POSITIVE -> viewModel.save()
|
DialogInterface.BUTTON_POSITIVE -> activity.showSaveConfirmation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showConfirmation() {
|
private fun showConfirmation() {
|
||||||
MaterialAlertDialogBuilder(context)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.color_correction)
|
.setTitle(R.string.color_correction)
|
||||||
.setMessage(R.string.text_unsaved_changes_prompt)
|
.setMessage(R.string.text_unsaved_changes_prompt)
|
||||||
.setNegativeButton(R.string.discard, this)
|
.setNegativeButton(R.string.discard, this)
|
||||||
|
|||||||
@@ -44,33 +44,19 @@ class ColorFilterConfigViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setBrightness(brightness: Float) {
|
fun setBrightness(brightness: Float) {
|
||||||
val cf = colorFilter.value
|
updateColorFilter { it.copy(brightness = brightness) }
|
||||||
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
|
updateColorFilter { it.copy(contrast = contrast) }
|
||||||
colorFilter.value = ReaderColorFilter(
|
|
||||||
brightness = cf?.brightness ?: 0f,
|
|
||||||
contrast = contrast,
|
|
||||||
isInverted = cf?.isInverted ?: false,
|
|
||||||
).takeUnless { it.isEmpty }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setInversion(invert: Boolean) {
|
fun setInversion(invert: Boolean) {
|
||||||
val cf = colorFilter.value
|
updateColorFilter { it.copy(isInverted = invert) }
|
||||||
if (invert == cf?.isInverted) {
|
}
|
||||||
return
|
|
||||||
}
|
fun setGrayscale(grayscale: Boolean) {
|
||||||
colorFilter.value = ReaderColorFilter(
|
updateColorFilter { it.copy(isGrayscale = grayscale) }
|
||||||
brightness = cf?.brightness ?: 0f,
|
|
||||||
contrast = cf?.contrast ?: 0f,
|
|
||||||
isInverted = invert,
|
|
||||||
).takeUnless { it.isEmpty }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
@@ -85,7 +71,18 @@ class ColorFilterConfigViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun saveGlobally() {
|
fun saveGlobally() {
|
||||||
settings.readerColorFilter = colorFilter.value
|
launchLoadingJob(Dispatchers.Default) {
|
||||||
onDismiss.call(Unit)
|
settings.readerColorFilter = colorFilter.value
|
||||||
|
if (mangaDataRepository.getColorFilter(manga.id) != null) {
|
||||||
|
mangaDataRepository.saveColorFilter(manga, colorFilter.value)
|
||||||
|
}
|
||||||
|
onDismiss.call(Unit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun updateColorFilter(block: (ReaderColorFilter) -> ReaderColorFilter) {
|
||||||
|
colorFilter.value = block(
|
||||||
|
colorFilter.value ?: ReaderColorFilter.EMPTY,
|
||||||
|
).takeUnless { it.isEmpty }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,10 +102,10 @@ class ReaderSettings(
|
|||||||
AppSettings.KEY_READER_BACKGROUND,
|
AppSettings.KEY_READER_BACKGROUND,
|
||||||
AppSettings.KEY_32BIT_COLOR,
|
AppSettings.KEY_32BIT_COLOR,
|
||||||
AppSettings.KEY_READER_OPTIMIZE,
|
AppSettings.KEY_READER_OPTIMIZE,
|
||||||
AppSettings.KEY_CF_ENABLED,
|
|
||||||
AppSettings.KEY_CF_CONTRAST,
|
AppSettings.KEY_CF_CONTRAST,
|
||||||
AppSettings.KEY_CF_BRIGHTNESS,
|
AppSettings.KEY_CF_BRIGHTNESS,
|
||||||
AppSettings.KEY_CF_INVERTED,
|
AppSettings.KEY_CF_INVERTED,
|
||||||
|
AppSettings.KEY_CF_GRAYSCALE,
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun emit(value: ReaderColorFilter?) {
|
override suspend fun emit(value: ReaderColorFilter?) {
|
||||||
|
|||||||
@@ -127,6 +127,18 @@
|
|||||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/switch_grayscale"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/margin_normal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="@string/invert_colors"
|
||||||
|
android:textAppearance="?textAppearanceTitleMedium"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/switch_invert" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView_brightness"
|
android:id="@+id/textView_brightness"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -137,7 +149,7 @@
|
|||||||
android:textAppearance="?textAppearanceTitleMedium"
|
android:textAppearance="?textAppearanceTitleMedium"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||||
app:layout_constraintTop_toBottomOf="@id/switch_invert" />
|
app:layout_constraintTop_toBottomOf="@id/switch_grayscale" />
|
||||||
|
|
||||||
<com.google.android.material.slider.Slider
|
<com.google.android.material.slider.Slider
|
||||||
android:id="@+id/slider_brightness"
|
android:id="@+id/slider_brightness"
|
||||||
@@ -178,29 +190,6 @@
|
|||||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||||
app:layout_constraintTop_toBottomOf="@id/textView_contrast" />
|
app:layout_constraintTop_toBottomOf="@id/textView_contrast" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView_tip"
|
|
||||||
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" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/checkBox_global"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/margin_small"
|
|
||||||
android:text="Save these settings globally and apply for all manga"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/textView_tip"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/textView_tip"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/textView_tip" />
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -111,6 +111,17 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/imageView_before" />
|
app:layout_constraintTop_toBottomOf="@id/imageView_before" />
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/switch_grayscale"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="@string/grayscale"
|
||||||
|
android:textAppearance="?textAppearanceTitleMedium"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/switch_invert" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView_brightness"
|
android:id="@+id/textView_brightness"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -120,7 +131,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/switch_invert" />
|
app:layout_constraintTop_toBottomOf="@id/switch_grayscale" />
|
||||||
|
|
||||||
<com.google.android.material.slider.Slider
|
<com.google.android.material.slider.Slider
|
||||||
android:id="@+id/slider_brightness"
|
android:id="@+id/slider_brightness"
|
||||||
@@ -158,37 +169,15 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/textView_contrast" />
|
app:layout_constraintTop_toBottomOf="@id/textView_contrast" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView_tip"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/margin_normal"
|
|
||||||
android:layout_marginEnd="@dimen/margin_normal"
|
|
||||||
android:text="@string/color_correction_hint"
|
|
||||||
android:textAppearance="?textAppearanceBodySmall"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/button_reset"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/slider_contrast" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/checkBox_global"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/margin_small"
|
|
||||||
android:text="Save these settings globally and apply for all manga"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/textView_tip"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/textView_tip"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/textView_tip" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_reset"
|
android:id="@+id/button_reset"
|
||||||
style="?materialButtonOutlinedStyle"
|
style="?materialButtonOutlinedStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
android:text="@string/reset"
|
android:text="@string/reset"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/checkBox_global"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/textView_tip" />
|
app:layout_constraintTop_toBottomOf="@id/slider_contrast" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -535,4 +535,9 @@
|
|||||||
<string name="error_search_not_supported">Search is not supported by this manga source</string>
|
<string name="error_search_not_supported">Search is not supported by this manga source</string>
|
||||||
<string name="downloads_settings_info">You can enable download slowdown for each manga source individually in the source settings if you are having problems with server-side blocking</string>
|
<string name="downloads_settings_info">You can enable download slowdown for each manga source individually in the source settings if you are having problems with server-side blocking</string>
|
||||||
<string name="skip">Skip</string>
|
<string name="skip">Skip</string>
|
||||||
|
<string name="grayscale">Grayscale</string>
|
||||||
|
<string name="globally">Globally</string>
|
||||||
|
<string name="this_manga">This manga</string>
|
||||||
|
<string name="color_correction_apply_text">These settings can be applied globally or only to the current manga. If applied globally, individual settings will not be overridden.</string>
|
||||||
|
<string name="apply">Apply</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user