Auto scroll update (#7)

* updated auto-scroll logic for EPUB and PDF

* Refactored auto-scroll to use temporary debounced pauses instead of hard stops on manual interaction.
* Updated tap handling to allow toggling bars without interrupting scroll.
* Added a 2-second orientation pause on EPUB chapter transitions.
* Enhanced AutoScrollControls UI with circular progress overlay to indicate the "temporarily paused" state.

* Refactored auto-scroll controls

This commit refactors the auto-scroll controls for both EPUB and PDF readers, introducing a more advanced and user-friendly interface.

Key changes:
- Redesigned the auto-scroll controls UI into a collapsible and lockable card.
- Added a "lock" feature to hide controls during scrolling.
- Introduced an alternative slider-based input for speed adjustment, which can be toggled.
- Persisted the lock and input mode states in SharedPreferences.
- Improved the EPUB auto-scroll mechanism using `translate3d` for smoother sub-pixel scrolling.
This commit is contained in:
Aryan 2026-02-26 17:16:01 +05:30 committed by GitHub
parent 1f111034f1
commit de376e2ace
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 410 additions and 238 deletions

View file

@ -213,6 +213,7 @@ internal fun PdfVerticalReader(
topContentPaddingPx: Float = 0f,
onTextBoxMoved: (String, Int, Rect) -> Unit = { _, _, _ -> },
isAutoScrollPlaying: Boolean = false,
isAutoScrollTempPaused: Boolean = false,
autoScrollSpeed: Float = 1.0f,
onInteractionListener: () -> Unit = {}
) {
@ -484,9 +485,9 @@ internal fun PdfVerticalReader(
}
}
LaunchedEffect(isAutoScrollPlaying, autoScrollSpeed, totalDocHeight, screenHeight) {
if (isAutoScrollPlaying) {
val baseSpeedPxPerSec = 30f
LaunchedEffect(isAutoScrollPlaying, isAutoScrollTempPaused, autoScrollSpeed, totalDocHeight, screenHeight) {
if (isAutoScrollPlaying && !isAutoScrollTempPaused) {
val baseSpeedPxPerSec = 80f
var lastFrameTime = withFrameNanos { it }
while (isActive) {

View file

@ -284,6 +284,28 @@ private const val DOCK_LOCATION_KEY = "dock_location"
private const val DOCK_OFFSET_X_KEY = "dock_offset_x"
private const val DOCK_OFFSET_Y_KEY = "dock_offset_y"
private const val PDF_AUTO_SCROLL_SPEED_KEY = "pdf_auto_scroll_speed"
private const val PDF_AUTO_SCROLL_LOCKED_KEY = "pdf_auto_scroll_locked"
private const val PDF_AUTO_SCROLL_USE_SLIDER_KEY = "pdf_auto_scroll_use_slider"
private fun savePdfAutoScrollLocked(context: Context, isLocked: Boolean) {
val prefs = context.getSharedPreferences(SETTINGS_PREFS_NAME, Context.MODE_PRIVATE)
prefs.edit { putBoolean(PDF_AUTO_SCROLL_LOCKED_KEY, isLocked) }
}
private fun loadPdfAutoScrollLocked(context: Context): Boolean {
val prefs = context.getSharedPreferences(SETTINGS_PREFS_NAME, Context.MODE_PRIVATE)
return prefs.getBoolean(PDF_AUTO_SCROLL_LOCKED_KEY, false)
}
private fun savePdfAutoScrollUseSlider(context: Context, useSlider: Boolean) {
val prefs = context.getSharedPreferences(SETTINGS_PREFS_NAME, Context.MODE_PRIVATE)
prefs.edit { putBoolean(PDF_AUTO_SCROLL_USE_SLIDER_KEY, useSlider) }
}
private fun loadPdfAutoScrollUseSlider(context: Context): Boolean {
val prefs = context.getSharedPreferences(SETTINGS_PREFS_NAME, Context.MODE_PRIVATE)
return prefs.getBoolean(PDF_AUTO_SCROLL_USE_SLIDER_KEY, false)
}
private fun savePdfAutoScrollSpeed(context: Context, speed: Float) {
val prefs = context.getSharedPreferences(SETTINGS_PREFS_NAME, Context.MODE_PRIVATE)
@ -604,13 +626,30 @@ fun PdfViewerScreen(
var isAutoScrollModeActive by remember { mutableStateOf(false) }
var isAutoScrollPlaying by remember { mutableStateOf(false) }
var isAutoScrollTempPaused by remember { mutableStateOf(false) }
val autoScrollResumeJob = remember { mutableStateOf<Job?>(null) }
var autoScrollSpeed by remember { mutableFloatStateOf(loadPdfAutoScrollSpeed(context)) }
var isAutoScrollCollapsed by remember { mutableStateOf(false) }
var isAutoScrollLocked by remember { mutableStateOf(loadPdfAutoScrollLocked(context)) }
var autoScrollUseSlider by remember { mutableStateOf(loadPdfAutoScrollUseSlider(context)) }
fun triggerAutoScrollTempPause(durationMs: Long) {
if (!isAutoScrollModeActive || !isAutoScrollPlaying) return
autoScrollResumeJob.value?.cancel()
isAutoScrollTempPaused = true
autoScrollResumeJob.value = coroutineScope.launch {
delay(durationMs)
if (isActive && isAutoScrollModeActive && isAutoScrollPlaying) {
isAutoScrollTempPaused = false
}
}
}
val onAutoScrollInteraction = remember {
{
if (isAutoScrollPlaying) {
isAutoScrollPlaying = false
triggerAutoScrollTempPause(1000L)
}
}
}
@ -1102,7 +1141,6 @@ fun PdfViewerScreen(
val onSingleTapStable = remember {
{
onAutoScrollInteraction()
if (selectedTextBoxId != null) {
val box = textBoxes.find { it.id == selectedTextBoxId }
if (box != null && box.text.trim().isEmpty()) {
@ -3641,6 +3679,7 @@ fun PdfViewerScreen(
}
},
isAutoScrollPlaying = isAutoScrollPlaying,
isAutoScrollTempPaused = isAutoScrollTempPaused,
autoScrollSpeed = autoScrollSpeed,
onInteractionListener = onAutoScrollInteraction
)
@ -4116,7 +4155,7 @@ fun PdfViewerScreen(
showMoreMenu = false
isAutoScrollModeActive = true
isAutoScrollPlaying = true
showBars = false
showBars = true
}
)
HorizontalDivider()
@ -5554,13 +5593,15 @@ fun PdfViewerScreen(
label = "AutoScrollPadding"
)
val isAutoScrollControlsVisible = isAutoScrollModeActive && (!isAutoScrollLocked || showBars)
val alignmentBias by animateFloatAsState(
targetValue = if (isAutoScrollCollapsed) 1f else 0f,
label = "AutoScrollAlignAnimation"
)
AnimatedVisibility(
visible = isAutoScrollModeActive,
visible = isAutoScrollControlsVisible,
enter = slideInVertically { it } + fadeIn(),
exit = slideOutVertically { it } + fadeOut(),
modifier = Modifier
@ -5570,8 +5611,10 @@ fun PdfViewerScreen(
) {
AutoScrollControls(
isPlaying = isAutoScrollPlaying,
isTempPaused = isAutoScrollTempPaused,
onPlayPauseToggle = { isAutoScrollPlaying = !isAutoScrollPlaying },
speed = autoScrollSpeed,
maxSpeed = 20f,
onSpeedChange = {
autoScrollSpeed = it
savePdfAutoScrollSpeed(context, it)
@ -5582,7 +5625,17 @@ fun PdfViewerScreen(
showBars = true
},
isCollapsed = isAutoScrollCollapsed,
onCollapseChange = { isAutoScrollCollapsed = it }
onCollapseChange = { isAutoScrollCollapsed = it },
isLocked = isAutoScrollLocked,
onLockToggle = {
isAutoScrollLocked = !isAutoScrollLocked
savePdfAutoScrollLocked(context, isAutoScrollLocked)
},
useSlider = autoScrollUseSlider,
onInputModeToggle = {
autoScrollUseSlider = !autoScrollUseSlider
savePdfAutoScrollUseSlider(context, autoScrollUseSlider)
}
)
}
}