diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/MangaDatabase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/MangaDatabase.kt index e2fbd6108..72a4ba35b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/MangaDatabase.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/MangaDatabase.kt @@ -42,6 +42,7 @@ import org.koitharu.kotatsu.core.db.migrations.Migration23To24 import org.koitharu.kotatsu.core.db.migrations.Migration24To23 import org.koitharu.kotatsu.core.db.migrations.Migration24To25 import org.koitharu.kotatsu.core.db.migrations.Migration25To26 +import org.koitharu.kotatsu.core.db.migrations.Migration26To27 import org.koitharu.kotatsu.core.db.migrations.Migration2To3 import org.koitharu.kotatsu.core.db.migrations.Migration3To4 import org.koitharu.kotatsu.core.db.migrations.Migration4To5 @@ -69,7 +70,7 @@ import org.koitharu.kotatsu.tracker.data.TrackEntity import org.koitharu.kotatsu.tracker.data.TrackLogEntity import org.koitharu.kotatsu.tracker.data.TracksDao -const val DATABASE_VERSION = 26 +const val DATABASE_VERSION = 27 @Database( entities = [ @@ -140,6 +141,7 @@ fun getDatabaseMigrations(context: Context): Array = arrayOf( Migration24To23(), Migration24To25(), Migration25To26(), + Migration26To27(), ) fun MangaDatabase(context: Context): MangaDatabase = Room diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt index ae78aaf95..28db6ec6e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt @@ -26,6 +26,7 @@ data class MangaPrefsEntity( @ColumnInfo(name = "cf_contrast") val cfContrast: Float, @ColumnInfo(name = "cf_invert") val cfInvert: Boolean, @ColumnInfo(name = "cf_grayscale") val cfGrayscale: Boolean, + @ColumnInfo(name = "cf_book") val cfBookEffect: Boolean, @ColumnInfo(name = "title_override") val titleOverride: String?, @ColumnInfo(name = "cover_override") val coverUrlOverride: String?, @ColumnInfo(name = "content_rating_override") val contentRatingOverride: String?, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration26To27.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration26To27.kt new file mode 100644 index 000000000..b5763070a --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration26To27.kt @@ -0,0 +1,11 @@ +package org.koitharu.kotatsu.core.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration26To27 : Migration(26, 27) { + + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("ALTER TABLE preferences ADD COLUMN cf_book INTEGER NOT NULL DEFAULT 0") + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt index ae11a85a6..6da7cf7d0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt @@ -197,8 +197,14 @@ class MangaDataRepository @Inject constructor( } private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? { - return if (cfBrightness != 0f || cfContrast != 0f || cfInvert || cfGrayscale) { - ReaderColorFilter(cfBrightness, cfContrast, cfInvert, cfGrayscale) + return if (cfBrightness != 0f || cfContrast != 0f || cfInvert || cfGrayscale || cfBookEffect) { + ReaderColorFilter( + brightness = cfBrightness, + contrast = cfContrast, + isInverted = cfInvert, + isGrayscale = cfGrayscale, + isBookBackground = cfBookEffect + ) } else { null } @@ -219,10 +225,11 @@ class MangaDataRepository @Inject constructor( private fun newEntity(mangaId: Long) = MangaPrefsEntity( mangaId = mangaId, mode = -1, - cfBrightness = 0f, - cfContrast = 0f, - cfInvert = false, - cfGrayscale = false, + cfBrightness = ReaderColorFilter.EMPTY.brightness, + cfContrast = ReaderColorFilter.EMPTY.contrast, + cfInvert = ReaderColorFilter.EMPTY.isInverted, + cfGrayscale = ReaderColorFilter.EMPTY.isGrayscale, + cfBookEffect = ReaderColorFilter.EMPTY.isBookBackground, titleOverride = null, coverUrlOverride = null, contentRatingOverride = null, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 165b25ac3..d3d40f5f4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -401,19 +401,29 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { var readerColorFilter: ReaderColorFilter? get() = runCatching { - val brightness = prefs.getFloat(KEY_CF_BRIGHTNESS, ReaderColorFilter.EMPTY.brightness) - val contrast = prefs.getFloat(KEY_CF_CONTRAST, ReaderColorFilter.EMPTY.contrast) - val inverted = prefs.getBoolean(KEY_CF_INVERTED, ReaderColorFilter.EMPTY.isInverted) - val grayscale = prefs.getBoolean(KEY_CF_GRAYSCALE, ReaderColorFilter.EMPTY.isGrayscale) - ReaderColorFilter(brightness, contrast, inverted, grayscale).takeUnless { it.isEmpty } + ReaderColorFilter( + brightness = prefs.getFloat(KEY_CF_BRIGHTNESS, ReaderColorFilter.EMPTY.brightness), + contrast = prefs.getFloat(KEY_CF_CONTRAST, ReaderColorFilter.EMPTY.contrast), + isInverted = prefs.getBoolean(KEY_CF_INVERTED, ReaderColorFilter.EMPTY.isInverted), + isGrayscale = prefs.getBoolean(KEY_CF_GRAYSCALE, ReaderColorFilter.EMPTY.isGrayscale), + isBookBackground = prefs.getBoolean(KEY_CF_BOOK, ReaderColorFilter.EMPTY.isBookBackground), + ).takeUnless { it.isEmpty } }.getOrNull() set(value) { prefs.edit { - val cf = value ?: ReaderColorFilter.EMPTY - putFloat(KEY_CF_BRIGHTNESS, cf.brightness) - putFloat(KEY_CF_CONTRAST, cf.contrast) - putBoolean(KEY_CF_INVERTED, cf.isInverted) - putBoolean(KEY_CF_GRAYSCALE, cf.isGrayscale) + if (value != null) { + putFloat(KEY_CF_BRIGHTNESS, value.brightness) + putFloat(KEY_CF_CONTRAST, value.contrast) + putBoolean(KEY_CF_INVERTED, value.isInverted) + putBoolean(KEY_CF_GRAYSCALE, value.isGrayscale) + putBoolean(KEY_CF_BOOK, value.isBookBackground) + } else { + remove(KEY_CF_BRIGHTNESS) + remove(KEY_CF_CONTRAST) + remove(KEY_CF_INVERTED) + remove(KEY_CF_GRAYSCALE) + remove(KEY_CF_BOOK) + } } } @@ -740,6 +750,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_CF_CONTRAST = "cf_contrast" const val KEY_CF_INVERTED = "cf_inverted" const val KEY_CF_GRAYSCALE = "cf_grayscale" + const val KEY_CF_BOOK = "cf_book" const val KEY_PAGES_TAB = "pages_tab" const val KEY_DETAILS_TAB = "details_tab" const val KEY_DETAILS_LAST_TAB = "details_last_tab" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt index eb5c73669..5ae078de2 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt @@ -1,5 +1,7 @@ package org.koitharu.kotatsu.reader.domain +import android.content.res.ColorStateList +import android.graphics.Color import android.graphics.ColorMatrix import android.graphics.ColorMatrixColorFilter @@ -8,10 +10,11 @@ data class ReaderColorFilter( val contrast: Float, val isInverted: Boolean, val isGrayscale: Boolean, + val isBookBackground: Boolean, ) { val isEmpty: Boolean - get() = !isGrayscale && !isInverted && brightness == 0f && contrast == 0f + get() = !isGrayscale && !isInverted && !isBookBackground && brightness == 0f && contrast == 0f fun toColorFilter(): ColorMatrixColorFilter { val cm = ColorMatrix() @@ -23,9 +26,19 @@ data class ReaderColorFilter( } cm.setBrightness(brightness) cm.setContrast(contrast) + if (isBookBackground) { + cm.addBookEffect() + } return ColorMatrixColorFilter(cm) } + fun getBackgroundTint(): ColorStateList? = if (isBookBackground) { + val color = Color.rgb(255, 255, (255 * BOOK_BLUE_FACTOR).toInt()) + ColorStateList.valueOf(color) + } else { + null + } + private fun ColorMatrix.setBrightness(brightness: Float) { val scale = brightness + 1f val matrix = ColorMatrix() @@ -60,13 +73,26 @@ data class ReaderColorFilter( setSaturation(0f) } + private fun ColorMatrix.addBookEffect() { + val removeBlueMatrix = floatArrayOf( + 1f, 0f, 0f, 0f, 0f, + 0f, 1f, 0f, 0f, 0f, + 0f, 0f, BOOK_BLUE_FACTOR, 0f, 0f, + 0f, 0f, 0f, 1f, 0f, + ) + postConcat(ColorMatrix(removeBlueMatrix)) + } + companion object { + private const val BOOK_BLUE_FACTOR = 0.92f + val EMPTY = ReaderColorFilter( brightness = 0.0f, contrast = 0.0f, isInverted = false, isGrayscale = false, + isBookBackground = false, ) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt index 99b93b8c3..a54e5cb5c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt @@ -53,6 +53,7 @@ class ColorFilterConfigActivity : viewBinding.sliderBrightness.setLabelFormatter(formatter) viewBinding.switchInvert.setOnCheckedChangeListener(this) viewBinding.switchGrayscale.setOnCheckedChangeListener(this) + viewBinding.switchBook.setOnCheckedChangeListener(this) viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonReset.setOnClickListener(this) @@ -93,6 +94,7 @@ class ColorFilterConfigActivity : when (buttonView.id) { R.id.switch_invert -> viewModel.setInversion(isChecked) R.id.switch_grayscale -> viewModel.setGrayscale(isChecked) + R.id.switch_book -> viewModel.setBookEffect(isChecked) } } @@ -120,6 +122,7 @@ class ColorFilterConfigActivity : viewBinding.sliderContrast.setValueRounded(readerColorFilter?.contrast ?: 0f) viewBinding.switchInvert.setChecked(readerColorFilter?.isInverted == true, false) viewBinding.switchGrayscale.setChecked(readerColorFilter?.isGrayscale == true, false) + viewBinding.switchBook.setChecked(readerColorFilter?.isBookBackground == true, false) viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt index 42172cae9..0c4496457 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt @@ -56,6 +56,10 @@ class ColorFilterConfigViewModel @Inject constructor( updateColorFilter { it.copy(isGrayscale = grayscale) } } + fun setBookEffect(book: Boolean) { + updateColorFilter { it.copy(isBookBackground = book) } + } + fun reset() { colorFilter.value = null } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt index fdb6be6c9..3b7634181 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt @@ -57,6 +57,11 @@ data class ReaderSettings( fun applyBackground(view: View) { view.background = background.resolve(view.context) + view.backgroundTintList = if (background.isLight(view.context)) { + colorFilter?.getBackgroundTint() + } else { + null + } } fun isPagesCropEnabled(isWebtoon: Boolean) = if (isWebtoon) { diff --git a/app/src/main/res/layout-w600dp-land/activity_color_filter.xml b/app/src/main/res/layout-w600dp-land/activity_color_filter.xml index 131dec830..057f4ac17 100644 --- a/app/src/main/res/layout-w600dp-land/activity_color_filter.xml +++ b/app/src/main/res/layout-w600dp-land/activity_color_filter.xml @@ -191,6 +191,18 @@ app:layout_constraintStart_toEndOf="@id/guideline_vertical" app:layout_constraintTop_toBottomOf="@id/textView_contrast" /> + + diff --git a/app/src/main/res/layout/activity_color_filter.xml b/app/src/main/res/layout/activity_color_filter.xml index 06abfc378..70ccb2011 100644 --- a/app/src/main/res/layout/activity_color_filter.xml +++ b/app/src/main/res/layout/activity_color_filter.xml @@ -170,15 +170,26 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textView_contrast" /> + +