Scroll timer improvements
This commit is contained in:
@@ -110,7 +110,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
|
|||||||
setSupportActionBar(viewBinding.searchBar)
|
setSupportActionBar(viewBinding.searchBar)
|
||||||
|
|
||||||
viewBinding.fab?.setOnClickListener(this)
|
viewBinding.fab?.setOnClickListener(this)
|
||||||
viewBinding.navRail?.headerView?.setOnClickListener(this)
|
viewBinding.navRail?.headerView?.findViewById<View>(R.id.railFab)?.setOnClickListener(this)
|
||||||
fadingAppbarMediator =
|
fadingAppbarMediator =
|
||||||
FadingAppbarMediator(viewBinding.appbar, viewBinding.layoutSearch ?: viewBinding.searchBar)
|
FadingAppbarMediator(viewBinding.appbar, viewBinding.layoutSearch ?: viewBinding.searchBar)
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class ReaderActivity :
|
|||||||
ReaderControlDelegate.OnInteractionListener,
|
ReaderControlDelegate.OnInteractionListener,
|
||||||
ReaderNavigationCallback,
|
ReaderNavigationCallback,
|
||||||
IdlingDetector.Callback,
|
IdlingDetector.Callback,
|
||||||
ZoomControl.ZoomControlListener {
|
ZoomControl.ZoomControlListener, View.OnClickListener, ScrollTimerControlView.OnVisibilityChangeListener {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settings: AppSettings
|
lateinit var settings: AppSettings
|
||||||
@@ -115,10 +115,15 @@ class ReaderActivity :
|
|||||||
controlDelegate = ReaderControlDelegate(resources, settings, tapGridSettings, this)
|
controlDelegate = ReaderControlDelegate(resources, settings, tapGridSettings, this)
|
||||||
viewBinding.zoomControl.listener = this
|
viewBinding.zoomControl.listener = this
|
||||||
viewBinding.actionsView.listener = this
|
viewBinding.actionsView.listener = this
|
||||||
|
viewBinding.buttonTimer?.setOnClickListener(this)
|
||||||
idlingDetector.bindToLifecycle(this)
|
idlingDetector.bindToLifecycle(this)
|
||||||
screenOrientationHelper.applySettings()
|
screenOrientationHelper.applySettings()
|
||||||
viewModel.isBookmarkAdded.observe(this) { viewBinding.actionsView.isBookmarkAdded = it }
|
viewModel.isBookmarkAdded.observe(this) { viewBinding.actionsView.isBookmarkAdded = it }
|
||||||
scrollTimer.isActive.observe(this) { viewBinding.actionsView.setTimerActive(it) }
|
scrollTimer.isActive.observe(this) {
|
||||||
|
updateScrollTimerButton()
|
||||||
|
viewBinding.actionsView.setTimerActive(it)
|
||||||
|
}
|
||||||
|
viewBinding.timerControl.onVisibilityChangeListener = this
|
||||||
viewBinding.timerControl.attach(scrollTimer, this)
|
viewBinding.timerControl.attach(scrollTimer, this)
|
||||||
if (resources.getBoolean(R.bool.is_tablet)) {
|
if (resources.getBoolean(R.bool.is_tablet)) {
|
||||||
viewBinding.timerControl.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
viewBinding.timerControl.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||||
@@ -198,6 +203,10 @@ class ReaderActivity :
|
|||||||
viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState())
|
viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onVisibilityChanged(v: View, visibility: Int) {
|
||||||
|
updateScrollTimerButton()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onZoomIn() {
|
override fun onZoomIn() {
|
||||||
readerManager.currentReader?.onZoomIn()
|
readerManager.currentReader?.onZoomIn()
|
||||||
}
|
}
|
||||||
@@ -206,6 +215,12 @@ class ReaderActivity :
|
|||||||
readerManager.currentReader?.onZoomOut()
|
readerManager.currentReader?.onZoomOut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
when (v.id) {
|
||||||
|
R.id.button_timer -> onScrollTimerClick(isLongClick = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onInitReader(mode: ReaderMode?) {
|
private fun onInitReader(mode: ReaderMode?) {
|
||||||
if (mode == null) {
|
if (mode == null) {
|
||||||
return
|
return
|
||||||
@@ -328,6 +343,7 @@ class ReaderActivity :
|
|||||||
viewBinding.toolbarDocked?.isVisible = isUiVisible
|
viewBinding.toolbarDocked?.isVisible = isUiVisible
|
||||||
viewBinding.infoBar.isGone = isUiVisible || (!viewModel.isInfoBarEnabled.value)
|
viewBinding.infoBar.isGone = isUiVisible || (!viewModel.isInfoBarEnabled.value)
|
||||||
viewBinding.infoBar.isTimeVisible = isFullscreen
|
viewBinding.infoBar.isTimeVisible = isFullscreen
|
||||||
|
updateScrollTimerButton()
|
||||||
systemUiController.setSystemUiVisible(isUiVisible || !isFullscreen)
|
systemUiController.setSystemUiVisible(isUiVisible || !isFullscreen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,6 +471,18 @@ class ReaderActivity :
|
|||||||
viewBinding.actionsView.isPrevEnabled = uiState.hasPreviousChapter()
|
viewBinding.actionsView.isPrevEnabled = uiState.hasPreviousChapter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateScrollTimerButton() {
|
||||||
|
val button = viewBinding.buttonTimer ?: return
|
||||||
|
val isButtonVisible = scrollTimer.isActive.value
|
||||||
|
&& !viewBinding.appbarTop.isVisible
|
||||||
|
&& !viewBinding.timerControl.isVisible
|
||||||
|
if (button.isVisible != isButtonVisible) {
|
||||||
|
val transition = Fade().addTarget(button)
|
||||||
|
TransitionManager.beginDelayedTransition(viewBinding.root, transition)
|
||||||
|
button.isVisible = isButtonVisible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun askForIncognitoMode() {
|
private fun askForIncognitoMode() {
|
||||||
buildAlertDialog(this, isCentered = true) {
|
buildAlertDialog(this, isCentered = true) {
|
||||||
var dontAskAgain = false
|
var dontAskAgain = false
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
|||||||
import org.koitharu.kotatsu.core.util.ext.resolveDp
|
import org.koitharu.kotatsu.core.util.ext.resolveDp
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
private const val MAX_DELAY = 8L
|
private const val MAX_DELAY = 32L
|
||||||
private const val MAX_SWITCH_DELAY = 10_000L
|
private const val MAX_SWITCH_DELAY = 10_000L
|
||||||
private const val INTERACTION_SKIP_MS = 2_000L
|
private const val INTERACTION_SKIP_MS = 2_000L
|
||||||
private const val SPEED_FACTOR_DELTA = 0.02f
|
private const val SPEED_FACTOR_DELTA = 0.02f
|
||||||
@@ -45,7 +45,7 @@ class ScrollTimer @AssistedInject constructor(
|
|||||||
private var resumeAt = 0L
|
private var resumeAt = 0L
|
||||||
private var isTouchDown = MutableStateFlow(false)
|
private var isTouchDown = MutableStateFlow(false)
|
||||||
private val isRunning = MutableStateFlow(false)
|
private val isRunning = MutableStateFlow(false)
|
||||||
private val scrollDelta = resources.resolveDp(2)
|
private val scrollDelta = resources.resolveDp(1)
|
||||||
|
|
||||||
val isActive: StateFlow<Boolean>
|
val isActive: StateFlow<Boolean>
|
||||||
get() = isRunning
|
get() = isRunning
|
||||||
@@ -88,7 +88,7 @@ class ScrollTimer @AssistedInject constructor(
|
|||||||
delayMs = 0L
|
delayMs = 0L
|
||||||
pageSwitchDelay = 0L
|
pageSwitchDelay = 0L
|
||||||
} else {
|
} else {
|
||||||
val speedFactor = 1 - speed
|
val speedFactor = 1f - speed
|
||||||
delayMs = (MAX_DELAY * speedFactor).roundToLong()
|
delayMs = (MAX_DELAY * speedFactor).roundToLong()
|
||||||
pageSwitchDelay = (MAX_SWITCH_DELAY * speedFactor).roundToLong()
|
pageSwitchDelay = (MAX_SWITCH_DELAY * speedFactor).roundToLong()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.koitharu.kotatsu.core.util.ext.parentView
|
|||||||
import org.koitharu.kotatsu.databinding.ViewScrollTimerBinding
|
import org.koitharu.kotatsu.databinding.ViewScrollTimerBinding
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ScrollTimerControlView @JvmOverloads constructor(
|
class ScrollTimerControlView @JvmOverloads constructor(
|
||||||
@@ -37,6 +38,8 @@ class ScrollTimerControlView @JvmOverloads constructor(
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var settings: AppSettings
|
lateinit var settings: AppSettings
|
||||||
|
|
||||||
|
var onVisibilityChangeListener: OnVisibilityChangeListener? = null
|
||||||
|
|
||||||
private val binding = ViewScrollTimerBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ViewScrollTimerBinding.inflate(LayoutInflater.from(context), this)
|
||||||
|
|
||||||
private var scrollTimer: ScrollTimer? = null
|
private var scrollTimer: ScrollTimer? = null
|
||||||
@@ -63,10 +66,12 @@ class ScrollTimerControlView @JvmOverloads constructor(
|
|||||||
key = AppSettings.KEY_READER_AUTOSCROLL_SPEED,
|
key = AppSettings.KEY_READER_AUTOSCROLL_SPEED,
|
||||||
valueProducer = { readerAutoscrollSpeed },
|
valueProducer = { readerAutoscrollSpeed },
|
||||||
).observe(lifecycleOwner) {
|
).observe(lifecycleOwner) {
|
||||||
binding.sliderTimer.value = it.coerceIn(
|
if (abs(it - binding.sliderTimer.value) > 0.0001) {
|
||||||
binding.sliderTimer.valueFrom,
|
binding.sliderTimer.value = it.coerceIn(
|
||||||
binding.sliderTimer.valueTo,
|
binding.sliderTimer.valueFrom,
|
||||||
)
|
binding.sliderTimer.valueTo,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateDescription()
|
updateDescription()
|
||||||
}
|
}
|
||||||
@@ -83,9 +88,10 @@ class ScrollTimerControlView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getFormattedValue(value: Float): String {
|
override fun getFormattedValue(value: Float): String {
|
||||||
// val minValue = binding.sliderTimer.valueFrom
|
val valueFrom = binding.sliderTimer.valueFrom
|
||||||
// val maxValue = binding.sliderTimer.valueTo
|
val valueTo = binding.sliderTimer.valueTo
|
||||||
return labelPattern.format(value * 10f)
|
val percent = (value - valueFrom) / (valueTo - valueFrom)
|
||||||
|
return labelPattern.format(0.1 + percent * 10) // just something to display
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onValueChange(
|
override fun onValueChange(
|
||||||
@@ -103,6 +109,11 @@ class ScrollTimerControlView @JvmOverloads constructor(
|
|||||||
scrollTimer?.setActive(isChecked)
|
scrollTimer?.setActive(isChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setVisibility(visibility: Int) {
|
||||||
|
super.setVisibility(visibility)
|
||||||
|
onVisibilityChangeListener?.onVisibilityChanged(this, visibility)
|
||||||
|
}
|
||||||
|
|
||||||
fun show() {
|
fun show() {
|
||||||
setupVisibilityTransition()
|
setupVisibilityTransition()
|
||||||
isVisible = true
|
isVisible = true
|
||||||
@@ -139,4 +150,9 @@ class ScrollTimerControlView @JvmOverloads constructor(
|
|||||||
binding.textViewDescription.isVisible = true
|
binding.textViewDescription.isVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun interface OnVisibilityChangeListener {
|
||||||
|
|
||||||
|
fun onVisibilityChanged(v: View, visibility: Int)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,19 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:background="@color/grey" />
|
tools:background="@color/grey" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/button_timer"
|
||||||
|
style="?materialIconButtonOutlinedStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:contentDescription="@string/page_switch_timer"
|
||||||
|
android:tooltipText="@string/page_switch_timer"
|
||||||
|
app:backgroundTint="@color/bg_floating_button"
|
||||||
|
app:icon="@drawable/ic_timelapse"
|
||||||
|
app:layout_insetEdge="bottom" />
|
||||||
|
|
||||||
<org.koitharu.kotatsu.core.ui.widgets.ZoomControl
|
<org.koitharu.kotatsu.core.ui.widgets.ZoomControl
|
||||||
android:id="@+id/zoomControl"
|
android:id="@+id/zoomControl"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -66,8 +66,8 @@
|
|||||||
android:layout_marginEnd="@dimen/margin_normal"
|
android:layout_marginEnd="@dimen/margin_normal"
|
||||||
android:contentDescription="@string/speed"
|
android:contentDescription="@string/speed"
|
||||||
android:labelFor="@id/switch_scroll_timer"
|
android:labelFor="@id/switch_scroll_timer"
|
||||||
android:valueFrom="0.001"
|
android:valueFrom="0.000001"
|
||||||
android:valueTo="0.9"
|
android:valueTo="0.95"
|
||||||
app:labelBehavior="floating"
|
app:labelBehavior="floating"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/label_timer"
|
app:layout_constraintStart_toEndOf="@id/label_timer"
|
||||||
|
|||||||
Reference in New Issue
Block a user