From 53e00e46890c511da63b646b3ce8744491dc38d1 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 2 Dec 2023 15:45:49 +0200 Subject: [PATCH] Global color filter initial implementation #562 --- .../kotatsu/core/prefs/AppSettings.kt | 42 +++++++++++++++++++ .../colorfilter/ColorFilterConfigActivity.kt | 7 +++- .../colorfilter/ColorFilterConfigViewModel.kt | 7 +++- .../reader/ui/config/ReaderSettings.kt | 22 ++++++---- .../activity_color_filter.xml | 12 ++++++ .../main/res/layout/activity_color_filter.xml | 34 ++++++++++----- 6 files changed, 103 insertions(+), 21 deletions(-) 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 1fd0c9e2b..0512630c3 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 @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.core.prefs +import android.annotation.SuppressLint import android.content.Context import android.content.SharedPreferences import android.net.ConnectivityManager @@ -13,12 +14,16 @@ import androidx.core.content.edit import androidx.core.os.LocaleListCompat import androidx.preference.PreferenceManager import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import org.json.JSONArray import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.network.DoHProvider import org.koitharu.kotatsu.core.util.ext.connectivityManager import org.koitharu.kotatsu.core.util.ext.getEnumValue import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import org.koitharu.kotatsu.core.util.ext.putEnumValue import org.koitharu.kotatsu.core.util.ext.takeIfReadable import org.koitharu.kotatsu.core.util.ext.toUriOrNull @@ -28,6 +33,7 @@ import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.find import org.koitharu.kotatsu.parsers.util.mapNotNullToSet import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.reader.domain.ReaderColorFilter import java.io.File import java.net.Proxy import java.util.Locale @@ -293,6 +299,27 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { val isReaderKeepScreenOn: Boolean get() = prefs.getBoolean(KEY_READER_SCREEN_ON, true) + var readerColorFilter: ReaderColorFilter? + get() { + if (!prefs.getBoolean(KEY_CF_ENABLED, false)) { + return null + } + val brightness = prefs.getFloat(KEY_CF_BRIGHTNESS, 0f) + val contrast = prefs.getFloat(KEY_CF_CONTRAST, 0f) + val inverted = prefs.getBoolean(KEY_CF_INVERTED, false) + return ReaderColorFilter(brightness, contrast, inverted) + } + set(value) { + prefs.edit { + putBoolean(KEY_CF_ENABLED, value != null) + if (value != null) { + putFloat(KEY_CF_BRIGHTNESS, value.brightness) + putFloat(KEY_CF_CONTRAST, value.contrast) + putBoolean(KEY_CF_INVERTED, value.isInverted) + } + } + } + val isImagesProxyEnabled: Boolean get() = prefs.getBoolean(KEY_IMAGES_PROXY, false) @@ -425,6 +452,17 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { return result } + @SuppressLint("ApplySharedPref") + private inline fun SharedPreferences.editAsync( + action: SharedPreferences.Editor.() -> Unit + ) { + val editor = edit() + action(editor) + processLifecycleScope.launch(Dispatchers.IO, CoroutineStart.ATOMIC) { + editor.commit() + } + } + companion object { const val PAGE_SWITCH_TAPS = "taps" @@ -535,6 +573,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_32BIT_COLOR = "enhanced_colors" const val KEY_SOURCES_ORDER = "sources_sort_order" 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_CONTRAST = "cf_contrast" + const val KEY_CF_INVERTED = "cf_inverted" // About const val KEY_APP_UPDATE = "app_update" 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 20c12d7d9..65aaf9c46 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 @@ -90,7 +90,12 @@ class ColorFilterConfigActivity : override fun onClick(v: View) { when (v.id) { - R.id.button_done -> viewModel.save() + R.id.button_done -> if (viewBinding.checkBoxGlobal.isChecked) { + viewModel.saveGlobally() + } else { + viewModel.save() + } + R.id.button_reset -> viewModel.reset() } } 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 c9ff9bc5f..e41e19045 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 @@ -38,7 +38,7 @@ class ColorFilterConfigViewModel @Inject constructor( init { launchLoadingJob { - initialColorFilter = mangaDataRepository.getColorFilter(manga.id) + initialColorFilter = mangaDataRepository.getColorFilter(manga.id) ?: settings.readerColorFilter colorFilter.value = initialColorFilter } } @@ -83,4 +83,9 @@ class ColorFilterConfigViewModel @Inject constructor( onDismiss.call(Unit) } } + + fun saveGlobally() { + settings.readerColorFilter = colorFilter.value + onDismiss.call(Unit) + } } 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 96c45e63b..0cc10934e 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 @@ -34,7 +34,7 @@ class ReaderSettings( get() = settings.zoomMode val colorFilter: ReaderColorFilter? - get() = colorFilterFlow.value?.takeUnless { it.isEmpty } + get() = colorFilterFlow.value?.takeUnless { it.isEmpty } ?: settings.readerColorFilter val isReaderOptimizationEnabled: Boolean get() = settings.isReaderOptimizationEnabled @@ -96,6 +96,18 @@ class ReaderSettings( FlowCollector, SharedPreferences.OnSharedPreferenceChangeListener { + private val settingsKeys = setOf( + AppSettings.KEY_ZOOM_MODE, + AppSettings.KEY_PAGES_NUMBERS, + AppSettings.KEY_READER_BACKGROUND, + AppSettings.KEY_32BIT_COLOR, + AppSettings.KEY_READER_OPTIMIZE, + AppSettings.KEY_CF_ENABLED, + AppSettings.KEY_CF_CONTRAST, + AppSettings.KEY_CF_BRIGHTNESS, + AppSettings.KEY_CF_INVERTED, + ) + override suspend fun emit(value: ReaderColorFilter?) { withContext(Dispatchers.Main.immediate) { notifyChanged() @@ -103,13 +115,7 @@ class ReaderSettings( } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { - if ( - key == AppSettings.KEY_ZOOM_MODE || - key == AppSettings.KEY_PAGES_NUMBERS || - key == AppSettings.KEY_READER_BACKGROUND || - key == AppSettings.KEY_32BIT_COLOR || - key == AppSettings.KEY_READER_OPTIMIZE - ) { + if (key in settingsKeys) { notifyChanged() } } 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 7e8bc7dd5..88060cdeb 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 @@ -179,6 +179,7 @@ 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 0288a026f..21850f5ee 100644 --- a/app/src/main/res/layout/activity_color_filter.xml +++ b/app/src/main/res/layout/activity_color_filter.xml @@ -158,25 +158,37 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textView_contrast" /> -