Smooth start-stop on smooth scrolling

pull/311/head
Koitharu 3 years ago
parent b81ecda43e
commit d258f479b3
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -19,7 +19,8 @@ import kotlin.math.roundToLong
private const val MAX_DELAY = 20L private const val MAX_DELAY = 20L
private const val MAX_SWITCH_DELAY = 10_000L private const val MAX_SWITCH_DELAY = 10_000L
private const val INTERACTION_SKIP_MS = 1_000L private const val INTERACTION_SKIP_MS = 2_000L
private const val SPEED_FACTOR_DELTA = 0.02f
class ScrollTimer @AssistedInject constructor( class ScrollTimer @AssistedInject constructor(
@Assisted private val listener: ReaderControlDelegate.OnInteractionListener, @Assisted private val listener: ReaderControlDelegate.OnInteractionListener,
@ -31,7 +32,7 @@ class ScrollTimer @AssistedInject constructor(
private var job: Job? = null private var job: Job? = null
private var delayMs: Long = 10L private var delayMs: Long = 10L
private var pageSwitchDelay: Long = 100L private var pageSwitchDelay: Long = 100L
private var skip = 0L private var resumeAt = 0L
var isEnabled: Boolean = false var isEnabled: Boolean = false
set(value) { set(value) {
@ -51,7 +52,7 @@ class ScrollTimer @AssistedInject constructor(
} }
fun onUserInteraction() { fun onUserInteraction() {
skip = INTERACTION_SKIP_MS resumeAt = System.currentTimeMillis() + INTERACTION_SKIP_MS
} }
private fun onSpeedChanged(speed: Float) { private fun onSpeedChanged(speed: Float) {
@ -70,20 +71,29 @@ class ScrollTimer @AssistedInject constructor(
private fun restartJob() { private fun restartJob() {
job?.cancel() job?.cancel()
skip = 0 resumeAt = 0L
if (!isEnabled || delayMs == 0L) { if (!isEnabled || delayMs == 0L) {
job = null job = null
return return
} }
job = coroutineScope.launch { job = coroutineScope.launch {
var accumulator = 0L var accumulator = 0L
var speedFactor = 1f
while (isActive) { while (isActive) {
delay(delayMs) if (isPaused()) {
if (!listener.isReaderResumed()) { speedFactor = (speedFactor - SPEED_FACTOR_DELTA).coerceAtLeast(0f)
} else if (speedFactor < 1f) {
speedFactor = (speedFactor + SPEED_FACTOR_DELTA).coerceAtMost(1f)
}
if (speedFactor == 1f) {
delay(delayMs)
} else if (speedFactor == 0f) {
delayUntilResumed()
continue continue
} else {
delay((delayMs * (1f + speedFactor * 2)).toLong())
} }
skip -= delayMs if (!listener.isReaderResumed()) {
if (skip > 0) {
continue continue
} }
if (!listener.scrollBy(1)) { if (!listener.scrollBy(1)) {
@ -97,6 +107,16 @@ class ScrollTimer @AssistedInject constructor(
} }
} }
private fun isPaused(): Boolean {
return resumeAt > System.currentTimeMillis()
}
private suspend fun delayUntilResumed() {
while (isPaused()) {
delay(resumeAt - System.currentTimeMillis())
}
}
@AssistedFactory @AssistedFactory
interface Factory { interface Factory {

Loading…
Cancel
Save