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:
parent
1f111034f1
commit
de376e2ace
6 changed files with 410 additions and 238 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue