diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt index dddf408c0..5502d338b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt @@ -51,9 +51,6 @@ class GeneralBytecodeAdsPatch : BytecodePatch() { "ad_attribution", "reel_multiple_items_shelf", "info_cards_drawer_header", - "endscreen_element_layout_video", - "endscreen_element_layout_circle", - "endscreen_element_layout_icon", ).map { name -> ResourceMappingResourcePatch.resourceMappings.single { it.name == name }.id } @@ -242,26 +239,6 @@ class GeneralBytecodeAdsPatch : BytecodePatch() { //ToDo: Add Settings toggle for whatever this is mutableMethod!!.implementation!!.removeInstruction(removeIndex) } - - resourceIds[3], resourceIds[4], resourceIds[5] -> { // end screen ads - // and is followed by an instruction with the mnemonic IPUT_OBJECT - val insertIndex = index + 7 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed - - // create proxied method, make sure to not re-resolve() the current class - if (mutableClass == null) mutableClass = context.proxy(classDef).mutableClass - if (mutableMethod == null) mutableMethod = - mutableClass!!.findMutableMethodOf(method) - - // TODO: dynamically get registers - mutableMethod!!.addInstructions( - insertIndex, """ - const/16 v1, 0x8 - invoke-virtual {v0,v1}, Landroid/widget/FrameLayout;->setVisibility(I)V - """ - ) - } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt new file mode 100644 index 000000000..ec0e3812b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.hideendscreencards.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class HideEndscreenCardsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt new file mode 100644 index 000000000..722aa6230 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility +import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +@Name("layout-circle-fingerprint") +@HideEndscreenCardsCompatibility +@Version("0.0.1") +object LayoutCircleFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.CONST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { instruction -> + instruction.opcode.ordinal == Opcode.CONST.ordinal && + (instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutCircle + } == true + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt new file mode 100644 index 000000000..dc59051fd --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility +import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +@Name("layout-icon-fingerprint") +@HideEndscreenCardsCompatibility +@Version("0.0.1") +object LayoutIconFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.CONST_4, + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { instruction -> + instruction.opcode.ordinal == Opcode.CONST.ordinal && + (instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutIcon + } == true + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt new file mode 100644 index 000000000..ca4d2e85a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility +import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +@Name("layout-video-fingerprint") +@HideEndscreenCardsCompatibility +@Version("0.0.1") +object LayoutVideoFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.CONST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { instruction -> + instruction.opcode.ordinal == Opcode.CONST.ordinal && + (instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutVideo + } == true + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt new file mode 100644 index 000000000..8bef7a928 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt @@ -0,0 +1,57 @@ +package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.patch + +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.fingerprint.Fingerprint +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult +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.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility +import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutCircleFingerprint +import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutIconFingerprint +import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutVideoFingerprint +import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch +import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch +import org.jf.dexlib2.iface.instruction.formats.Instruction21c + +@Patch +@DependsOn([IntegrationsPatch::class, HideEndscreenCardsResourcePatch::class]) +@Name("hide-endscreen-cards") +@Description("Hides the suggested video cards at the end of a video in fullscreen.") +@HideEndscreenCardsCompatibility +@Version("0.0.1") +class HideEndscreenCardsPatch : BytecodePatch( + listOf( + LayoutCircleFingerprint, + LayoutIconFingerprint, + LayoutVideoFingerprint, + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + fun MethodFingerprint.injectHideCall() { + val layoutResult = result!! + val layoutMethod = layoutResult.mutableMethod + + val checkCastIndex = layoutResult.scanResult.patternScanResult!!.endIndex + val viewRegister = (layoutMethod.instruction(checkCastIndex) as Instruction21c).registerA + + layoutMethod.addInstruction( + checkCastIndex + 1, + "invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V" + ) + } + + listOf(LayoutCircleFingerprint, LayoutIconFingerprint, LayoutVideoFingerprint).forEach(MethodFingerprint::injectHideCall) + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt new file mode 100644 index 000000000..c5404d3d4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt @@ -0,0 +1,48 @@ +package app.revanced.patches.youtube.layout.hideendscreencards.resource.patch + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.ResourcePatch +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility +import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch +import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch +import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource +import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference + +@Name("hide-endscreen-cards-resource-patch") +@HideEndscreenCardsCompatibility +@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) +@Version("0.0.1") +class HideEndscreenCardsResourcePatch : ResourcePatch { + internal companion object { + var layoutCircle: Long = -1 + var layoutIcon: Long = -1 + var layoutVideo: Long = -1 + } + + override fun execute(context: ResourceContext): PatchResult { + SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( + SwitchPreference( + "revanced_hide_endscreen_cards", + StringResource("revanced_hide_endscreen_cards_title", "Hide end-screen cards"), + true, + StringResource("revanced_hide_endscreen_cards_summary_on", "End-screen cards are hidden"), + StringResource("revanced_hide_endscreen_cards_summary_off", "End-screen cards are shown") + ), + ) + + fun findEndscreenResourceId(name: String) = ResourceMappingResourcePatch.resourceMappings.single { + it.type == "layout" && it.name == "endscreen_element_layout_$name" + }.id + + layoutCircle = findEndscreenResourceId("circle") + layoutIcon = findEndscreenResourceId("icon") + layoutVideo = findEndscreenResourceId("video") + + return PatchResultSuccess() + } +} \ No newline at end of file