fix(YouTube/Fix suggested video end screen): no longer closes the suggested video end screen, but instead follows the autoplay settings

This commit is contained in:
inotia00 2024-04-05 02:37:58 +09:00
parent 30fc242496
commit f51739a4fe
9 changed files with 110 additions and 149 deletions

View File

@ -0,0 +1,81 @@
package app.revanced.patches.youtube.player.suggestedvideoendscreen
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.player.suggestedvideoendscreen.fingerprints.RemoveOnLayoutChangeListenerFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexReversed
import app.revanced.util.getWalkerMethod
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Suppress("unused")
object SuggestedVideoEndScreenPatch : BaseBytecodePatch(
name = "Fix suggested video end screen",
description = "Fixes an issue where the suggested video end screen is shown at the end of a video, regardless of whether autoplay setting is on or off.",
dependencies = setOf(SettingsPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(RemoveOnLayoutChangeListenerFingerprint)
) {
override fun execute(context: BytecodeContext) {
/**
* The reasons why this patch is classified as a patch that fixes a 'bug' are as follows:
* 1. In YouTube v18.29.38, the suggested video end screen was only shown when the autoplay setting was turned on.
* 2. Starting from YouTube v18.35.36, the suggested video end screen is shown regardless of whether autoplay setting was turned on or off.
*
* This patch changes the suggested video end screen to be shown only when the autoplay setting is turned on.
* Automatically closing the suggested video end screen is not appropriate as it will disable the autoplay behavior.
*/
RemoveOnLayoutChangeListenerFingerprint.resultOrThrow().let {
val walkerIndex = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
walkerIndex.apply {
val invokeInterfaceIndex = getTargetIndex(Opcode.INVOKE_INTERFACE)
val iGetObjectIndex = getTargetIndexReversed(invokeInterfaceIndex, Opcode.IGET_OBJECT)
val invokeInterfaceReference = getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference
val iGetObjectReference = getInstruction<ReferenceInstruction>(iGetObjectIndex).reference
addInstructionsWithLabels(
0,
"""
iget-object v0, p0, $iGetObjectReference
# This reference checks whether autoplay is turned on.
invoke-interface {v0}, $invokeInterfaceReference
move-result v0
# Hide suggested video end screen only when autoplay is turned off.
if-nez v0, :show_suggested_video_end_screen
return-void
""",
ExternalLabel(
"show_suggested_video_end_screen",
getInstruction(0)
)
)
}
}
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: PLAYER_SETTINGS",
"SETTINGS: PLAYER_EXPERIMENTAL_FLAGS",
"SETTINGS: HIDE_SUGGESTED_VIDEO_END_SCREEN"
)
)
SettingsPatch.updatePatchStatus("Fix suggested video end screen")
}
}

View File

@ -0,0 +1,22 @@
package app.revanced.patches.youtube.player.suggestedvideoendscreen.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.fingerprint.ReferenceFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* This fingerprint is also compatible with very old YouTube versions.
* Tested on YouTube v16.40.36, v18.29.38, v19.12.41.
*/
internal object RemoveOnLayoutChangeListenerFingerprint : ReferenceFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.IPUT,
Opcode.INVOKE_VIRTUAL
),
// This is the only reference present in the entire smali.
reference = { "YouTubePlayerOverlaysLayout;->removeOnLayoutChangeListener(Landroid/view/View${'$'}OnLayoutChangeListener;)V" }
)

View File

@ -1,95 +0,0 @@
package app.revanced.patches.youtube.player.suggestedvideooverlay
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.player.suggestedvideooverlay.fingerprints.CoreContainerBuilderFingerprint
import app.revanced.patches.youtube.player.suggestedvideooverlay.fingerprints.MiniPlayerPlayButtonFingerprint
import app.revanced.patches.youtube.player.suggestedvideooverlay.fingerprints.TouchAreaOnClickListenerFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Suppress("unused")
object SuggestedVideoOverlayPatch : BaseBytecodePatch(
name = "Hide suggested video overlay",
description = "Adds an option to hide the suggested video overlay at the end of videos.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
CoreContainerBuilderFingerprint,
TouchAreaOnClickListenerFingerprint
)
) {
override fun execute(context: BytecodeContext) {
CoreContainerBuilderFingerprint.resultOrThrow().let { parentResult ->
parentResult.mutableMethod.apply {
val addOnClickEventListenerIndex = parentResult.scanResult.patternScanResult!!.endIndex - 1
val viewRegister = getInstruction<FiveRegisterInstruction>(addOnClickEventListenerIndex).registerC
addInstruction(
addOnClickEventListenerIndex + 1,
"invoke-static {v$viewRegister}, $PLAYER_CLASS_DESCRIPTOR->hideSuggestedVideoOverlay(Landroid/widget/ImageView;)V"
)
}
// Resolves fingerprints
MiniPlayerPlayButtonFingerprint.resolve(context, parentResult.classDef)
MiniPlayerPlayButtonFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstructionsWithLabels(
0, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSuggestedVideoOverlay()Z
move-result v0
if-eqz v0, :show
return-void
""", ExternalLabel("show", getInstruction(0))
)
}
}
}
TouchAreaOnClickListenerFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertMethod = it.mutableClass.methods.find { method -> method.parameters == listOf("Landroid/view/View${'$'}OnClickListener;") }
insertMethod?.apply {
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener")
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
addInstruction(
setOnClickListenerIndex + 1,
"invoke-static {v$setOnClickListenerRegister}, $PLAYER_CLASS_DESCRIPTOR->hideSuggestedVideoOverlayAutoPlay(Landroid/view/View;)V"
)
} ?: throw PatchException("Failed to find setOnClickListener method")
}
}
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: PLAYER_SETTINGS",
"SETTINGS: PLAYER_EXPERIMENTAL_FLAGS",
"SETTINGS: HIDE_SUGGESTED_VIDEO_OVERLAY"
)
)
SettingsPatch.updatePatchStatus("Hide suggested video overlay")
}
}

View File

@ -1,19 +0,0 @@
package app.revanced.patches.youtube.player.suggestedvideooverlay.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CoreContainer
import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object CoreContainerBuilderFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/content/Context;"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST
),
literalSupplier = { CoreContainer }
)

View File

@ -1,11 +0,0 @@
package app.revanced.patches.youtube.player.suggestedvideooverlay.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object MiniPlayerPlayButtonFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/content/Context;", "Landroid/view/View;")
)

View File

@ -1,12 +0,0 @@
package app.revanced.patches.youtube.player.suggestedvideooverlay.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TouchArea
import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object TouchAreaOnClickListenerFingerprint : LiteralValueFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
literalSupplier = { TouchArea }
)

View File

@ -32,7 +32,6 @@ object SharedResourceIdPatch : ResourcePatch() {
var CompactLink = -1L
var CompactListItem = -1L
var ControlsLayoutStub = -1L
var CoreContainer = -1L
var DarkSplashAnimation = -1L
var DonationCompanion = -1L
var EasySeekEduContainer = -1L
@ -84,7 +83,6 @@ object SharedResourceIdPatch : ResourcePatch() {
var TabsBarTextTabView = -1L
var ToolTipContentView = -1L
var TotalTime = -1L
var TouchArea = -1L
var VideoQualityBottomSheet = -1L
var VideoZoomIndicatorLayout = -1L
var YoutubeControlsOverlay = -1L
@ -108,7 +106,6 @@ object SharedResourceIdPatch : ResourcePatch() {
CompactLink = getId(LAYOUT, "compact_link")
CompactListItem = getId(LAYOUT, "compact_list_item")
ControlsLayoutStub = getId(ID, "controls_layout_stub")
CoreContainer = getId(ID, "core_container")
DarkSplashAnimation = getId(ID, "dark_splash_animation")
DonationCompanion = getId(LAYOUT, "donation_companion")
EasySeekEduContainer = getId(ID, "easy_seek_edu_container")
@ -162,7 +159,6 @@ object SharedResourceIdPatch : ResourcePatch() {
TabsBarTextTabView = getId(ID, "tabs_bar_text_tab_view")
ToolTipContentView = getId(LAYOUT, "tooltip_content_view")
TotalTime = getId(STRING, "total_time")
TouchArea = getId(ID, "touch_area")
VideoQualityBottomSheet = getId(LAYOUT, "video_quality_bottom_sheet_list_fragment_title")
VideoZoomIndicatorLayout = getId(ID, "video_zoom_indicator_layout")
YoutubeControlsOverlay = getId(ID, "youtube_controls_overlay")

View File

@ -664,10 +664,10 @@ Known issue: Official headers in search results will be hidden."</string>
<string name="revanced_hide_suggested_actions_summary_off">Suggested actions shown.</string>
<string name="revanced_hide_suggested_actions_summary_on">Suggested actions hidden.</string>
<string name="revanced_hide_suggested_actions_title">Hide suggested actions</string>
<string name="revanced_hide_suggested_video_overlay_auto_play_summary">When you finished a video, another play automatically</string>
<string name="revanced_hide_suggested_video_overlay_auto_play_title">Auto play the next video</string>
<string name="revanced_hide_suggested_video_overlay_summary">Hides suggested video overlay to play next.</string>
<string name="revanced_hide_suggested_video_overlay_title">Hide suggested video overlay</string>
<string name="revanced_hide_suggested_video_end_screen_summary">"This setting has been deprecated.
Instead, use the 'Settings → Autoplay → Autoplay next video' setting."</string>
<string name="revanced_hide_suggested_video_end_screen_title">Hide suggested video end screen</string>
<string name="revanced_hide_suggestions_shelf_summary">"Hides following shelves:
• Breaking news
• Continue watching

View File

@ -479,6 +479,7 @@
<Preference android:title="Custom player overlay opacity" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Disable haptic feedback" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Disable speed overlay" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Fix suggested video end screen" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Hide autoplay button" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Hide captions button" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Hide channel watermark" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
@ -491,7 +492,6 @@
<Preference android:title="Hide previous next button" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Hide seek message" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Hide suggested actions" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title="Hide suggested video overlay" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
<Preference android:title=" " android:selectable="false" android:summary="@string/revanced_seekbar" />
<Preference android:title="Append time stamps information" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
@ -626,9 +626,8 @@
<!-- SETTINGS: HIDE_FILMSTRIP_OVERLAY
<SwitchPreference android:title="@string/revanced_hide_filmstrip_overlay_title" android:key="revanced_hide_filmstrip_overlay" android:defaultValue="false" android:summaryOn="@string/revanced_hide_filmstrip_overlay_summary_on" android:summaryOff="@string/revanced_hide_filmstrip_overlay_summary_off" />SETTINGS: HIDE_FILMSTRIP_OVERLAY -->
<!-- SETTINGS: HIDE_SUGGESTED_VIDEO_OVERLAY
<SwitchPreference android:title="@string/revanced_hide_suggested_video_overlay_title" android:key="revanced_hide_suggested_video_overlay" android:defaultValue="false" android:summary="@string/revanced_hide_suggested_video_overlay_summary" />
<SwitchPreference android:title="@string/revanced_hide_suggested_video_overlay_auto_play_title" android:key="revanced_hide_suggested_video_overlay_auto_play" android:defaultValue="false" android:summary="@string/revanced_hide_suggested_video_overlay_auto_play_summary" android:dependency="revanced_hide_suggested_video_overlay" />SETTINGS: HIDE_SUGGESTED_VIDEO_OVERLAY -->
<!-- SETTINGS: HIDE_SUGGESTED_VIDEO_END_SCREEN
<Preference android:title="@string/revanced_hide_suggested_video_end_screen_title" android:key="revanced_hide_suggested_video_end_screen" android:defaultValue="false" android:selectable="false" android:summary="@string/revanced_hide_suggested_video_end_screen_summary" />SETTINGS: HIDE_SUGGESTED_VIDEO_END_SCREEN -->
<!-- SETTINGS: DISABLE_HAPTIC_FEEDBACK
<Preference android:title=" " android:selectable="false" android:summary="@string/revanced_haptic_feedback_title" />