From dd8afa2b07b50be24d764c0f6ddc9e1bbdb91bf1 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 8 Jun 2025 15:04:58 -0300 Subject: [PATCH] feat(YouTube - Hide player overlay buttons): Add in app setting for "Hide player control buttons background" (#5147) --- .../HidePlayerOverlayButtonsPatch.java | 29 ++++++++++++++++ .../extension/youtube/settings/Settings.java | 1 + .../layout/buttons/overlay/Fingerprints.kt | 8 +++++ .../overlay/HidePlayerOverlayButtonsPatch.kt | 34 ++++++++++++++++++- .../PlayerControlsBackgroundPatch.kt | 33 +++--------------- .../resources/addresources/values/strings.xml | 3 ++ 6 files changed, 78 insertions(+), 30 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/HidePlayerOverlayButtonsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/HidePlayerOverlayButtonsPatch.java index c1a0065db..070c330d0 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/HidePlayerOverlayButtonsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/HidePlayerOverlayButtonsPatch.java @@ -1,6 +1,7 @@ package app.revanced.extension.youtube.patches; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import app.revanced.extension.shared.Logger; @@ -58,6 +59,22 @@ public final class HidePlayerOverlayButtonsPatch { }); } + /** + * Injection point. + */ + public static void hidePlayerControlButtonsBackground(View rootView) { + try { + if (!Settings.HIDE_PLAYER_CONTROL_BUTTONS_BACKGROUND.get()) { + return; + } + + // Each button is an ImageView with a background set to another drawable. + removeImageViewsBackgroundRecursive(rootView); + } catch (Exception ex) { + Logger.printException(() -> "removePlayerControlButtonsBackground failure", ex); + } + } + private static void hideView(View parentView, int resourceId) { View nextPreviousButton = parentView.findViewById(resourceId); @@ -69,4 +86,16 @@ public final class HidePlayerOverlayButtonsPatch { Logger.printDebug(() -> "Hiding previous/next button"); Utils.hideViewByRemovingFromParentUnderCondition(true, nextPreviousButton); } + + private static void removeImageViewsBackgroundRecursive(View currentView) { + if (currentView instanceof ImageView imageView) { + imageView.setBackground(null); + } + + if (currentView instanceof ViewGroup viewGroup) { + for (int i = 0; i < viewGroup.getChildCount(); i++) { + removeImageViewsBackgroundRecursive(viewGroup.getChildAt(i)); + } + } + } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java index c01820d51..d644a582d 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -135,6 +135,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_AUTOPLAY_BUTTON = new BooleanSetting("revanced_hide_autoplay_button", TRUE, true); public static final BooleanSetting HIDE_CAPTIONS_BUTTON = new BooleanSetting("revanced_hide_captions_button", FALSE); public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_hide_cast_button", TRUE, true); + public static final BooleanSetting HIDE_PLAYER_CONTROL_BUTTONS_BACKGROUND = new BooleanSetting("revanced_hide_player_control_buttons_background", FALSE, true); public static final BooleanSetting HIDE_CHANNEL_BAR = new BooleanSetting("revanced_hide_channel_bar", FALSE); public static final BooleanSetting HIDE_CHANNEL_MEMBER_SHELF = new BooleanSetting("revanced_hide_channel_member_shelf", TRUE); public static final BooleanSetting HIDE_COMMUNITY_GUIDELINES = new BooleanSetting("revanced_hide_community_guidelines", TRUE); diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt index 323603b50..7cc63f0fe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt @@ -2,6 +2,7 @@ package app.revanced.patches.youtube.layout.buttons.overlay import app.revanced.patcher.fingerprint import app.revanced.util.containsLiteralInstruction +import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags internal val playerControlsPreviousNextOverlayTouchFingerprint = fingerprint { @@ -20,3 +21,10 @@ internal val mediaRouteButtonFingerprint = fingerprint { methodDef.definingClass.endsWith("/MediaRouteButton;") && methodDef.name == "setVisibility" } } + +internal val inflateControlsGroupLayoutStubFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters() + returns("V") + literal { controlsButtonGroupLayoutStub } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt index 504fad256..8f1cd6d54 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt @@ -28,6 +28,8 @@ internal var playerControlPreviousButtonTouchArea = -1L private set internal var playerControlNextButtonTouchArea = -1L private set +internal var controlsButtonGroupLayoutStub = -1L + private set private val hidePlayerOverlayButtonsResourcePatch = resourcePatch { dependsOn(resourceMappingPatch) @@ -35,6 +37,7 @@ private val hidePlayerOverlayButtonsResourcePatch = resourcePatch { execute { playerControlPreviousButtonTouchArea = resourceMappings["id", "player_control_previous_button_touch_area"] playerControlNextButtonTouchArea = resourceMappings["id", "player_control_next_button_touch_area"] + controlsButtonGroupLayoutStub = resourceMappings["id", "youtube_controls_button_group_layout_stub"] } } @@ -43,7 +46,8 @@ private const val EXTENSION_CLASS_DESCRIPTOR = val hidePlayerOverlayButtonsPatch = bytecodePatch( name = "Hide player overlay buttons", - description = "Adds options to hide the player Cast, Autoplay, Captions, and Previous & Next buttons.", + description = "Adds options to hide the player Cast, Autoplay, Captions, Previous & Next buttons, and the player " + + "control buttons background.", ) { dependsOn( sharedExtensionPatch, @@ -72,6 +76,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( SwitchPreference("revanced_hide_cast_button"), SwitchPreference("revanced_hide_captions_button"), SwitchPreference("revanced_hide_autoplay_button"), + SwitchPreference("revanced_hide_player_control_buttons_background"), ) // region Hide player next/previous button. @@ -147,5 +152,32 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( } // endregion + + // region Hide player control buttons background. + + inflateControlsGroupLayoutStubFingerprint.method.apply { + val controlsButtonGroupLayoutStubResIdConstIndex = + indexOfFirstLiteralInstructionOrThrow(controlsButtonGroupLayoutStub) + val inflateControlsGroupLayoutStubIndex = + indexOfFirstInstruction(controlsButtonGroupLayoutStubResIdConstIndex) { + getReference()?.name == "inflate" + } + + val freeRegister = findFreeRegister(inflateControlsGroupLayoutStubIndex) + val hidePlayerControlButtonsBackgroundDescriptor = + "$EXTENSION_CLASS_DESCRIPTOR->hidePlayerControlButtonsBackground(Landroid/view/View;)V" + + addInstructions( + inflateControlsGroupLayoutStubIndex + 1, + """ + # Move the inflated layout to a temporary register. + # The result of the inflate method is by default not moved to a register after the method is called. + move-result-object v$freeRegister + invoke-static { v$freeRegister }, $hidePlayerControlButtonsBackgroundDescriptor + """ + ) + } + + // endregion } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt index ca109ed20..5c20556a8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt @@ -1,37 +1,12 @@ package app.revanced.patches.youtube.layout.player.background import app.revanced.patcher.patch.resourcePatch -import app.revanced.util.doRecursively -import org.w3c.dom.Element +import app.revanced.patches.youtube.layout.buttons.overlay.hidePlayerOverlayButtonsPatch @Suppress("unused") +@Deprecated("Functionality added to hidePlayerOverlayButtonsPatch", ReplaceWith("hidePlayerOverlayButtonsPatch")) val playerControlsBackgroundPatch = resourcePatch( - name = "Remove player controls background", - description = "Removes the dark background surrounding the video player controls.", - use = false, + description = "Removes the dark background surrounding the video player control buttons.", ) { - compatibleWith( - "com.google.android.youtube"( - "19.16.39", - "19.25.37", - "19.34.42", - "19.43.41", - "19.47.53", - "20.07.39", - "20.12.46", - ) - ) - - execute { - document("res/drawable/player_button_circle_background.xml").use { document -> - - document.doRecursively node@{ node -> - if (node !is Element) return@node - - node.getAttributeNode("android:color")?.let { attribute -> - attribute.textContent = "@android:color/transparent" - } - } - } - } + dependsOn(hidePlayerOverlayButtonsPatch) } diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 3fe80b645..16d1a7cae 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -743,6 +743,9 @@ To show the Audio track menu, change \'Spoof video streams\' to iOS TV" Hide Autoplay button Autoplay button is hidden Autoplay button is shown + Hide player control buttons background + Player control buttons background is hidden + Player control buttons background is shown Hide end screen cards