From 443d56f69bc1df515ed2edcd5b2936ed8710fb71 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 28 Oct 2023 16:21:45 -0400 Subject: [PATCH] Add option to flash white screen on page change in reader for e-ink displays Closes #2123 --- .../settings/screen/SettingsReaderScreen.kt | 5 +++ .../presentation/reader/DisplayRefreshHost.kt | 45 +++++++++++++++++++ .../reader/settings/GeneralSettingsPage.kt | 5 +++ .../tachiyomi/ui/reader/ReaderActivity.kt | 12 +++++ .../tachiyomi/ui/reader/ReaderViewModel.kt | 3 ++ .../ui/reader/setting/ReaderPreferences.kt | 2 + i18n/src/main/res/values/strings.xml | 2 + 7 files changed, 74 insertions(+) create mode 100644 app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt index e4ac76681d..750f8138d0 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt @@ -64,6 +64,11 @@ object SettingsReaderScreen : SearchableSettings { pref = readerPref.pageTransitions(), title = stringResource(R.string.pref_page_transitions), ), + Preference.PreferenceItem.SwitchPreference( + pref = readerPref.flashOnPageChange(), + title = stringResource(R.string.pref_flash_page), + subtitle = stringResource(R.string.pref_flash_page_summ), + ), getDisplayGroup(readerPreferences = readerPref), getReadingGroup(readerPreferences = readerPref), getPagedGroup(readerPreferences = readerPref), diff --git a/app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt b/app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt new file mode 100644 index 0000000000..018dbb948c --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt @@ -0,0 +1,45 @@ +package eu.kanade.presentation.reader + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import kotlinx.coroutines.delay + +@Stable +class DisplayRefreshHost { + + internal var currentDisplayRefresh by mutableStateOf(false) + + fun flash() { + currentDisplayRefresh = true + } +} + +@Composable +fun DisplayRefreshHost( + hostState: DisplayRefreshHost, + modifier: Modifier = Modifier, +) { + val currentDisplayRefresh = hostState.currentDisplayRefresh + LaunchedEffect(currentDisplayRefresh) { + if (currentDisplayRefresh) { + delay(200) + hostState.currentDisplayRefresh = false + } + } + + if (currentDisplayRefresh) { + Canvas( + modifier = modifier.fillMaxSize(), + ) { + drawRect(Color.White) + } + } +} diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt index 8d165ec766..5fe65eb2f0 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt @@ -68,4 +68,9 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) { label = stringResource(R.string.pref_page_transitions), pref = screenModel.preferences.pageTransitions(), ) + + CheckboxItem( + label = stringResource(R.string.pref_flash_page), + pref = screenModel.preferences.flashOnPageChange(), + ) } 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 1b8784d1a5..9580af393d 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 @@ -43,6 +43,7 @@ import com.google.android.material.transition.platform.MaterialContainerTransfor 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.OrientationModeSelectDialog import eu.kanade.presentation.reader.PageIndicatorText import eu.kanade.presentation.reader.ReaderPageActionsDialog @@ -122,6 +123,7 @@ class ReaderActivity : BaseActivity() { private var menuToggleToast: Toast? = null private var readingModeToast: Toast? = null + private val displayRefreshHost = DisplayRefreshHost() private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, binding.root) } @@ -197,6 +199,9 @@ class ReaderActivity : BaseActivity() { ReaderViewModel.Event.ReloadViewerChapters -> { viewModel.state.value.viewerChapters?.let(::setChapters) } + ReaderViewModel.Event.PageChanged -> { + displayRefreshHost.flash() + } is ReaderViewModel.Event.SetOrientation -> { setOrientation(event.orientation) } @@ -323,6 +328,7 @@ class ReaderActivity : BaseActivity() { val isHttpSource = viewModel.getSource() is HttpSource val isFullscreen by readerPreferences.fullscreen().collectAsState() + val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState() val cropBorderPaged by readerPreferences.cropBorders().collectAsState() val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState() @@ -375,6 +381,12 @@ class ReaderActivity : BaseActivity() { value = state.brightnessOverlayValue, ) + if (flashOnPageChange) { + DisplayRefreshHost( + hostState = displayRefreshHost, + ) + } + val onDismissRequest = viewModel::closeDialog when (state.dialog) { is ReaderViewModel.Dialog.Loading -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index d1c91b62a6..201c2eaa32 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -429,6 +429,8 @@ class ReaderViewModel @JvmOverloads constructor( if (inDownloadRange) { downloadNextChapters() } + + eventChannel.trySend(Event.PageChanged) } private fun downloadNextChapters() { @@ -917,6 +919,7 @@ class ReaderViewModel @JvmOverloads constructor( sealed interface Event { data object ReloadViewerChapters : Event + data object PageChanged : Event data class SetOrientation(val orientation: Int) : Event data class SetCoverResult(val result: SetAsCoverResult) : Event 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 faf75d0ba9..ab38911f8e 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 @@ -13,6 +13,8 @@ class ReaderPreferences( fun pageTransitions() = preferenceStore.getBoolean("pref_enable_transitions_key", true) + fun flashOnPageChange() = preferenceStore.getBoolean("pref_reader_flash", false) + fun doubleTapAnimSpeed() = preferenceStore.getInt("pref_double_tap_anim_speed", 500) fun showPageNumber() = preferenceStore.getBoolean("pref_show_page_number_key", true) diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 76fa240b70..642f4ce7d3 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -333,6 +333,8 @@ Double tap to zoom Show content in cutout area Animate page transitions + Flash white on page change + Reduces ghosting on e-ink displays Double tap animation speed Show page number Show reading mode