diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/SuggestionsShelfPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/SuggestionsShelfPatch.kt index 62c160dc1..9ba886331 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/SuggestionsShelfPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/SuggestionsShelfPatch.kt @@ -3,34 +3,23 @@ package app.revanced.patches.youtube.general.suggestions import app.revanced.extensions.exception 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.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.shared.patch.litho.ComponentParserPatch.emptyComponentLabel import app.revanced.patches.youtube.general.suggestions.fingerprints.BreakingNewsFingerprint -import app.revanced.patches.youtube.general.suggestions.fingerprints.SuggestionContentsBuilderFingerprint -import app.revanced.patches.youtube.general.suggestions.fingerprints.SuggestionContentsBuilderLegacyFingerprint +import app.revanced.patches.youtube.utils.browseid.BrowseIdHookPatch import app.revanced.patches.youtube.utils.litho.LithoFilterPatch -import app.revanced.patches.youtube.utils.navigationbuttons.NavigationButtonHookPatch -import app.revanced.patches.youtube.utils.navigationbuttons.NavigationButtonHookPatch.PivotBarMethod -import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AvatarImageWithTextTab import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.bytecode.getWideLiteralIndex import app.revanced.util.integrations.Constants.COMPONENTS_PATH -import app.revanced.util.pivotbar.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.pivotbar.InjectionUtils.injectHook -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( name = "Hide suggestions shelf", description = "Hides the suggestions shelf.", dependencies = [ + BrowseIdHookPatch::class, LithoFilterPatch::class, - NavigationButtonHookPatch::class, SettingsPatch::class ], compatiblePackages = [ @@ -57,12 +46,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction ) @Suppress("unused") object SuggestionsShelfPatch : BytecodePatch( - setOf( - BreakingNewsFingerprint, - SuggestionContentsBuilderFingerprint, - SuggestionContentsBuilderLegacyFingerprint - ) + setOf(BreakingNewsFingerprint) ) { + private const val FILTER_CLASS_DESCRIPTOR = + "$COMPONENTS_PATH/SuggestionsShelfFilter;" + override fun execute(context: BytecodeContext) { /** @@ -80,37 +68,6 @@ object SuggestionsShelfPatch : BytecodePatch( } } ?: throw BreakingNewsFingerprint.exception - /** - * Target method only removes the horizontal video shelf's content in the feed. - * Since the header of the horizontal video shelf is not removed, it should be removed through the SuggestionsShelfFilter - */ - val result = SuggestionContentsBuilderFingerprint.result // YouTube v18.36.xx ~ - ?: SuggestionContentsBuilderLegacyFingerprint.result // ~ YouTube v18.35.xx - ?: throw SuggestionContentsBuilderFingerprint.exception - - result.let { - it.mutableMethod.apply { - addInstructionsWithLabels( - 2, """ - invoke-static/range {p2 .. p2}, $FILTER_CLASS_DESCRIPTOR->filterSuggestionsShelfSubComponents(Ljava/lang/Object;)Z - move-result v0 - if-eqz v0, :show - """ + emptyComponentLabel, ExternalLabel("show", getInstruction(2)) - ) - } - } - - PivotBarMethod.apply { - val insertIndex = implementation!!.instructions.let { - val scanStart = getWideLiteralIndex(AvatarImageWithTextTab) - - scanStart + it.subList(scanStart, it.size - 1).indexOfFirst { instruction -> - instruction.opcode == Opcode.INVOKE_VIRTUAL - } - } + 2 - injectHook(YOU_BUTTON_HOOK, insertIndex) - } - LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) @@ -127,12 +84,4 @@ object SuggestionsShelfPatch : BytecodePatch( SettingsPatch.updatePatchStatus("Hide suggestions shelf") } - - private const val FILTER_CLASS_DESCRIPTOR = - "$COMPONENTS_PATH/SuggestionsShelfFilter;" - - private const val YOU_BUTTON_HOOK = - "invoke-static { v${REGISTER_TEMPLATE_REPLACEMENT} }, $FILTER_CLASS_DESCRIPTOR" + - "->" + - "isYouButtonEnabled(Landroid/view/View;)V" } diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/SuggestionContentsBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/SuggestionContentsBuilderFingerprint.kt deleted file mode 100644 index 316c9ebd3..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/SuggestionContentsBuilderFingerprint.kt +++ /dev/null @@ -1,45 +0,0 @@ -package app.revanced.patches.youtube.general.suggestions.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -object SuggestionContentsBuilderFingerprint : MethodFingerprint( - returnType = "L", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("L", "L"), - opcodes = listOf( - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IGET_OBJECT, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_EQZ, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.IGET_OBJECT, - Opcode.IGET, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST_4, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.INVOKE_VIRTUAL_RANGE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.RETURN_OBJECT - ), - customFingerprint = { methodDef, classDef -> - classDef.methods.count() == 2 - && methodDef.name == "a" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/SuggestionContentsBuilderLegacyFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/SuggestionContentsBuilderLegacyFingerprint.kt deleted file mode 100644 index cddb00f75..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/SuggestionContentsBuilderLegacyFingerprint.kt +++ /dev/null @@ -1,40 +0,0 @@ -package app.revanced.patches.youtube.general.suggestions.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -object SuggestionContentsBuilderLegacyFingerprint : MethodFingerprint( - returnType = "L", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("L", "L"), - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IPUT_OBJECT, - null, - null, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT - ), - customFingerprint = { methodDef, classDef -> - classDef.methods.count() == 3 - && methodDef.name == "a" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt index d27fafa32..a3d349fb7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt @@ -10,9 +10,8 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.AutoMotiveFingerprint import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarEnumFingerprint import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarShortsButtonViewFingerprint -import app.revanced.patches.youtube.utils.navigationbuttons.NavigationButtonHookPatch -import app.revanced.patches.youtube.utils.navigationbuttons.NavigationButtonHookPatch.PivotBarMethod -import app.revanced.patches.youtube.utils.navigationbuttons.NavigationButtonHookPatch.PivotBarResult +import app.revanced.patches.youtube.utils.fingerprints.PivotBarCreateButtonViewFingerprint +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AvatarImageWithTextTab import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ImageOnlyTab import app.revanced.patches.youtube.utils.settings.SettingsPatch @@ -27,8 +26,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction name = "Hide navigation buttons", description = "Adds options to hide or change navigation buttons.", dependencies = [ - NavigationButtonHookPatch::class, - SettingsPatch::class + SettingsPatch::class, + SharedResourceIdPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -54,52 +53,66 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction ) @Suppress("unused") object NavigationButtonsPatch : BytecodePatch( - setOf(AutoMotiveFingerprint) + setOf( + AutoMotiveFingerprint, + PivotBarCreateButtonViewFingerprint + ) ) { override fun execute(context: BytecodeContext) { - val pivotBarList = - arrayOf( - PivotBarEnumFingerprint, - PivotBarShortsButtonViewFingerprint - ).onEach { - it.resolve( - context, - PivotBarResult.classDef - ) - }.map { fingerprint -> - fingerprint.result?.scanResult?.patternScanResult - ?: throw fingerprint.exception + PivotBarCreateButtonViewFingerprint.result?.let { parentResult -> + + /** + * Home, Shorts, Subscriptions Button + */ + with( + arrayOf( + PivotBarEnumFingerprint, + PivotBarShortsButtonViewFingerprint + ).onEach { + it.resolve( + context, + parentResult.mutableMethod, + parentResult.mutableClass + ) + }.map { + it.result?.scanResult?.patternScanResult ?: throw it.exception + } + ) { + val enumScanResult = this[0] + val buttonViewResult = this[1] + + val enumHookInsertIndex = enumScanResult.startIndex + 2 + val buttonHookInsertIndex = buttonViewResult.endIndex + + mapOf( + BUTTON_HOOK to buttonHookInsertIndex, + ENUM_HOOK to enumHookInsertIndex + ).forEach { (hook, insertIndex) -> + parentResult.mutableMethod.injectHook(hook, insertIndex) + } } - PivotBarMethod.apply { - val enumScanResult = pivotBarList[0] - val buttonViewResult = pivotBarList[1] + /** + * Create, You Button + */ + parentResult.mutableMethod.apply { + mapOf( + CREATE_BUTTON_HOOK to ImageOnlyTab, + YOU_BUTTON_HOOK to AvatarImageWithTextTab + ).forEach { (hook, resourceId) -> + val insertIndex = implementation!!.instructions.let { + val scanStart = getWideLiteralIndex(resourceId) - val enumHookInsertIndex = enumScanResult.startIndex + 2 - val buttonHookInsertIndex = buttonViewResult.endIndex - - mapOf( - BUTTON_HOOK to buttonHookInsertIndex, - ENUM_HOOK to enumHookInsertIndex - ).forEach { (hook, insertIndex) -> - injectHook(hook, insertIndex) + scanStart + it.subList(scanStart, it.size - 1).indexOfFirst { instruction -> + instruction.opcode == Opcode.INVOKE_VIRTUAL + } + } + 2 + injectHook(hook, insertIndex) + } } - mapOf( - CREATE_BUTTON_HOOK to ImageOnlyTab, - YOU_BUTTON_HOOK to AvatarImageWithTextTab - ).forEach { (hook, resourceId) -> - val insertIndex = implementation!!.instructions.let { - val scanStart = getWideLiteralIndex(resourceId) - - scanStart + it.subList(scanStart, it.size - 1).indexOfFirst { instruction -> - instruction.opcode == Opcode.INVOKE_VIRTUAL - } - } + 2 - injectHook(hook, insertIndex) - } - } + } ?: throw PivotBarCreateButtonViewFingerprint.exception /** * Switch create button with notifications button diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/browseid/BrowseIdHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/browseid/BrowseIdHookPatch.kt new file mode 100644 index 000000000..171095cee --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/browseid/BrowseIdHookPatch.kt @@ -0,0 +1,68 @@ +package app.revanced.patches.youtube.utils.browseid + +import app.revanced.extensions.exception +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.annotation.Patch +import app.revanced.patches.shared.patch.litho.ComponentParserPatch +import app.revanced.patches.youtube.utils.browseid.fingerprints.BrowseIdClassFingerprint +import app.revanced.patches.youtube.utils.fingerprints.SetToolBarPaddingFingerprint +import app.revanced.patches.youtube.utils.litho.LithoFilterPatch +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.util.integrations.Constants.UTILS_PATH +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, + SharedResourceIdPatch::class + ] +) +object BrowseIdHookPatch : BytecodePatch( + setOf( + BrowseIdClassFingerprint, + SetToolBarPaddingFingerprint + ) +) { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = + "$UTILS_PATH/BrowseIdPatch;" + + override fun execute(context: BytecodeContext) { + + /** + * This class handles BrowseId. + * Pass an instance of this class to integrations to use Java Reflection. + */ + BrowseIdClassFingerprint.result + ?.mutableClass?.methods?.find { method -> method.name == "" } + ?.apply { + val browseIdFieldIndex = implementation!!.instructions.indexOfFirst { instruction -> + instruction.opcode == Opcode.IPUT_OBJECT + } + val browseIdFieldName = + (getInstruction(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 BrowseIdClassFingerprint.exception + + /** + * Set BrowseId to integrations. + */ + ComponentParserPatch.insertMethod.apply { + addInstruction( + 0, + "invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->setBrowseIdFromField()V" + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/browseid/fingerprints/BrowseIdClassFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/browseid/fingerprints/BrowseIdClassFingerprint.kt new file mode 100644 index 000000000..ff0136c8c --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/browseid/fingerprints/BrowseIdClassFingerprint.kt @@ -0,0 +1,7 @@ +package app.revanced.patches.youtube.utils.browseid.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +object BrowseIdClassFingerprint : MethodFingerprint( + strings = listOf("\u0001\t\u0000\u0001\u0002\u0010\t\u0000\u0000\u0001\u0002\u1008\u0000\u0003\u1008\u0002\u0005\u1008\u0003\u0006\u1409\u0005\u0007\u1007\u0004\u0008\u1009\u0006\u000c\u1008\n\u000e\u180c\u000b\u0010\u1007\r") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navigationbuttons/NavigationButtonHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigationbuttons/NavigationButtonHookPatch.kt deleted file mode 100644 index fb70dd6c6..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/navigationbuttons/NavigationButtonHookPatch.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.revanced.patches.youtube.utils.navigationbuttons - -import app.revanced.extensions.exception -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.fingerprint.MethodFingerprintResult -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.utils.fingerprints.PivotBarCreateButtonViewFingerprint -import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch - -@Patch(dependencies = [SharedResourceIdPatch::class]) -object NavigationButtonHookPatch : BytecodePatch( - setOf(PivotBarCreateButtonViewFingerprint) -) { - internal lateinit var PivotBarResult: MethodFingerprintResult - internal lateinit var PivotBarMethod: MutableMethod - - override fun execute(context: BytecodeContext) { - PivotBarResult = PivotBarCreateButtonViewFingerprint.result - ?: throw PivotBarCreateButtonViewFingerprint.exception - - PivotBarMethod = PivotBarResult.mutableMethod - } -} \ No newline at end of file