feat(YouTube/Hide shorts components): use browseId instead of navigation bar index

- Sometimes the Shorts shelves are loaded first before the navigation bar index is updated, and under certain circumstances the Shorts shelves are not hidden properly.
- This issue can be resolved by checking the browser id instead of the navigation bar index.
This commit is contained in:
inotia00 2024-04-23 22:17:20 +09:00
parent 12e88259e2
commit 1765d0575f
7 changed files with 65 additions and 132 deletions

View File

@ -17,7 +17,6 @@ import app.revanced.patches.youtube.shorts.components.fingerprints.ShortsPivotLe
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelDynRemix
@ -45,7 +44,6 @@ object ShortsComponentPatch : BaseBytecodePatch(
description = "Adds options to hide components related to YouTube Shorts.",
dependencies = setOf(
LithoFilterPatch::class,
NavigationBarHookPatch::class,
PlayerTypeHookPatch::class,
SettingsPatch::class,
SharedResourceIdPatch::class,

View File

@ -1,109 +0,0 @@
package app.revanced.patches.youtube.utils.browseid
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint
import app.revanced.patches.youtube.utils.browseid.fingerprints.BrowseIdClassFingerprint
import app.revanced.patches.youtube.utils.browseid.fingerprints.MobileTopBarDialogFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.util.getStringInstructionIndex
import app.revanced.util.getTargetIndex
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch(
dependencies = [
LithoFilterPatch::class,
MainActivityResolvePatch::class,
SharedResourceIdPatch::class
]
)
@Deprecated("This patch will be removed in the future.")
object BrowseIdHookPatch : BytecodePatch(
setOf(
BrowseIdClassFingerprint,
MobileTopBarDialogFingerprint,
PathBuilderFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"$SHARED_PATH/BrowseId;"
private const val SETTINGS_ACTIVITY_CLASS_DESCRIPTOR =
"Lcom/google/android/apps/youtube/app/settings/SettingsActivity;"
override fun execute(context: BytecodeContext) {
/**
* This class handles BrowseId.
* Pass an instance of this class to integrations to use Java Reflection.
*/
BrowseIdClassFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getStringInstructionIndex("VL") - 1
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
val targetClass = context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass
targetClass.methods.find { method -> method.name == "<init>" }
?.apply {
val browseIdFieldIndex = getTargetIndex(Opcode.IPUT_OBJECT)
val browseIdFieldName =
(getInstruction<ReferenceInstruction>(browseIdFieldIndex).reference as FieldReference).name
addInstructions(
1, """
const-string v0, "$browseIdFieldName"
invoke-static {p0, v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;Ljava/lang/String;)V
"""
)
} ?: throw PatchException("BrowseIdClass not found!")
}
}
val mobileTopBarDialogClass =
MobileTopBarDialogFingerprint.resultOrThrow().mutableClass
val mobileTopBarDialogOnBackPressedMethod =
mobileTopBarDialogClass.methods.single { method ->
method.name == "onBackPressed"
}
val mobileTopBarDialogOnStopMethod =
mobileTopBarDialogClass.methods.single { method ->
method.name == "onStop"
}
val pathBuilderMethod = PathBuilderFingerprint.resultOrThrow().mutableMethod
val settingsActivityOnBackPressedMethod =
context.findClass(SETTINGS_ACTIVITY_CLASS_DESCRIPTOR)!!.mutableClass.methods.single { method ->
method.name == "onBackPressed"
}
/**
* Set BrowseId to integrations.
*/
listOf(
MainActivityResolvePatch.onBackPressedMethod,
mobileTopBarDialogOnBackPressedMethod,
mobileTopBarDialogOnStopMethod,
pathBuilderMethod,
settingsActivityOnBackPressedMethod
).forEach { method ->
method.addInstruction(
0,
"invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->setBrowseIdFromField()V"
)
}
}
}

View File

@ -1,11 +0,0 @@
package app.revanced.patches.youtube.utils.browseid.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object MobileTopBarDialogFingerprint : MethodFingerprint(
returnType = "V",
customFingerprint = { methodDef, classDef ->
methodDef.name == "setContentView" &&
classDef.superclass == "Landroid/app/Dialog;"
}
)

View File

@ -10,7 +10,6 @@ import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.utils.fingerprints.InitializeButtonsFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch
import app.revanced.patches.youtube.utils.navigation.fingerprints.NavigationEnumFingerprint
import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButtonsCreateDrawableViewFingerprint
import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButtonsCreateResourceViewFingerprint
@ -18,19 +17,21 @@ import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButton
import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarConstructorFingerprint
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.util.addFieldAndInstructions
import app.revanced.util.getReference
import app.revanced.util.getTargetIndex
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
@Patch(
description = "Hooks the active navigation or search bar.",
dependencies = [
MainActivityResolvePatch::class,
PlayerTypeHookPatch::class,
SharedResourceIdPatch::class
],
@ -112,11 +113,6 @@ object NavigationBarHookPatch : BytecodePatch(
}
}
MainActivityResolvePatch.injectOnBackPressedMethodCall(
INTEGRATIONS_CLASS_DESCRIPTOR,
"onBackPressed"
)
navigationTabCreatedCallback = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
method.name == "navigationTabCreatedCallback"
} ?: throw PatchException("Could not find navigationTabCreatedCallback method")

