diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt index 8131fa90e..3a9ae3238 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt @@ -2,68 +2,46 @@ package app.revanced.patches.youtube.ads.general.bytecode.patch import app.revanced.extensions.findMutableMethodOf import app.revanced.extensions.injectHideCall -import app.revanced.extensions.toResult import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.shared.annotation.YouTubeCompatibility -import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch import app.revanced.util.bytecode.BytecodeHelper.updatePatchStatus -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.* +import org.jf.dexlib2.iface.instruction.formats.Instruction31i +import org.jf.dexlib2.iface.instruction.formats.Instruction35c @Name("hide-general-ads-bytecode-patch") -@DependsOn([ResourceMappingPatch::class]) -@YouTubeCompatibility +@DependsOn([SharedResourceIdPatch::class]) @Version("0.0.1") class GeneralAdsBytecodePatch : BytecodePatch() { - private val resourceIds = arrayOf( - "id" to "ad_attribution", - "layout" to "horizontal_card_list" - ).map { (type, name) -> - ResourceMappingPatch - .resourceMappings - .single { it.type == type && it.name == name }.id - } - private var patchSuccessArray = Array(resourceIds.size) {false} - override fun execute(context: BytecodeContext): PatchResult { context.classes.forEach { classDef -> classDef.methods.forEach { method -> with(method.implementation) { this?.instructions?.forEachIndexed { index, instruction -> - when (instruction.opcode) { - Opcode.CONST -> { - when ((instruction as Instruction31i).wideLiteral) { - resourceIds[0] -> { // general ads - val insertIndex = index + 1 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed + if (instruction.opcode != org.jf.dexlib2.Opcode.CONST) + return@forEachIndexed + // Instruction to store the id adAttribution into a register + if ((instruction as Instruction31i).wideLiteral != SharedResourceIdPatch.adAttributionLabelId) + return@forEachIndexed - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + val insertIndex = index + 1 - val viewRegister = (invokeInstruction as Instruction35c).registerC - mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideAdAttributionView") - patchSuccessArray[0] = true - } + // Call to get the view with the id adAttribution + with(instructions.elementAt(insertIndex)) { + if (opcode != org.jf.dexlib2.Opcode.INVOKE_VIRTUAL) + return@forEachIndexed - resourceIds[1] -> { // breaking news - val insertIndex = index + 4 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - - val viewRegister = (invokeInstruction as Instruction21c).registerA - mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideBreakingNewsShelf") - patchSuccessArray[1] = true - } - } - } - else -> return@forEachIndexed + // Hide the view + val viewRegister = (this as Instruction35c).registerC + context.proxy(classDef) + .mutableClass + .findMutableMethodOf(method) + .implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideAdAttributionView") } } } @@ -71,6 +49,6 @@ class GeneralAdsBytecodePatch : BytecodePatch() { } context.updatePatchStatus("GeneralAds") - return toResult(patchSuccessArray.indexOf(false)) + return PatchResultSuccess() } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/breakingnews/fingerprints/BreakingNewsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/breakingnews/fingerprints/BreakingNewsFingerprint.kt new file mode 100644 index 000000000..2ae095107 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/breakingnews/fingerprints/BreakingNewsFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.youtube.layout.general.breakingnews.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +object BreakingNewsFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.CONST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { instruction -> + instruction.opcode.ordinal == Opcode.CONST.ordinal && + (instruction as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.horizontalCardListId + } == true + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/breakingnews/patch/BreakingNewsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/breakingnews/patch/BreakingNewsPatch.kt new file mode 100644 index 000000000..b2b046d53 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/breakingnews/patch/BreakingNewsPatch.kt @@ -0,0 +1,64 @@ +package app.revanced.patches.youtube.layout.general.breakingnews.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.shared.annotation.YouTubeCompatibility +import app.revanced.patches.youtube.layout.general.breakingnews.fingerprints.BreakingNewsFingerprint +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch +import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch +import app.revanced.util.integrations.Constants.GENERAL +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch +@Name("hide-breaking-news-shelf") +@Description("Hides the breaking news shelf on the homepage tab.") +@DependsOn( + [ + SettingsPatch::class, + SharedResourceIdPatch::class, + ] +) +@YouTubeCompatibility +@Version("0.0.1") +class BreakingNewsPatch : BytecodePatch( + listOf( + BreakingNewsFingerprint, + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + BreakingNewsFingerprint.result?.let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = (instruction(targetIndex) as OneRegisterInstruction).registerA + addInstruction( + targetIndex + 1, + "invoke-static {v$targetRegister}, $GENERAL->hideBreakingNewsShelf(Landroid/view/View;)V" + ) + } + }?: return BreakingNewsFingerprint.toErrorResult() + + /** + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE: GENERAL_SETTINGS", + "SETTINGS: HIDE_BREAKING_NEWS_SHELF" + ) + ) + + SettingsPatch.updatePatchStatus("hide-breaking-news-shelf") + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt index 41f2cd511..b85052b51 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt @@ -20,6 +20,7 @@ class SharedResourceIdPatch : ResourcePatch { internal companion object { var accessibilityProgressTimeLabelId: Long = -1 var accountSwitcherAccessibilityLabelId: Long = -1 + var adAttributionLabelId: Long = -1 var appearanceStringId: Long = -1 var backgroundCategoryLabelId: Long = -1 var barContainerHeightLabelId: Long = -1 @@ -33,6 +34,7 @@ class SharedResourceIdPatch : ResourcePatch { var fabLabelId: Long = -1 var filterBarHeightLabelId: Long = -1 var floatyBarTopMarginLabelId: Long = -1 + var horizontalCardListId: Long = -1 var imageOnlyTabId: Long = -1 var inlineTimeBarColorizedBarPlayedColorDarkId: Long = -1 var inlineTimeBarPlayedNotHighlightedColorId: Long = -1 @@ -64,6 +66,7 @@ class SharedResourceIdPatch : ResourcePatch { accessibilityProgressTimeLabelId = find(STRING, "accessibility_player_progress_time") accountSwitcherAccessibilityLabelId = find(STRING, "account_switcher_accessibility_label") + adAttributionLabelId = find(ID, "ad_attribution") appearanceStringId = find(STRING, "app_theme_appearance_dark") backgroundCategoryLabelId = find(STRING, "pref_background_and_offline_category") barContainerHeightLabelId = find(DIMEN, "bar_container_height") @@ -77,6 +80,7 @@ class SharedResourceIdPatch : ResourcePatch { fabLabelId = find(ID, "fab") filterBarHeightLabelId = find(DIMEN, "filter_bar_height") floatyBarTopMarginLabelId = find(DIMEN, "floaty_bar_button_top_margin") + horizontalCardListId = find(LAYOUT, "horizontal_card_list") imageOnlyTabId = find(LAYOUT, "image_only_tab") inlineTimeBarColorizedBarPlayedColorDarkId = find(COLOR, "inline_time_bar_colorized_bar_played_color_dark") inlineTimeBarPlayedNotHighlightedColorId = find(COLOR, "inline_time_bar_played_not_highlighted_color") diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index ed20fac40..56e879893 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -135,10 +135,12 @@ - SETTINGS: HIDE_GENERAL_ADS --> + + @@ -479,6 +481,7 @@ +