fix(YouTube - Player components): Disable player popup panels doesn't work sometimes https://github.com/inotia00/ReVanced_Extended/issues/2814

This commit is contained in:
inotia00 2025-03-06 12:04:32 +09:00
parent 00ff1b5ec5
commit 6a42fea64a
7 changed files with 162 additions and 36 deletions

View File

@ -426,9 +426,40 @@ public class PlayerPatch {
imageView.setImageAlpha(PLAYER_OVERLAY_OPACITY_LEVEL);
}
/**
* Used in YouTube 18.29.38 ~ 20.04.46.
*/
private static boolean isAutoPopupPanel;
/**
* Used in YouTube 18.29.38 ~ 20.04.46.
*/
public static boolean disableAutoPlayerPopupPanels(boolean isLiveChatOrPlaylistPanel) {
if (!Settings.DISABLE_AUTO_PLAYER_POPUP_PANELS.get()) {
return false;
}
if (isLiveChatOrPlaylistPanel) {
return true;
}
return isAutoPopupPanel && ShortsPlayerState.getCurrent().isClosed();
}
/**
* Used in YouTube 18.29.38 ~ 20.04.46.
*/
public static void setInitVideoPanel(boolean initVideoPanel) {
isAutoPopupPanel = initVideoPanel;
}
/**
* Used in YouTube 20.05.46+.
*/
@NonNull
private static final AtomicBoolean newVideoStarted = new AtomicBoolean(false);
/**
* Used in YouTube 20.05.46+.
*/
public static boolean disableAutoPlayerPopupPanels(boolean isLiveChatOrPlaylistPanel, String panelId) {
if (Settings.DISABLE_AUTO_PLAYER_POPUP_PANELS.get()) {
return isLiveChatOrPlaylistPanel || (panelId.equals("PAproduct_list") && newVideoStarted.get());
@ -436,11 +467,14 @@ public class PlayerPatch {
return false;
}
/**
* Used in YouTube 20.05.46+.
*/
public static void disableAutoPlayerPopupPanels(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName,
@NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle,
final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) {
if (Settings.DISABLE_AUTO_PLAYER_POPUP_PANELS.get() && newVideoStarted.compareAndSet(false, true)) {
Utils.runOnMainThreadDelayed(() -> newVideoStarted.compareAndSet(true, false), 1500L);
Utils.runOnMainThreadDelayed(() -> newVideoStarted.compareAndSet(true, false), 3000L);
}
}

View File

@ -95,6 +95,27 @@ fun indexOfSpannableStringInstruction(method: Method) = method.indexOfFirstInstr
getReference<MethodReference>()?.toString() == SPANNABLE_STRING_REFERENCE
}
internal val startVideoInformerFingerprint = legacyFingerprint(
name = "startVideoInformerFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.RETURN_VOID
),
strings = listOf("pc"),
customFingerprint = { method, _ ->
method.implementation
?.instructions
?.withIndex()
?.filter { (_, instruction) ->
instruction.opcode == Opcode.CONST_STRING
}
?.map { (index, _) -> index }
?.size == 1
}
)
internal val videoLengthFingerprint = legacyFingerprint(
name = "videoLengthFingerprint",
returnType = "V",

View File

@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
import app.revanced.patches.shared.startVideoInformerFingerprint
import app.revanced.util.fingerprint.methodOrThrow
private const val EXTENSION_CLASS_DESCRIPTOR =

View File

@ -3,28 +3,6 @@ package app.revanced.patches.shared.captions
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val startVideoInformerFingerprint = legacyFingerprint(
name = "startVideoInformerFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.RETURN_VOID
),
strings = listOf("pc"),
customFingerprint = { method, _ ->
method.implementation
?.instructions
?.withIndex()
?.filter { (_, instruction) ->
instruction.opcode == Opcode.CONST_STRING
}
?.map { (index, _) -> index }
?.size == 1
}
)
internal val storyboardRendererDecoderRecommendedLevelFingerprint = legacyFingerprint(
name = "storyboardRendererDecoderRecommendedLevelFingerprint",

View File

@ -2,12 +2,14 @@
package app.revanced.patches.youtube.player.components
import app.revanced.patches.youtube.utils.resourceid.componentLongClickListener
import app.revanced.patches.youtube.utils.resourceid.darkBackground
import app.revanced.patches.youtube.utils.resourceid.donationCompanion
import app.revanced.patches.youtube.utils.resourceid.easySeekEduContainer
import app.revanced.patches.youtube.utils.resourceid.endScreenElementLayoutCircle
import app.revanced.patches.youtube.utils.resourceid.endScreenElementLayoutIcon
import app.revanced.patches.youtube.utils.resourceid.endScreenElementLayoutVideo
import app.revanced.patches.youtube.utils.resourceid.offlineActionsVideoDeletedUndoSnackbarText
import app.revanced.patches.youtube.utils.resourceid.scrubbing
import app.revanced.patches.youtube.utils.resourceid.seekEasyHorizontalTouchOffsetToStartScrubbing
import app.revanced.patches.youtube.utils.resourceid.suggestedAction
@ -207,6 +209,30 @@ internal val layoutVideoFingerprint = legacyFingerprint(
literals = listOf(endScreenElementLayoutVideo),
)
internal val lithoComponentOnClickListenerFingerprint = legacyFingerprint(
name = "lithoComponentOnClickListenerFingerprint",
returnType = "V",
accessFlags = AccessFlags.PRIVATE or AccessFlags.STATIC,
parameters = listOf("L"),
literals = listOf(componentLongClickListener),
)
internal val engagementPanelPlaylistSyntheticFingerprint = legacyFingerprint(
name = "engagementPanelPlaylistSyntheticFingerprint",
strings = listOf("engagement-panel-playlist"),
customFingerprint = { _, classDef ->
classDef.interfaces.contains("Landroid/view/View${'$'}OnClickListener;")
}
)
internal val offlineActionsOnClickListenerFingerprint = legacyFingerprint(
name = "offlineActionsOnClickListenerFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Ljava/lang/String;"),
literals = listOf(offlineActionsVideoDeletedUndoSnackbarText),
)
internal val quickSeekOverlayFingerprint = legacyFingerprint(
name = "quickSeekOverlayFingerprint",
returnType = "V",

View File

@ -13,6 +13,7 @@ import app.revanced.patches.shared.litho.addLithoFilter
import app.revanced.patches.shared.litho.lithoFilterPatch
import app.revanced.patches.shared.spans.addSpanFilter
import app.revanced.patches.shared.spans.inclusiveSpanPatch
import app.revanced.patches.shared.startVideoInformerFingerprint
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.controlsoverlay.controlsOverlayConfigPatch
import app.revanced.patches.youtube.utils.engagement.engagementPanelBuilderMethod
@ -42,6 +43,7 @@ import app.revanced.patches.youtube.utils.youtubeControlsOverlayFingerprint
import app.revanced.patches.youtube.video.information.hookVideoInformation
import app.revanced.patches.youtube.video.information.videoInformationPatch
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.util.Utils.printWarn
import app.revanced.util.findMethodOrThrow
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
import app.revanced.util.fingerprint.injectLiteralInstructionViewCall
@ -51,6 +53,7 @@ import app.revanced.util.fingerprint.mutableClassOrThrow
import app.revanced.util.fingerprint.resolvable
import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
@ -375,19 +378,70 @@ val playerComponentsPatch = bytecodePatch(
// region patch for disable auto player popup panels
engagementPanelBuilderMethod.addInstructionsWithLabels(
engagementPanelIdIndex, """
move/from16 v$engagementPanelFreeRegister, p4
invoke-static {v$engagementPanelFreeRegister, v$engagementPanelIdRegister}, $PLAYER_CLASS_DESCRIPTOR->disableAutoPlayerPopupPanels(ZLjava/lang/String;)Z
move-result v$engagementPanelFreeRegister
if-eqz v$engagementPanelFreeRegister, :shown
const/4 v$engagementPanelFreeRegister, 0x0
return-object v$engagementPanelFreeRegister
:shown
nop
"""
)
hookVideoInformation("$PLAYER_CLASS_DESCRIPTOR->disableAutoPlayerPopupPanels(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
fun MutableMethod.hookInitVideoPanel(initVideoPanel: Int) =
addInstructions(
0, """
const/4 v0, $initVideoPanel
invoke-static {v0}, $PLAYER_CLASS_DESCRIPTOR->setInitVideoPanel(Z)V
"""
)
if (is_20_05_or_greater) {
engagementPanelBuilderMethod.addInstructionsWithLabels(
engagementPanelIdIndex, """
move/from16 v$engagementPanelFreeRegister, p4
invoke-static {v$engagementPanelFreeRegister, v$engagementPanelIdRegister}, $PLAYER_CLASS_DESCRIPTOR->disableAutoPlayerPopupPanels(ZLjava/lang/String;)Z
move-result v$engagementPanelFreeRegister
if-eqz v$engagementPanelFreeRegister, :shown
const/4 v$engagementPanelFreeRegister, 0x0
return-object v$engagementPanelFreeRegister
:shown
nop
"""
)
hookVideoInformation("$PLAYER_CLASS_DESCRIPTOR->disableAutoPlayerPopupPanels(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
} else {
arrayOf(
lithoComponentOnClickListenerFingerprint,
offlineActionsOnClickListenerFingerprint,
).forEach { fingerprint ->
fingerprint.methodOrThrow().apply {
val syntheticIndex =
indexOfFirstInstruction(Opcode.NEW_INSTANCE)
if (syntheticIndex >= 0) {
val syntheticReference =
getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
findMethodOrThrow(syntheticReference) {
name == "onClick"
}.hookInitVideoPanel(0)
} else {
printWarn("target Opcode not found in ${fingerprint.first}")
}
}
}
findMethodOrThrow(
engagementPanelPlaylistSyntheticFingerprint.methodOrThrow().definingClass
) {
name == "onClick"
}.hookInitVideoPanel(0)
startVideoInformerFingerprint.methodOrThrow().hookInitVideoPanel(1)
engagementPanelBuilderMethod.addInstructionsWithLabels(
0, """
move/from16 v0, p4
invoke-static {v0}, $PLAYER_CLASS_DESCRIPTOR->disableAutoPlayerPopupPanels(Z)Z
move-result v0
if-eqz v0, :shown
const/4 v0, 0x0
return-object v0
:shown
nop
"""
)
}
// endregion

View File

@ -61,6 +61,8 @@ var compactLink = -1L
private set
var compactListItem = -1L
private set
var componentLongClickListener = -1L
private set
var contentPill = -1L
private set
var controlsLayoutStub = -1L
@ -143,6 +145,8 @@ var musicAppDeeplinkButtonView = -1L
private set
var notificationBigPictureIconWidth = -1L
private set
var offlineActionsVideoDeletedUndoSnackbarText = -1L
private set
var playerCollapseButton = -1L
private set
var playerControlPreviousButtonTouchArea = -1L
@ -348,6 +352,10 @@ internal val sharedResourceIdPatch = resourcePatch(
LAYOUT,
"compact_list_item"
]
componentLongClickListener = resourceMappings[
ID,
"component_long_click_listener"
]
contentPill = resourceMappings[
LAYOUT,
"content_pill"
@ -512,6 +520,10 @@ internal val sharedResourceIdPatch = resourcePatch(
DIMEN,
"notification_big_picture_icon_width"
]
offlineActionsVideoDeletedUndoSnackbarText = resourceMappings[
STRING,
"offline_actions_video_deleted_undo_snackbar_text"
]
playerCollapseButton = resourceMappings[
ID,
"player_collapse_button"