diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt new file mode 100644 index 000000000..20072b127 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.autoplaybutton.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.25.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class AutoplayButtonCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutonavInformerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutonavInformerFingerprint.kt new file mode 100644 index 000000000..4ef4a6b8a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutonavInformerFingerprint.kt @@ -0,0 +1,38 @@ +package app.revanced.patches.youtube.layout.autoplaybutton.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("autonav-informer-fingerprint") +@MatchingMethod( + "com/google/android/libraries/youtube/player/features/prefetch/WillAutonavInformer;", "k" +) +@FuzzyPatternScanMethod(2) +@AutoplayButtonCompatibility +@Version("0.0.1") +object AutonavInformerFingerprint : MethodFingerprint( + "Z", + AccessFlags.PUBLIC or AccessFlags.FINAL, + null, + listOf( + Opcode.IGET_BOOLEAN, + Opcode.IF_EQZ, + Opcode.IGET_BOOLEAN, + Opcode.RETURN, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + ), + null, + { it.definingClass.endsWith("WillAutonavInformer;") } +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt new file mode 100644 index 000000000..d584709cf --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt @@ -0,0 +1,32 @@ +package app.revanced.patches.youtube.layout.autoplaybutton.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("layout-constructor-fingerprint") +@MatchingMethod( + "Lcom/google/android/apps/youtube/app/player/overlay/YouTubeControlsOverlay;", "F" +) +@FuzzyPatternScanMethod(2) +@AutoplayButtonCompatibility +@Version("0.0.1") +object LayoutConstructorFingerprint : MethodFingerprint( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + null, + listOf( + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.INVOKE_VIRTUAL, + ), + listOf("1.0x") +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/AutoplayButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/AutoplayButtonRemoverPatch.kt new file mode 100644 index 000000000..403233314 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/AutoplayButtonRemoverPatch.kt @@ -0,0 +1,61 @@ +package app.revanced.patches.youtube.layout.autoplaybutton.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.impl.BytecodeData +import app.revanced.patcher.extensions.removeInstructions +import app.revanced.patcher.extensions.replaceInstructions +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.Dependencies +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.impl.BytecodePatch +import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility +import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutonavInformerFingerprint +import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint +import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +@Patch +@Dependencies(dependencies = [ResourceIdMappingProviderResourcePatch::class]) +@Name("disable-autoplay-button") +@Description("Disable the autoplay button.") +@AutoplayButtonCompatibility +@Version("0.0.1") +class AutoplayButtonRemoverPatch : BytecodePatch( + listOf( + LayoutConstructorFingerprint, AutonavInformerFingerprint + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val layoutGenMethod = LayoutConstructorFingerprint.result!!.mutableMethod + + val autonavToggle = + ResourceIdMappingProviderResourcePatch.resourceMappings.first { it.type == "id" && it.name == "autonav_toggle" } + val autonavPreviewStub = + ResourceIdMappingProviderResourcePatch.resourceMappings.first { it.type == "id" && it.name == "autonav_preview_stub" } + + val autonavToggleConstIndex = + layoutGenMethod.implementation!!.instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavToggle.id } + val autonavPreviewStubConstIndex = + layoutGenMethod.implementation!!.instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavPreviewStub.id } + + //remove adding autoplay button to the layout + layoutGenMethod.removeInstructions(autonavToggleConstIndex, 5) + layoutGenMethod.removeInstructions(autonavPreviewStubConstIndex, 5) + + val autonavInformerMethod = AutonavInformerFingerprint.result!!.mutableMethod + + //force disable autoplay since it's hard to do without the button + autonavInformerMethod.replaceInstructions( + 0, + """ + const/4 v0, 0x0 + return v0 + """ + ) + + return PatchResultSuccess() + } +}