Add option to flash white screen on page change in reader for e-ink displays

Closes #2123
This commit is contained in:
arkon 2023-10-28 16:21:45 -04:00
parent 7457a18aee
commit 443d56f69b
7 changed files with 74 additions and 0 deletions

View file

@ -64,6 +64,11 @@ object SettingsReaderScreen : SearchableSettings {
pref = readerPref.pageTransitions(), pref = readerPref.pageTransitions(),
title = stringResource(R.string.pref_page_transitions), 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), getDisplayGroup(readerPreferences = readerPref),
getReadingGroup(readerPreferences = readerPref), getReadingGroup(readerPreferences = readerPref),
getPagedGroup(readerPreferences = readerPref), getPagedGroup(readerPreferences = readerPref),

View file

@ -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)
}
}
}

View file

@ -68,4 +68,9 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
label = stringResource(R.string.pref_page_transitions), label = stringResource(R.string.pref_page_transitions),
pref = screenModel.preferences.pageTransitions(), pref = screenModel.preferences.pageTransitions(),
) )
CheckboxItem(
label = stringResource(R.string.pref_flash_page),
pref = screenModel.preferences.flashOnPageChange(),
)
} }

View file

@ -43,6 +43,7 @@ import com.google.android.material.transition.platform.MaterialContainerTransfor
import dev.chrisbanes.insetter.applyInsetter import dev.chrisbanes.insetter.applyInsetter
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.presentation.reader.BrightnessOverlay import eu.kanade.presentation.reader.BrightnessOverlay
import eu.kanade.presentation.reader.DisplayRefreshHost
import eu.kanade.presentation.reader.OrientationModeSelectDialog import eu.kanade.presentation.reader.OrientationModeSelectDialog
import eu.kanade.presentation.reader.PageIndicatorText import eu.kanade.presentation.reader.PageIndicatorText
import eu.kanade.presentation.reader.ReaderPageActionsDialog import eu.kanade.presentation.reader.ReaderPageActionsDialog
@ -122,6 +123,7 @@ class ReaderActivity : BaseActivity() {
private var menuToggleToast: Toast? = null private var menuToggleToast: Toast? = null
private var readingModeToast: Toast? = null private var readingModeToast: Toast? = null
private val displayRefreshHost = DisplayRefreshHost()
private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, binding.root) } private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, binding.root) }
@ -197,6 +199,9 @@ class ReaderActivity : BaseActivity() {
ReaderViewModel.Event.ReloadViewerChapters -> { ReaderViewModel.Event.ReloadViewerChapters -> {
viewModel.state.value.viewerChapters?.let(::setChapters) viewModel.state.value.viewerChapters?.let(::setChapters)
} }
ReaderViewModel.Event.PageChanged -> {
displayRefreshHost.flash()
}
is ReaderViewModel.Event.SetOrientation -> { is ReaderViewModel.Event.SetOrientation -> {
setOrientation(event.orientation) setOrientation(event.orientation)
} }
@ -323,6 +328,7 @@ class ReaderActivity : BaseActivity() {
val isHttpSource = viewModel.getSource() is HttpSource val isHttpSource = viewModel.getSource() is HttpSource
val isFullscreen by readerPreferences.fullscreen().collectAsState() val isFullscreen by readerPreferences.fullscreen().collectAsState()
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()
val cropBorderPaged by readerPreferences.cropBorders().collectAsState() val cropBorderPaged by readerPreferences.cropBorders().collectAsState()
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState() val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
@ -375,6 +381,12 @@ class ReaderActivity : BaseActivity() {
value = state.brightnessOverlayValue, value = state.brightnessOverlayValue,
) )
if (flashOnPageChange) {
DisplayRefreshHost(
hostState = displayRefreshHost,
)
}
val onDismissRequest = viewModel::closeDialog val onDismissRequest = viewModel::closeDialog
when (state.dialog) { when (state.dialog) {
is ReaderViewModel.Dialog.Loading -> { is ReaderViewModel.Dialog.Loading -> {

View file

@ -429,6 +429,8 @@ class ReaderViewModel @JvmOverloads constructor(
if (inDownloadRange) { if (inDownloadRange) {
downloadNextChapters() downloadNextChapters()
} }
eventChannel.trySend(Event.PageChanged)
} }
private fun downloadNextChapters() { private fun downloadNextChapters() {
@ -917,6 +919,7 @@ class ReaderViewModel @JvmOverloads constructor(
sealed interface Event { sealed interface Event {
data object ReloadViewerChapters : Event data object ReloadViewerChapters : Event
data object PageChanged : Event
data class SetOrientation(val orientation: Int) : Event data class SetOrientation(val orientation: Int) : Event
data class SetCoverResult(val result: SetAsCoverResult) : Event data class SetCoverResult(val result: SetAsCoverResult) : Event

View file

@ -13,6 +13,8 @@ class ReaderPreferences(
fun pageTransitions() = preferenceStore.getBoolean("pref_enable_transitions_key", true) 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 doubleTapAnimSpeed() = preferenceStore.getInt("pref_double_tap_anim_speed", 500)
fun showPageNumber() = preferenceStore.getBoolean("pref_show_page_number_key", true) fun showPageNumber() = preferenceStore.getBoolean("pref_show_page_number_key", true)

View file

@ -333,6 +333,8 @@
<string name="pref_double_tap_zoom">Double tap to zoom</string> <string name="pref_double_tap_zoom">Double tap to zoom</string>
<string name="pref_cutout_short">Show content in cutout area</string> <string name="pref_cutout_short">Show content in cutout area</string>
<string name="pref_page_transitions">Animate page transitions</string> <string name="pref_page_transitions">Animate page transitions</string>
<string name="pref_flash_page">Flash white on page change</string>
<string name="pref_flash_page_summ">Reduces ghosting on e-ink displays</string>
<string name="pref_double_tap_anim_speed">Double tap animation speed</string> <string name="pref_double_tap_anim_speed">Double tap animation speed</string>
<string name="pref_show_page_number">Show page number</string> <string name="pref_show_page_number">Show page number</string>
<string name="pref_show_reading_mode">Show reading mode</string> <string name="pref_show_reading_mode">Show reading mode</string>