revanced-integrations/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/gesture/ClassicSwipeController.kt

118 lines
3.9 KiB
Kotlin

package app.revanced.integrations.youtube.swipecontrols.controller.gesture
import android.view.MotionEvent
import app.revanced.integrations.youtube.shared.PlayerControlsVisibilityObserver
import app.revanced.integrations.youtube.shared.PlayerControlsVisibilityObserverImpl
import app.revanced.integrations.youtube.swipecontrols.SwipeControlsHostActivity
import app.revanced.integrations.youtube.swipecontrols.controller.gesture.core.BaseGestureController
import app.revanced.integrations.youtube.swipecontrols.controller.gesture.core.SwipeDetector
import app.revanced.integrations.youtube.swipecontrols.misc.contains
import app.revanced.integrations.youtube.swipecontrols.misc.toPoint
/**
* provides the classic swipe controls experience, as it was with 'XFenster'
*
* @param controller reference to the main swipe controller
*/
class ClassicSwipeController(
private val controller: SwipeControlsHostActivity
) : BaseGestureController(controller),
PlayerControlsVisibilityObserver by PlayerControlsVisibilityObserverImpl(controller) {
/**
* the last event captured in [onDown]
*/
private var lastOnDownEvent: MotionEvent? = null
override val shouldForceInterceptEvents: Boolean
get() = currentSwipe == SwipeDetector.SwipeDirection.VERTICAL
override fun isInSwipeZone(motionEvent: MotionEvent): Boolean {
val inVolumeZone = if (controller.config.enableVolumeControls) {
(motionEvent.toPoint() in controller.zones.volume)
} else {
false
}
val inBrightnessZone = if (controller.config.enableBrightnessControl) {
(motionEvent.toPoint() in controller.zones.brightness)
} else {
false
}
return inVolumeZone || inBrightnessZone
}
override fun shouldDropMotion(motionEvent: MotionEvent): Boolean {
// ignore gestures with more than one pointer
// when such a gesture is detected, dispatch the first event of the gesture to downstream
if (motionEvent.pointerCount > 1) {
lastOnDownEvent?.let {
controller.dispatchDownstreamTouchEvent(it)
it.recycle()
}
lastOnDownEvent = null
return true
}
// ignore gestures when player controls are visible
return arePlayerControlsVisible
}
override fun onDown(motionEvent: MotionEvent): Boolean {
// save the event for later
lastOnDownEvent?.recycle()
lastOnDownEvent = MotionEvent.obtain(motionEvent)
// must be inside swipe zone
return isInSwipeZone(motionEvent)
}
override fun onSingleTapUp(motionEvent: MotionEvent): Boolean {
MotionEvent.obtain(motionEvent).let {
it.action = MotionEvent.ACTION_DOWN
controller.dispatchDownstreamTouchEvent(it)
it.recycle()
}
return false
}
override fun onDoubleTapEvent(motionEvent: MotionEvent): Boolean {
MotionEvent.obtain(motionEvent).let {
controller.dispatchDownstreamTouchEvent(it)
it.recycle()
}
return super.onDoubleTapEvent(motionEvent)
}
override fun onLongPress(motionEvent: MotionEvent) {
MotionEvent.obtain(motionEvent).let {
controller.dispatchDownstreamTouchEvent(it)
it.recycle()
}
super.onLongPress(motionEvent)
}
override fun onSwipe(
from: MotionEvent,
to: MotionEvent,
distanceX: Double,
distanceY: Double
): Boolean {
// cancel if not vertical
if (currentSwipe != SwipeDetector.SwipeDirection.VERTICAL) return false
return when (from.toPoint()) {
in controller.zones.volume -> {
scrollVolume(distanceY)
true
}
in controller.zones.brightness -> {
scrollBrightness(distanceY)
true
}
else -> false
}
}
}