@@ -2,22 +2,26 @@ package app.revanced.patches.reddit.layout.screenshotpopup
2
2
3
3
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
4
4
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
5
+ import app.revanced.patcher.patch.PatchException
5
6
import app.revanced.patcher.patch.bytecodePatch
7
+ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
6
8
import app.revanced.patcher.util.smali.ExternalLabel
7
9
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE
8
10
import app.revanced.patches.reddit.utils.extension.Constants.PATCHES_PATH
9
11
import app.revanced.patches.reddit.utils.patch.PatchList.DISABLE_SCREENSHOT_POPUP
10
- import app.revanced.patches.reddit.utils.resourceid.screenShotShareBanner
11
- import app.revanced.patches.reddit.utils.resourceid.sharedResourceIdPatch
12
- import app.revanced.patches.reddit.utils.settings.is_2025_06_or_greater
13
12
import app.revanced.patches.reddit.utils.settings.settingsPatch
14
13
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
14
+ import app.revanced.util.findMutableMethodOf
15
+ import app.revanced.util.fingerprint.methodCall
15
16
import app.revanced.util.fingerprint.methodOrThrow
17
+ import app.revanced.util.getReference
18
+ import app.revanced.util.indexOfFirstInstruction
16
19
import app.revanced.util.indexOfFirstInstructionOrThrow
17
- import app.revanced.util.indexOfFirstInstructionReversedOrThrow
18
- import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
20
+ import app.revanced.util.indexOfFirstStringInstruction
19
21
import com.android.tools.smali.dexlib2.Opcode
22
+ import com.android.tools.smali.dexlib2.iface.Method
20
23
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
24
+ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
21
25
22
26
private const val EXTENSION_METHOD_DESCRIPTOR =
23
27
" $PATCHES_PATH /ScreenshotPopupPatch;->disableScreenshotPopup()Z"
@@ -29,41 +33,80 @@ val screenshotPopupPatch = bytecodePatch(
29
33
) {
30
34
compatibleWith(COMPATIBLE_PACKAGE )
31
35
32
- dependsOn(
33
- settingsPatch,
34
- sharedResourceIdPatch,
35
- )
36
+ dependsOn(settingsPatch)
36
37
37
38
execute {
38
39
39
- if (is_2025_06_or_greater) {
40
- screenshotTakenBannerFingerprint.methodOrThrow().apply {
41
- val literalIndex = indexOfFirstLiteralInstructionOrThrow(screenShotShareBanner)
42
- val insertIndex = indexOfFirstInstructionReversedOrThrow(literalIndex, Opcode .CONST_4 )
43
- val insertRegister = getInstruction<OneRegisterInstruction >(insertIndex).registerA
44
- val jumpIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode .SGET_OBJECT )
40
+ val screenshotTriggerSharingListenerMethodCall =
41
+ screenshotBannerContainerFingerprint.methodCall()
45
42
46
- addInstructionsWithLabels(
47
- insertIndex, """
48
- invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR
49
- move-result v$insertRegister
50
- if-nez v$insertRegister , :hidden
51
- """ , ExternalLabel (" hidden" , getInstruction(jumpIndex))
52
- )
43
+ fun indexOfScreenshotTriggerInstruction (method : Method ) =
44
+ method.indexOfFirstInstruction {
45
+ getReference<MethodReference >()?.toString() == screenshotTriggerSharingListenerMethodCall
53
46
}
54
- } else {
55
- screenshotTakenBannerLegacyFingerprint.methodOrThrow().apply {
47
+
48
+ val isScreenshotTriggerMethod: Method .() -> Boolean = {
49
+ indexOfScreenshotTriggerInstruction(this ) >= 0
50
+ }
51
+
52
+ var hookCount = 0
53
+
54
+ fun MutableMethod.hook () {
55
+ if (returnType == " V" ) {
56
56
addInstructionsWithLabels(
57
57
0 , """
58
58
invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR
59
59
move-result v0
60
- if-eqz v0, :dismiss
60
+ if-eqz v0, :shown
61
61
return-void
62
- """ , ExternalLabel (" dismiss " , getInstruction(0 ))
62
+ """ , ExternalLabel (" shown " , getInstruction(0 ))
63
63
)
64
+
65
+ hookCount++
66
+ } else if (returnType.startsWith(" L" )) { // Reddit 2025.06+
67
+ val insertIndex =
68
+ indexOfFirstStringInstruction(" screenshotTriggerSharingListener" )
69
+
70
+ if (insertIndex >= 0 ) {
71
+ val insertRegister =
72
+ getInstruction<OneRegisterInstruction >(insertIndex).registerA
73
+ val triggerIndex =
74
+ indexOfScreenshotTriggerInstruction(this )
75
+ val jumpIndex =
76
+ indexOfFirstInstructionOrThrow(triggerIndex, Opcode .RETURN_OBJECT )
77
+
78
+ addInstructionsWithLabels(
79
+ insertIndex, """
80
+ invoke-static {}, $EXTENSION_METHOD_DESCRIPTOR
81
+ move-result v$insertRegister
82
+ if-nez v$insertRegister , :hidden
83
+ """ , ExternalLabel (" hidden" , getInstruction(jumpIndex))
84
+ )
85
+
86
+ hookCount++
87
+ }
88
+ }
89
+ }
90
+
91
+ screenshotBannerContainerFingerprint
92
+ .methodOrThrow()
93
+ .hook()
94
+
95
+ classes.forEach { classDef ->
96
+ classDef.methods.forEach { method ->
97
+ if (method.isScreenshotTriggerMethod()) {
98
+ proxy(classDef)
99
+ .mutableClass
100
+ .findMutableMethodOf(method)
101
+ .hook()
102
+ }
64
103
}
65
104
}
66
105
106
+ if (hookCount == 0 ) {
107
+ throw PatchException (" Failed to find hook method" )
108
+ }
109
+
67
110
updatePatchStatus(
68
111
" enableScreenshotPopup" ,
69
112
DISABLE_SCREENSHOT_POPUP
0 commit comments