diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt index 219e02a7..4fc21177 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt @@ -17,6 +17,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility import app.revanced.patches.youtube.ad.general.bytecode.fingerprints.ReelConstructorFingerprint import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch +import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch import app.revanced.patches.youtube.misc.fix.verticalscroll.patch.VerticalScrollPatch import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction import org.jf.dexlib2.iface.instruction.formats.Instruction31i @@ -24,7 +25,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c @Patch -@DependsOn([GeneralAdsResourcePatch::class, VerticalScrollPatch::class]) +@DependsOn([GeneralAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class]) @Name("general-ads") @Description("Removes general ads.") @GeneralAdsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt new file mode 100644 index 00000000..5e17690b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.49.37") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class FixBackToExitGestureCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt new file mode 100644 index 00000000..010fd65c --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object OnBackPressedFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.RETURN_VOID + ), + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("WatchWhileActivity;") + && methodDef.name == "onBackPressed" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewScrollingFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewScrollingFingerprint.kt new file mode 100644 index 00000000..7307d9ab --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewScrollingFingerprint.kt @@ -0,0 +1,19 @@ +package app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object RecyclerViewScrollingFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.CHECK_CAST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_LEZ, + Opcode.IGET_OBJECT, + Opcode.CONST_4, + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingFingerprint.kt new file mode 100644 index 00000000..99443654 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingFingerprint.kt @@ -0,0 +1,27 @@ +package app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object RecyclerViewTopScrollingFingerprint : MethodFingerprint( + "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( + Opcode.IGET_OBJECT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.GOTO, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt new file mode 100644 index 00000000..09964ba5 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt @@ -0,0 +1,20 @@ +package app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object RecyclerViewTopScrollingParentFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.CONST_16, + Opcode.INVOKE_VIRTUAL, + Opcode.NEW_INSTANCE + ), + customFingerprint = { methodDef -> + methodDef.name == "" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/patch/FixBackToExitGesturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/patch/FixBackToExitGesturePatch.kt new file mode 100644 index 00000000..a24b5db1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/patch/FixBackToExitGesturePatch.kt @@ -0,0 +1,86 @@ +package app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultError +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation.FixBackToExitGestureCompatibility +import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.OnBackPressedFingerprint +import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewScrollingFingerprint +import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewTopScrollingFingerprint +import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewTopScrollingParentFingerprint + +@Description("Fixes the swipe back to exit gesture.") +@FixBackToExitGestureCompatibility +@Version("0.0.1") +class FixBackToExitGesturePatch : BytecodePatch( + listOf( + RecyclerViewTopScrollingParentFingerprint, + RecyclerViewScrollingFingerprint, + OnBackPressedFingerprint, + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + RecyclerViewTopScrollingFingerprint.apply { + resolve( + context, + RecyclerViewTopScrollingParentFingerprint.result?.classDef + ?: return RecyclerViewTopScrollingParentFingerprint.toErrorResult() + ) + } + + mapOf( + RecyclerViewTopScrollingFingerprint to IntegrationsMethod( + methodName = "onTopView" + ), + RecyclerViewScrollingFingerprint to IntegrationsMethod( + methodName = "onScrollingViews" + ), + OnBackPressedFingerprint to IntegrationsMethod( + "p0", "onBackPressed", "Lcom/google/android/apps/youtube/app/watchwhile/WatchWhileActivity;" + ) + ).forEach { (fingerprint, target) -> + try { + fingerprint.injectCall(target) + } catch (error: PatchResultError) { + return error + } + } + + return PatchResultSuccess() + } + + private companion object { + /** + * A reference to a method from the integrations for [FixBackToExitGesturePatch]. + * + * @param register The method registers. + * @param methodName The method name. + * @param parameterTypes The parameters of the method. + */ + data class IntegrationsMethod( + val register: String = "", val methodName: String, val parameterTypes: String = "" + ) { + override fun toString() = + "invoke-static {$register}, Lapp/revanced/integrations/patches/FixBackToExitGesturePatch;->$methodName($parameterTypes)V" + } + + /** + * Inject a call to a method from the integrations. + * + * @param targetMethod The target method to call. + */ + fun MethodFingerprint.injectCall(targetMethod: IntegrationsMethod) = result?.apply { + mutableMethod.addInstruction( + scanResult.patternScanResult!!.endIndex, targetMethod.toString() + ) + } ?: throw this.toErrorResult() + } +} \ No newline at end of file