From bb5964ce9800bb9b6444e212efbe8cf86b902eb4 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Tue, 1 Apr 2025 18:51:58 +0900 Subject: [PATCH] fix(Reddit - Disable screenshot popup): Screenshot popup not being completely removed https://github.com/inotia00/ReVanced_Extended/issues/1810 --- .../reddit/patches/ScreenshotPopupPatch.java | 4 +- .../layout/screenshotpopup/Fingerprints.kt | 60 ------- .../screenshotpopup/ScreenshotPopupPatch.kt | 154 +++++------------- .../utils/resourceid/SharedResourceIdPatch.kt | 6 - 4 files changed, 42 insertions(+), 182 deletions(-) delete mode 100644 patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/Fingerprints.kt diff --git a/extensions/shared/src/main/java/app/revanced/extension/reddit/patches/ScreenshotPopupPatch.java b/extensions/shared/src/main/java/app/revanced/extension/reddit/patches/ScreenshotPopupPatch.java index 7216ea55c..9c84cdbec 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/reddit/patches/ScreenshotPopupPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/reddit/patches/ScreenshotPopupPatch.java @@ -5,7 +5,7 @@ import app.revanced.extension.reddit.settings.Settings; @SuppressWarnings("unused") public class ScreenshotPopupPatch { - public static boolean disableScreenshotPopup() { - return Settings.DISABLE_SCREENSHOT_POPUP.get(); + public static Boolean disableScreenshotPopup(Boolean original) { + return Settings.DISABLE_SCREENSHOT_POPUP.get() ? Boolean.FALSE : original; } } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/Fingerprints.kt deleted file mode 100644 index 42d350793..000000000 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/Fingerprints.kt +++ /dev/null @@ -1,60 +0,0 @@ -package app.revanced.patches.reddit.layout.screenshotpopup - -import app.revanced.patches.reddit.utils.resourceid.actionShare -import app.revanced.patches.reddit.utils.resourceid.screenShotShareBanner -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.fingerprint.legacyFingerprint -import app.revanced.util.or -import com.android.tools.smali.dexlib2.AccessFlags - -internal val screenshotBannerContainerFingerprint = legacyFingerprint( - name = "screenshotTakenBannerFingerprint", - returnType = "V", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - strings = listOf( - "bannerContainer", - "scope", - ) -) - -/** - * Reddit 2025.06.0 ~ - */ -internal val screenshotTakenBannerComposableFingerprint = legacyFingerprint( - name = "screenshotTakenBannerComposableFingerprint", - returnType = "L", - customFingerprint = { method, classDef -> - method.containsLiteralInstruction(actionShare) && - method.containsLiteralInstruction(screenShotShareBanner) && - classDef.type.startsWith("Lcom/reddit/sharing/screenshot/composables/") && - method.name == "invoke" - } -) - -/** - * ~ Reddit 2025.05.1 - */ -internal val screenshotTakenBannerLambdaActionFingerprint = legacyFingerprint( - name = "screenshotTakenBannerLambdaFingerprint", - returnType = "V", - parameters = listOf("Landroidx/compose/runtime/", "I"), - customFingerprint = { method, _ -> - method.containsLiteralInstruction(actionShare) && - method.name == "invoke" - } -) - -/** - * ~ Reddit 2025.05.1 - */ -internal val screenshotTakenBannerLambdaBannerFingerprint = legacyFingerprint( - name = "screenshotTakenBannerLambdaFingerprint", - returnType = "V", - parameters = listOf("Landroidx/compose/runtime/", "I"), - customFingerprint = { method, _ -> - method.containsLiteralInstruction(screenShotShareBanner) && - method.name == "invoke" - } -) - - diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/ScreenshotPopupPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/ScreenshotPopupPatch.kt index 3b43169b2..4c4653142 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/ScreenshotPopupPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/ScreenshotPopupPatch.kt @@ -1,37 +1,22 @@ package app.revanced.patches.reddit.layout.screenshotpopup -import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.reddit.utils.extension.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.patch.PatchList.DISABLE_SCREENSHOT_POPUP -import app.revanced.patches.reddit.utils.resourceid.actionShare -import app.revanced.patches.reddit.utils.resourceid.screenShotShareBanner -import app.revanced.patches.reddit.utils.resourceid.sharedResourceIdPatch -import app.revanced.patches.reddit.utils.settings.is_2025_06_or_greater import app.revanced.patches.reddit.utils.settings.settingsPatch import app.revanced.patches.reddit.utils.settings.updatePatchStatus import app.revanced.util.findMutableMethodOf -import app.revanced.util.fingerprint.methodCall -import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow -import app.revanced.util.indexOfFirstLiteralInstructionOrThrow -import app.revanced.util.indexOfFirstStringInstruction import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference -private const val EXTENSION_METHOD_DESCRIPTOR = - "$PATCHES_PATH/ScreenshotPopupPatch;->disableScreenshotPopup()Z" - @Suppress("unused") val screenshotPopupPatch = bytecodePatch( DISABLE_SCREENSHOT_POPUP.title, @@ -39,121 +24,62 @@ val screenshotPopupPatch = bytecodePatch( ) { compatibleWith(COMPATIBLE_PACKAGE) - dependsOn( - settingsPatch, - sharedResourceIdPatch, - ) + dependsOn(settingsPatch) execute { - val screenshotTriggerSharingListenerMethodCall = - screenshotBannerContainerFingerprint.methodCall() - - fun indexOfScreenshotTriggerInstruction(method: Method) = + fun indexOfShowBannerInstruction(method: Method) = method.indexOfFirstInstruction { - getReference()?.toString() == screenshotTriggerSharingListenerMethodCall + val reference = getReference() + opcode == Opcode.IGET_OBJECT && + reference?.name?.contains("shouldShowBanner") == true && + reference.definingClass.startsWith("Lcom/reddit/sharing/screenshot/") == true } - val isScreenshotTriggerMethod: Method.() -> Boolean = { - indexOfScreenshotTriggerInstruction(this) >= 0 - } - - var hookCount = 0 - - fun MutableMethod.hook() { - if (returnType == "V") { - addInstructionsWithLabels( - 0, """ - invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR - move-result v0 - if-eqz v0, :shown - return-void - """, ExternalLabel("shown", getInstruction(0)) - ) - - hookCount++ - } else if (returnType.startsWith("L")) { // Reddit 2025.06+ - val insertIndex = - indexOfFirstStringInstruction("screenshotTriggerSharingListener") - - if (insertIndex >= 0) { - val insertRegister = - getInstruction(insertIndex).registerA - val triggerIndex = - indexOfScreenshotTriggerInstruction(this) - val jumpIndex = - indexOfFirstInstructionOrThrow(triggerIndex, Opcode.RETURN_OBJECT) - - addInstructionsWithLabels( - insertIndex, """ - invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR - move-result v$insertRegister - if-nez v$insertRegister, :hidden - """, ExternalLabel("hidden", getInstruction(jumpIndex)) - ) - - hookCount++ - } + fun indexOfSetValueInstruction(method: Method) = + method.indexOfFirstInstruction { + getReference()?.name == "setValue" } - } - screenshotBannerContainerFingerprint - .methodOrThrow() - .hook() + fun indexOfBooleanInstruction(method: Method, startIndex: Int = 0) = + method.indexOfFirstInstruction(startIndex) { + val reference = getReference() + opcode == Opcode.SGET_OBJECT && + reference?.definingClass == "Ljava/lang/Boolean;" && + reference.type == "Ljava/lang/Boolean;" + } + + val isScreenShotMethod: Method.() -> Boolean = { + definingClass.startsWith("Lcom/reddit/sharing/screenshot/") && + name == "invokeSuspend" && + indexOfShowBannerInstruction(this) >= 0 && + indexOfBooleanInstruction(this) >= 0 && + indexOfSetValueInstruction(this) >= 0 + } classes.forEach { classDef -> classDef.methods.forEach { method -> - if (method.isScreenshotTriggerMethod()) { + if (method.isScreenShotMethod()) { proxy(classDef) .mutableClass .findMutableMethodOf(method) - .hook() + .apply { + val showBannerIndex = indexOfShowBannerInstruction(this) + val booleanIndex = indexOfBooleanInstruction(this, showBannerIndex) + val booleanRegister = + getInstruction(booleanIndex).registerA + + addInstructions( + booleanIndex + 1, """ + invoke-static {v$booleanRegister}, $PATCHES_PATH/ScreenshotPopupPatch;->disableScreenshotPopup(Ljava/lang/Boolean;)Ljava/lang/Boolean; + move-result-object v$booleanRegister + """ + ) + } } } } - if (hookCount == 0) { - throw PatchException("Failed to find hook method") - } - - if (is_2025_06_or_greater) { - screenshotTakenBannerComposableFingerprint.methodOrThrow().apply { - arrayOf( - actionShare, - screenShotShareBanner - ).forEach { literal -> - val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal) - val insertIndex = indexOfFirstInstructionReversedOrThrow(literalIndex, Opcode.CONST_4) - val insertRegister = getInstruction(insertIndex).registerA - val jumpIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.SGET_OBJECT) - - addInstructionsWithLabels( - insertIndex, """ - invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR - move-result v$insertRegister - if-nez v$insertRegister, :hidden - """, ExternalLabel("hidden", getInstruction(jumpIndex)) - ) - } - } - } else { - arrayOf( - screenshotTakenBannerLambdaActionFingerprint, - screenshotTakenBannerLambdaBannerFingerprint - ).forEach { fingerprint -> - fingerprint.methodOrThrow().addInstructionsWithLabels( - 0, """ - invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR - move-result v0 - if-eqz v0, :ignore - return-void - :ignore - nop - """ - ) - } - } - updatePatchStatus( "enableScreenshotPopup", DISABLE_SCREENSHOT_POPUP diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/utils/resourceid/SharedResourceIdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/utils/resourceid/SharedResourceIdPatch.kt index cb0ec3341..532b4326c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/utils/resourceid/SharedResourceIdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/utils/resourceid/SharedResourceIdPatch.kt @@ -5,12 +5,8 @@ import app.revanced.patches.shared.mapping.ResourceType.STRING import app.revanced.patches.shared.mapping.getResourceId import app.revanced.patches.shared.mapping.resourceMappingPatch -var actionShare = -1L - private set var nsfwDialogTitle = -1L private set -var screenShotShareBanner = -1L - private set internal val sharedResourceIdPatch = resourcePatch( description = "sharedResourceIdPatch" @@ -18,8 +14,6 @@ internal val sharedResourceIdPatch = resourcePatch( dependsOn(resourceMappingPatch) execute { - actionShare = getResourceId(STRING, "action_share") nsfwDialogTitle = getResourceId(STRING, "nsfw_dialog_title") - screenShotShareBanner = getResourceId(STRING, "screenshot_share_banner_title") } } \ No newline at end of file