View File

@ -5,23 +5,31 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
import app.revanced.patches.youtube.utils.playertype.fingerprint.ActionBarSearchResultsFingerprint
import app.revanced.patches.youtube.utils.playertype.fingerprint.BrowseIdClassFingerprint
import app.revanced.patches.youtube.utils.playertype.fingerprint.PlayerTypeFingerprint
import app.revanced.patches.youtube.utils.playertype.fingerprint.VideoStateFingerprint
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.util.addFieldAndInstructions
import app.revanced.util.getStringInstructionIndex
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch(dependencies = [SharedResourceIdPatch::class])
object PlayerTypeHookPatch : BytecodePatch(
setOf(
ActionBarSearchResultsFingerprint,
BrowseIdClassFingerprint,
PlayerTypeFingerprint,
YouTubeControlsOverlayFingerprint
)
@ -34,6 +42,8 @@ object PlayerTypeHookPatch : BytecodePatch(
override fun execute(context: BytecodeContext) {
// region patch for set player type
PlayerTypeFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstruction(
@ -44,6 +54,10 @@ object PlayerTypeHookPatch : BytecodePatch(
}
}
// endregion
// region patch for set video state
YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult ->
VideoStateFingerprint.also { it.resolve(context, parentResult.classDef)
}.resultOrThrow().let {
@ -62,7 +76,51 @@ object PlayerTypeHookPatch : BytecodePatch(
}
}
// Hook the search bar.
// endregion
// region patch for hook browse id
BrowseIdClassFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getStringInstructionIndex("VL") - 1
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
val targetClass = context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass
targetClass.methods.find { method -> method.name == "<init>" }
?.apply {
val browseIdFieldIndex = getTargetIndex(Opcode.IPUT_OBJECT)
val browseIdFieldName =
(getInstruction<ReferenceInstruction>(browseIdFieldIndex).reference as FieldReference).name
val smaliInstructions =
"""
if-eqz v0, :ignore
iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String;
if-eqz v0, :ignore
return-object v0
:ignore
const-string v0, ""
return-object v0
"""
val rootViewMutableClass =
context.findClass(INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR)!!.mutableClass
rootViewMutableClass.addFieldAndInstructions(
context,
"getBrowseId",
"browseIdClass",
definingClass,
smaliInstructions,
true
)
} ?: throw PatchException("BrowseIdClass not found!")
}
}
// endregion
// region patch for hook search bar
// Two different layouts are used at the hooked code.
// Insert before the first ViewGroup method call after inflating,
@ -78,6 +136,7 @@ object PlayerTypeHookPatch : BytecodePatch(
)
}
// endregion
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.utils.browseid.fingerprints
package app.revanced.patches.youtube.utils.playertype.fingerprint
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -397,7 +397,7 @@ fun MutableClass.addFieldAndInstructions(
if (shouldAddConstructor) {
context.findClass(objectClass)!!.mutableClass.methods
.filter { method -> MethodUtil.isConstructor(method) }
.filter { method -> method.name == "<init>" }
.forEach { mutableMethod ->
mutableMethod.apply {
val initializeIndex = getTargetIndexWithMethodReferenceName("<init>")