mirror of
https://github.com/revanced/revanced-integrations.git
synced 2024-08-30 11:05:15 +02:00
feat: swipe controls
override volume button behaviour (#114)
This commit is contained in:
parent
166bfd35ed
commit
8056e2e9eb
@ -3,7 +3,7 @@ package app.revanced.integrations.patches;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout;
|
import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Patch class for 'hdr-auto-brightness' patch
|
* Patch class for 'hdr-auto-brightness' patch
|
||||||
@ -27,7 +27,7 @@ public class HDRAutoBrightnessPatch {
|
|||||||
|
|
||||||
// override with brightness set by swipe-controls
|
// override with brightness set by swipe-controls
|
||||||
// only when swipe-controls is active and has overridden the brightness
|
// only when swipe-controls is active and has overridden the brightness
|
||||||
final SwipeControlsHostLayout swipeControlsHost = SwipeControlsPatch.CURRENT_HOST.get();
|
final SwipeControlsHostActivity swipeControlsHost = SwipeControlsHostActivity.getCurrentHost().get();
|
||||||
if (swipeControlsHost != null
|
if (swipeControlsHost != null
|
||||||
&& swipeControlsHost.getScreen() != null
|
&& swipeControlsHost.getScreen() != null
|
||||||
&& swipeControlsHost.getConfig().getEnableBrightnessControl()
|
&& swipeControlsHost.getConfig().getEnableBrightnessControl()
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
package app.revanced.integrations.patches;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook receiver class for 'swipe-controls' patch
|
|
||||||
*
|
|
||||||
* @usedBy app.revanced.patches.youtube.interaction.swipecontrols.patch.SwipeControlsPatch
|
|
||||||
* @smali Lapp/revanced/integrations/patches/SwipeControlsPatch;
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class SwipeControlsPatch {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the currently active swipe controls host.
|
|
||||||
* the reference may be null!
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public static WeakReference<SwipeControlsHostLayout> CURRENT_HOST = new WeakReference<>(null);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook into the main activity lifecycle
|
|
||||||
* (using onStart here, but really anything up until onResume should be fine)
|
|
||||||
*
|
|
||||||
* @param thisRef reference to the WatchWhileActivity instance
|
|
||||||
* @smali WatchWhileActivity_onStartHookEX(Ljava / lang / Object ;)V
|
|
||||||
*/
|
|
||||||
public static void WatchWhileActivity_onStartHookEX(@Nullable Object thisRef) {
|
|
||||||
if (thisRef == null) return;
|
|
||||||
if (thisRef instanceof Activity) {
|
|
||||||
SwipeControlsHostLayout swipeControlsHost = SwipeControlsHostLayout.attachTo((Activity) thisRef, false);
|
|
||||||
CURRENT_HOST = new WeakReference<>(swipeControlsHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,7 @@ class SwipeControlsConfigurationProvider(
|
|||||||
) {
|
) {
|
||||||
//region swipe enable
|
//region swipe enable
|
||||||
/**
|
/**
|
||||||
* should swipe controls be enabled? (global setting
|
* should swipe controls be enabled? (global setting)
|
||||||
*/
|
*/
|
||||||
val enableSwipeControls: Boolean
|
val enableSwipeControls: Boolean
|
||||||
get() = isFullscreenVideo && (enableVolumeControls || enableBrightnessControl)
|
get() = isFullscreenVideo && (enableVolumeControls || enableBrightnessControl)
|
||||||
@ -39,6 +39,14 @@ class SwipeControlsConfigurationProvider(
|
|||||||
get() = PlayerType.current == PlayerType.WATCH_WHILE_FULLSCREEN
|
get() = PlayerType.current == PlayerType.WATCH_WHILE_FULLSCREEN
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
//region keys enable
|
||||||
|
/**
|
||||||
|
* should volume key controls be overwritten? (global setting)
|
||||||
|
*/
|
||||||
|
val overwriteVolumeKeyControls: Boolean
|
||||||
|
get() = isFullscreenVideo && enableVolumeControls
|
||||||
|
//endregioin
|
||||||
|
|
||||||
//region gesture adjustments
|
//region gesture adjustments
|
||||||
/**
|
/**
|
||||||
* should press-to-swipe be enabled?
|
* should press-to-swipe be enabled?
|
||||||
|
@ -0,0 +1,178 @@
|
|||||||
|
package app.revanced.integrations.swipecontrols
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import app.revanced.integrations.shared.PlayerType
|
||||||
|
import app.revanced.integrations.swipecontrols.controller.AudioVolumeController
|
||||||
|
import app.revanced.integrations.swipecontrols.controller.ScreenBrightnessController
|
||||||
|
import app.revanced.integrations.swipecontrols.controller.SwipeZonesController
|
||||||
|
import app.revanced.integrations.swipecontrols.controller.VolumeKeysController
|
||||||
|
import app.revanced.integrations.swipecontrols.controller.gesture.NoPtSSwipeGestureController
|
||||||
|
import app.revanced.integrations.swipecontrols.controller.gesture.SwipeGestureController
|
||||||
|
import app.revanced.integrations.swipecontrols.misc.Rectangle
|
||||||
|
import app.revanced.integrations.swipecontrols.views.SwipeControlsOverlayLayout
|
||||||
|
import app.revanced.integrations.utils.LogHelper
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main controller for volume and brightness swipe controls.
|
||||||
|
* note that the superclass is overwritten to the superclass of the WatchWhileActivity at patch time
|
||||||
|
*
|
||||||
|
* @smali Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;
|
||||||
|
*/
|
||||||
|
class SwipeControlsHostActivity : Activity() {
|
||||||
|
/**
|
||||||
|
* current instance of [AudioVolumeController]
|
||||||
|
*/
|
||||||
|
var audio: AudioVolumeController? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current instance of [ScreenBrightnessController]
|
||||||
|
*/
|
||||||
|
var screen: ScreenBrightnessController? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current instance of [SwipeControlsConfigurationProvider]
|
||||||
|
*/
|
||||||
|
lateinit var config: SwipeControlsConfigurationProvider
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current instance of [SwipeControlsOverlayLayout]
|
||||||
|
*/
|
||||||
|
lateinit var overlay: SwipeControlsOverlayLayout
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current instance of [SwipeZonesController]
|
||||||
|
*/
|
||||||
|
lateinit var zones: SwipeZonesController
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main gesture controller
|
||||||
|
*/
|
||||||
|
private lateinit var gesture: SwipeGestureController
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main volume keys controller
|
||||||
|
*/
|
||||||
|
private lateinit var keys: VolumeKeysController
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current content view with id [android.R.id.content]
|
||||||
|
*/
|
||||||
|
private val contentRoot
|
||||||
|
get() = window.decorView.findViewById<ViewGroup>(android.R.id.content)
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// create controllers
|
||||||
|
LogHelper.info(this.javaClass, "initializing swipe controls controllers")
|
||||||
|
config = SwipeControlsConfigurationProvider(this)
|
||||||
|
gesture = createGestureController()
|
||||||
|
keys = VolumeKeysController(this)
|
||||||
|
audio = createAudioController()
|
||||||
|
screen = createScreenController()
|
||||||
|
|
||||||
|
// create overlay
|
||||||
|
SwipeControlsOverlayLayout(this).let {
|
||||||
|
overlay = it
|
||||||
|
contentRoot.addView(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create swipe zone controller
|
||||||
|
zones = SwipeZonesController(this) {
|
||||||
|
Rectangle(
|
||||||
|
contentRoot.x.toInt(),
|
||||||
|
contentRoot.y.toInt(),
|
||||||
|
contentRoot.width,
|
||||||
|
contentRoot.height
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen for changes in the player type
|
||||||
|
PlayerType.onChange += this::onPlayerTypeChanged
|
||||||
|
|
||||||
|
// set current instance reference
|
||||||
|
currentHost = WeakReference(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
|
||||||
|
// (re) attach overlay
|
||||||
|
LogHelper.info(this.javaClass, "attaching swipe controls overlay")
|
||||||
|
contentRoot.removeView(overlay)
|
||||||
|
contentRoot.addView(overlay)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
||||||
|
return if ((ev != null) && gesture.onTouchEvent(ev)) true else {
|
||||||
|
super.dispatchTouchEvent(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispatchKeyEvent(ev: KeyEvent?): Boolean {
|
||||||
|
return if((ev != null) && keys.onKeyEvent(ev)) true else {
|
||||||
|
super.dispatchKeyEvent(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dispatch a touch event to downstream views
|
||||||
|
*
|
||||||
|
* @param event the event to dispatch
|
||||||
|
* @return was the event consumed?
|
||||||
|
*/
|
||||||
|
fun dispatchDownstreamTouchEvent(event: MotionEvent) =
|
||||||
|
super.dispatchTouchEvent(event)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called when the player type changes
|
||||||
|
*
|
||||||
|
* @param type the new player type
|
||||||
|
*/
|
||||||
|
private fun onPlayerTypeChanged(type: PlayerType) {
|
||||||
|
when (type) {
|
||||||
|
PlayerType.WATCH_WHILE_FULLSCREEN -> screen?.restore()
|
||||||
|
else -> {
|
||||||
|
screen?.save()
|
||||||
|
screen?.restoreDefaultBrightness()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the audio volume controller
|
||||||
|
*/
|
||||||
|
private fun createAudioController() =
|
||||||
|
if (config.enableVolumeControls)
|
||||||
|
AudioVolumeController(this) else null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the screen brightness controller instance
|
||||||
|
*/
|
||||||
|
private fun createScreenController() =
|
||||||
|
if (config.enableBrightnessControl)
|
||||||
|
ScreenBrightnessController(this) else null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the gesture controller based on settings
|
||||||
|
*/
|
||||||
|
private fun createGestureController() =
|
||||||
|
if (config.shouldEnablePressToSwipe)
|
||||||
|
SwipeGestureController(this)
|
||||||
|
else NoPtSSwipeGestureController(this)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* the currently active swipe controls host.
|
||||||
|
* the reference may be null!
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
var currentHost: WeakReference<SwipeControlsHostActivity> = WeakReference(null)
|
||||||
|
private set
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package app.revanced.integrations.swipecontrols.controller
|
package app.revanced.integrations.swipecontrols.controller
|
||||||
|
|
||||||
import android.content.Context
|
import android.app.Activity
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import app.revanced.integrations.swipecontrols.misc.Rectangle
|
import app.revanced.integrations.swipecontrols.misc.Rectangle
|
||||||
@ -35,29 +35,28 @@ import kotlin.math.min
|
|||||||
*/
|
*/
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class SwipeZonesController(
|
class SwipeZonesController(
|
||||||
context: Context,
|
private val host: Activity,
|
||||||
private val parentView: ViewGroup,
|
|
||||||
private val fallbackScreenRect: () -> Rectangle
|
private val fallbackScreenRect: () -> Rectangle
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* 20dp, in pixels
|
* 20dp, in pixels
|
||||||
*/
|
*/
|
||||||
private val _20dp = 20.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
|
private val _20dp = 20.applyDimension(host, TypedValue.COMPLEX_UNIT_DIP)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 40dp, in pixels
|
* 40dp, in pixels
|
||||||
*/
|
*/
|
||||||
private val _40dp = 40.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
|
private val _40dp = 40.applyDimension(host, TypedValue.COMPLEX_UNIT_DIP)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 80dp, in pixels
|
* 80dp, in pixels
|
||||||
*/
|
*/
|
||||||
private val _80dp = 80.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
|
private val _80dp = 80.applyDimension(host, TypedValue.COMPLEX_UNIT_DIP)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* id for R.id.player_view
|
* id for R.id.player_view
|
||||||
*/
|
*/
|
||||||
private val playerViewId = ReVancedUtils.getResourceIdByName(context, "id", "player_view")
|
private val playerViewId = ReVancedUtils.getResourceIdByName(host, "id", "player_view")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* current bounding rectangle of the player
|
* current bounding rectangle of the player
|
||||||
@ -114,7 +113,7 @@ class SwipeZonesController(
|
|||||||
*/
|
*/
|
||||||
private fun maybeAttachPlayerBoundsListener() {
|
private fun maybeAttachPlayerBoundsListener() {
|
||||||
if (playerRect != null) return
|
if (playerRect != null) return
|
||||||
parentView.findViewById<ViewGroup>(playerViewId)?.let {
|
host.findViewById<ViewGroup>(playerViewId)?.let {
|
||||||
onPlayerViewLayout(it)
|
onPlayerViewLayout(it)
|
||||||
it.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
it.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
||||||
onPlayerViewLayout(it)
|
onPlayerViewLayout(it)
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package app.revanced.integrations.swipecontrols.controller
|
||||||
|
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controller for custom volume button behaviour
|
||||||
|
*
|
||||||
|
* @param controller main controller instance
|
||||||
|
*/
|
||||||
|
class VolumeKeysController(
|
||||||
|
private val controller: SwipeControlsHostActivity
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* key event handler
|
||||||
|
*
|
||||||
|
* @param event the key event
|
||||||
|
* @return consume the event?
|
||||||
|
*/
|
||||||
|
fun onKeyEvent(event: KeyEvent): Boolean {
|
||||||
|
if(!controller.config.overwriteVolumeKeyControls) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (event.keyCode) {
|
||||||
|
KeyEvent.KEYCODE_VOLUME_DOWN ->
|
||||||
|
handleVolumeKeyEvent(event, false)
|
||||||
|
KeyEvent.KEYCODE_VOLUME_UP ->
|
||||||
|
handleVolumeKeyEvent(event, true)
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle a volume up / down key event
|
||||||
|
*
|
||||||
|
* @param event the key event
|
||||||
|
* @param volumeUp was the key pressed the volume up key?
|
||||||
|
* @return consume the event?
|
||||||
|
*/
|
||||||
|
private fun handleVolumeKeyEvent(event: KeyEvent, volumeUp: Boolean): Boolean {
|
||||||
|
if (event.action == KeyEvent.ACTION_DOWN) {
|
||||||
|
controller.audio?.apply {
|
||||||
|
volume += if (volumeUp) 1 else -1
|
||||||
|
controller.overlay.onVolumeChanged(volume, maxVolume)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,14 @@
|
|||||||
package app.revanced.integrations.swipecontrols.controller.gesture
|
package app.revanced.integrations.swipecontrols.controller.gesture
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout
|
import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [SwipeGestureController], but with press-to-swipe disabled because a lot of people dislike the feature.
|
* [SwipeGestureController], but with press-to-swipe disabled because a lot of people dislike the feature.
|
||||||
* If you want to change something, try to do it in [SwipeGestureController] so that both configurations can benefit from it
|
* If you want to change something, try to do it in [SwipeGestureController] so that both configurations can benefit from it
|
||||||
*/
|
*/
|
||||||
class NoPtSSwipeGestureController(context: Context, controller: SwipeControlsHostLayout) :
|
class NoPtSSwipeGestureController(controller: SwipeControlsHostActivity) :
|
||||||
SwipeGestureController(context, controller) {
|
SwipeGestureController(controller) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* to disable press-to-swipe, we have to become press-to-swipe
|
* to disable press-to-swipe, we have to become press-to-swipe
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package app.revanced.integrations.swipecontrols.controller.gesture
|
package app.revanced.integrations.swipecontrols.controller.gesture
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.GestureDetector
|
import android.view.GestureDetector
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity
|
||||||
import app.revanced.integrations.swipecontrols.misc.ScrollDistanceHelper
|
import app.revanced.integrations.swipecontrols.misc.ScrollDistanceHelper
|
||||||
import app.revanced.integrations.swipecontrols.misc.applyDimension
|
import app.revanced.integrations.swipecontrols.misc.applyDimension
|
||||||
import app.revanced.integrations.swipecontrols.misc.contains
|
import app.revanced.integrations.swipecontrols.misc.contains
|
||||||
import app.revanced.integrations.swipecontrols.misc.toPoint
|
import app.revanced.integrations.swipecontrols.misc.toPoint
|
||||||
import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout
|
|
||||||
import app.revanced.integrations.utils.LogHelper
|
import app.revanced.integrations.utils.LogHelper
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
@ -17,21 +16,18 @@ import kotlin.math.pow
|
|||||||
* base gesture controller for volume and brightness swipe controls controls, with press-to-swipe enabled
|
* base gesture controller for volume and brightness swipe controls controls, with press-to-swipe enabled
|
||||||
* for the controller without press-to-swipe, see [NoPtSSwipeGestureController]
|
* for the controller without press-to-swipe, see [NoPtSSwipeGestureController]
|
||||||
*
|
*
|
||||||
* @param context the context to create in
|
|
||||||
* @param controller reference to main controller instance
|
* @param controller reference to main controller instance
|
||||||
*/
|
*/
|
||||||
@Suppress("LeakingThis")
|
@Suppress("LeakingThis")
|
||||||
open class SwipeGestureController(
|
open class SwipeGestureController(
|
||||||
context: Context,
|
private val controller: SwipeControlsHostActivity
|
||||||
private val controller: SwipeControlsHostLayout
|
|
||||||
) :
|
) :
|
||||||
GestureDetector.SimpleOnGestureListener(),
|
GestureDetector.SimpleOnGestureListener() {
|
||||||
SwipeControlsHostLayout.TouchEventListener {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the main gesture detector that powers everything
|
* the main gesture detector that powers everything
|
||||||
*/
|
*/
|
||||||
protected open val detector = GestureDetector(context, this)
|
protected open val detector = GestureDetector(controller, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* to enable swipe controls, users must first long- press. this flags monitors that long- press
|
* to enable swipe controls, users must first long- press. this flags monitors that long- press
|
||||||
@ -60,7 +56,7 @@ open class SwipeGestureController(
|
|||||||
*/
|
*/
|
||||||
protected open val volumeScroller = ScrollDistanceHelper(
|
protected open val volumeScroller = ScrollDistanceHelper(
|
||||||
10.applyDimension(
|
10.applyDimension(
|
||||||
context,
|
controller,
|
||||||
TypedValue.COMPLEX_UNIT_DIP
|
TypedValue.COMPLEX_UNIT_DIP
|
||||||
)
|
)
|
||||||
) { _, _, direction ->
|
) { _, _, direction ->
|
||||||
@ -75,7 +71,7 @@ open class SwipeGestureController(
|
|||||||
*/
|
*/
|
||||||
protected open val brightnessScroller = ScrollDistanceHelper(
|
protected open val brightnessScroller = ScrollDistanceHelper(
|
||||||
1.applyDimension(
|
1.applyDimension(
|
||||||
context,
|
controller,
|
||||||
TypedValue.COMPLEX_UNIT_DIP
|
TypedValue.COMPLEX_UNIT_DIP
|
||||||
)
|
)
|
||||||
) { _, _, direction ->
|
) { _, _, direction ->
|
||||||
@ -90,7 +86,13 @@ open class SwipeGestureController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTouchEvent(motionEvent: MotionEvent): Boolean {
|
/**
|
||||||
|
* touch event callback
|
||||||
|
*
|
||||||
|
* @param motionEvent the motion event that was received
|
||||||
|
* @return intercept the event? if true, child views will not receive the event
|
||||||
|
*/
|
||||||
|
fun onTouchEvent(motionEvent: MotionEvent): Boolean {
|
||||||
if (!controller.config.enableSwipeControls) {
|
if (!controller.config.enableSwipeControls) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -1,207 +0,0 @@
|
|||||||
package app.revanced.integrations.swipecontrols.views
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import app.revanced.integrations.shared.PlayerType
|
|
||||||
import app.revanced.integrations.swipecontrols.SwipeControlsConfigurationProvider
|
|
||||||
import app.revanced.integrations.swipecontrols.controller.AudioVolumeController
|
|
||||||
import app.revanced.integrations.swipecontrols.controller.ScreenBrightnessController
|
|
||||||
import app.revanced.integrations.swipecontrols.controller.SwipeZonesController
|
|
||||||
import app.revanced.integrations.swipecontrols.controller.gesture.NoPtSSwipeGestureController
|
|
||||||
import app.revanced.integrations.swipecontrols.controller.gesture.SwipeGestureController
|
|
||||||
import app.revanced.integrations.swipecontrols.misc.Rectangle
|
|
||||||
import app.revanced.integrations.swipecontrols.misc.SwipeControlsOverlay
|
|
||||||
import app.revanced.integrations.utils.LogHelper
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main controller for volume and brightness swipe controls
|
|
||||||
*
|
|
||||||
* @param hostActivity the activity that should host the controller
|
|
||||||
* @param debugTouchableZone show a overlay on all zones covered by this layout
|
|
||||||
*/
|
|
||||||
@SuppressLint("ViewConstructor")
|
|
||||||
class SwipeControlsHostLayout(
|
|
||||||
private val hostActivity: Activity,
|
|
||||||
private val mainContentChild: View,
|
|
||||||
debugTouchableZone: Boolean = false
|
|
||||||
) : FrameLayout(hostActivity) {
|
|
||||||
init {
|
|
||||||
isFocusable = false
|
|
||||||
isClickable = false
|
|
||||||
|
|
||||||
if (debugTouchableZone) {
|
|
||||||
val zoneOverlay = View(context).apply {
|
|
||||||
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
||||||
setBackgroundColor(Color.argb(50, 0, 255, 0))
|
|
||||||
z = 9999f
|
|
||||||
}
|
|
||||||
addView(zoneOverlay)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* current instance of [AudioVolumeController]
|
|
||||||
*/
|
|
||||||
val audio: AudioVolumeController?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* current instance of [ScreenBrightnessController]
|
|
||||||
*/
|
|
||||||
val screen: ScreenBrightnessController?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* current instance of [SwipeControlsConfigurationProvider]
|
|
||||||
*/
|
|
||||||
val config: SwipeControlsConfigurationProvider
|
|
||||||
|
|
||||||
/**
|
|
||||||
* current instance of [SwipeControlsOverlayLayout]
|
|
||||||
*/
|
|
||||||
val overlay: SwipeControlsOverlay
|
|
||||||
|
|
||||||
/**
|
|
||||||
* current instance of [SwipeZonesController]
|
|
||||||
*/
|
|
||||||
val zones: SwipeZonesController
|
|
||||||
|
|
||||||
/**
|
|
||||||
* main gesture controller
|
|
||||||
*/
|
|
||||||
private val gesture: SwipeGestureController
|
|
||||||
|
|
||||||
init {
|
|
||||||
// create controllers
|
|
||||||
LogHelper.info(this.javaClass, "initializing swipe controls controllers")
|
|
||||||
config = SwipeControlsConfigurationProvider(hostActivity)
|
|
||||||
gesture = createGestureController()
|
|
||||||
audio = createAudioController()
|
|
||||||
screen = createScreenController()
|
|
||||||
|
|
||||||
// create overlay
|
|
||||||
SwipeControlsOverlayLayout(hostActivity).let {
|
|
||||||
overlay = it
|
|
||||||
addView(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create swipe zone controller
|
|
||||||
zones = SwipeZonesController(context, this) {
|
|
||||||
Rectangle(x.toInt(), y.toInt(), width, height)
|
|
||||||
}
|
|
||||||
|
|
||||||
// listen for changes in the player type
|
|
||||||
PlayerType.onChange += this::onPlayerTypeChanged
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
|
||||||
return if (ev != null && gesture.onTouchEvent(ev)) true else {
|
|
||||||
super.dispatchTouchEvent(ev)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
|
|
||||||
// main content is always at index 0, all other are inserted after
|
|
||||||
if (child == mainContentChild) {
|
|
||||||
super.addView(child, 0, params)
|
|
||||||
} else {
|
|
||||||
super.addView(child, childCount, params)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called when the player type changes
|
|
||||||
*
|
|
||||||
* @param type the new player type
|
|
||||||
*/
|
|
||||||
private fun onPlayerTypeChanged(type: PlayerType) {
|
|
||||||
when (type) {
|
|
||||||
PlayerType.WATCH_WHILE_FULLSCREEN -> screen?.restore()
|
|
||||||
else -> {
|
|
||||||
screen?.save()
|
|
||||||
screen?.restoreDefaultBrightness()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dispatch a touch event to downstream views
|
|
||||||
*
|
|
||||||
* @param event the event to dispatch
|
|
||||||
* @return was the event consumed?
|
|
||||||
*/
|
|
||||||
fun dispatchDownstreamTouchEvent(event: MotionEvent) =
|
|
||||||
super.dispatchTouchEvent(event)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create the audio volume controller
|
|
||||||
*/
|
|
||||||
private fun createAudioController() =
|
|
||||||
if (config.enableVolumeControls)
|
|
||||||
AudioVolumeController(context) else null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create the screen brightness controller instance
|
|
||||||
*/
|
|
||||||
private fun createScreenController() =
|
|
||||||
if (config.enableBrightnessControl)
|
|
||||||
ScreenBrightnessController(hostActivity) else null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create the gesture controller based on settings
|
|
||||||
*/
|
|
||||||
private fun createGestureController() =
|
|
||||||
if (config.shouldEnablePressToSwipe)
|
|
||||||
SwipeGestureController(hostActivity, this)
|
|
||||||
else NoPtSSwipeGestureController(hostActivity, this)
|
|
||||||
|
|
||||||
|
|
||||||
interface TouchEventListener {
|
|
||||||
/**
|
|
||||||
* touch event callback
|
|
||||||
*
|
|
||||||
* @param motionEvent the motion event that was received
|
|
||||||
* @return intercept the event? if true, child views will not receive the event
|
|
||||||
*/
|
|
||||||
fun onTouchEvent(motionEvent: MotionEvent): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* attach a [SwipeControlsHostLayout] to the activity
|
|
||||||
*
|
|
||||||
* @param debugTouchableZone show a overlay on all zones covered by this layout
|
|
||||||
* @return the attached instance
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
fun Activity.attachTo(debugTouchableZone: Boolean = false): SwipeControlsHostLayout {
|
|
||||||
// get targets
|
|
||||||
val contentView: ViewGroup = window.decorView.findViewById(android.R.id.content)!!
|
|
||||||
var content = contentView.getChildAt(0)
|
|
||||||
|
|
||||||
// detach previously attached swipe host first
|
|
||||||
if (content is SwipeControlsHostLayout) {
|
|
||||||
contentView.removeView(content)
|
|
||||||
content.removeAllViews()
|
|
||||||
content = content.mainContentChild
|
|
||||||
}
|
|
||||||
|
|
||||||
// create swipe host
|
|
||||||
val swipeHost = SwipeControlsHostLayout(this, content, debugTouchableZone).apply {
|
|
||||||
layoutParams = ViewGroup.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert the swipe host as parent to the actual content
|
|
||||||
contentView.removeView(content)
|
|
||||||
contentView.addView(swipeHost)
|
|
||||||
swipeHost.addView(content)
|
|
||||||
return swipeHost
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user