fix(Reddit - Remove subreddit dialog): New type of NSFW dialog not hidden https://github.com/inotia00/ReVanced_Extended/issues/2895

This commit is contained in:
inotia00 2025-03-31 21:01:10 +09:00
parent 7f85e802c2
commit b439ef3ee7
3 changed files with 117 additions and 20 deletions

View File

@ -2,7 +2,10 @@ package app.revanced.extension.reddit.patches;
import static app.revanced.extension.shared.utils.StringRef.str; import static app.revanced.extension.shared.utils.StringRef.str;
import android.app.Dialog;
import android.view.View; import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -30,8 +33,33 @@ public class RemoveSubRedditDialogPatch {
clickViewDelayed(cancelButtonView); clickViewDelayed(cancelButtonView);
} }
public static boolean spoofHasBeenVisitedStatus(boolean hasBeenVisited) { public static void dismissNSFWDialog(Object customDialog) {
return Settings.REMOVE_NSFW_DIALOG.get() || hasBeenVisited; if (Settings.REMOVE_NSFW_DIALOG.get() &&
customDialog instanceof Dialog dialog) {
Window window = dialog.getWindow();
if (window != null) {
WindowManager.LayoutParams params = window.getAttributes();
params.height = 0;
params.width = 0;
// Change the size of dialog to 0.
window.setAttributes(params);
// Disable dialog's background dim.
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
// Hide DecorView.
View decorView = window.getDecorView();
decorView.setVisibility(View.GONE);
// Dismiss dialog.
dialog.dismiss();
}
}
}
public static boolean removeNSFWDialog() {
return Settings.REMOVE_NSFW_DIALOG.get();
} }
public static boolean spoofLoggedInStatus(boolean isLoggedIn) { public static boolean spoofLoggedInStatus(boolean isLoggedIn) {

View File

@ -1,5 +1,6 @@
package app.revanced.patches.reddit.layout.subredditdialog package app.revanced.patches.reddit.layout.subredditdialog
import app.revanced.patches.reddit.utils.resourceid.nsfwDialogTitle
import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
@ -9,6 +10,7 @@ import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
internal val frequentUpdatesSheetScreenFingerprint = legacyFingerprint( internal val frequentUpdatesSheetScreenFingerprint = legacyFingerprint(
name = "frequentUpdatesSheetScreenFingerprint", name = "frequentUpdatesSheetScreenFingerprint",
@ -52,6 +54,13 @@ fun listOfIsLoggedInInstruction(method: Method) =
?.reversed() ?.reversed()
?: emptyList() ?: emptyList()
fun indexOfGetOverInstruction(method: Method) =
method.indexOfFirstInstruction {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_VIRTUAL &&
reference?.name == "getOver18"
}
internal val nsfwAlertEmitFingerprint = legacyFingerprint( internal val nsfwAlertEmitFingerprint = legacyFingerprint(
name = "nsfwAlertEmitFingerprint", name = "nsfwAlertEmitFingerprint",
returnType = "Ljava/lang/Object;", returnType = "Ljava/lang/Object;",
@ -59,17 +68,32 @@ internal val nsfwAlertEmitFingerprint = legacyFingerprint(
strings = listOf("reddit://reddit/r/", "nsfwAlertDelegate"), strings = listOf("reddit://reddit/r/", "nsfwAlertDelegate"),
customFingerprint = { method, _ -> customFingerprint = { method, _ ->
method.name == "emit" && method.name == "emit" &&
indexOfHasBeenVisitedInstruction(method) >= 0 indexOfGetOverInstruction(method) >= 0
} }
) )
fun indexOfHasBeenVisitedInstruction(method: Method) = internal val nsfwAlertObserverFingerprint = legacyFingerprint(
method.indexOfFirstInstruction { name = "nsfwAlertObserverFingerprint",
val reference = getReference<MethodReference>() returnType = "Ljava/lang/Object;",
opcode == Opcode.INVOKE_VIRTUAL && accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
reference?.name == "getHasBeenVisited" && strings = listOf("nsfwAlertDelegate"),
reference.returnType == "Z" customFingerprint = { method, _ ->
method.name == "invokeSuspend" &&
indexOfGetOverInstruction(method) >= 0 &&
method.indexOfFirstInstruction {
opcode == Opcode.NEW_INSTANCE &&
getReference<TypeReference>()?.type?.startsWith("Lcom/reddit/frontpage/presentation/detail/DetailHolderPresenter\$showDialogIfNeverVisitedOrSubscribed\$") == true
} >= 0
} }
)
internal val nsfwAlertBuilderFingerprint = legacyFingerprint(
name = "nsfwAlertBuilderFingerprint",
literals = listOf(nsfwDialogTitle),
customFingerprint = { method, _ ->
method.definingClass.startsWith("Lcom/reddit/screen/nsfw")
}
)
internal val redditAlertDialogsFingerprint = legacyFingerprint( internal val redditAlertDialogsFingerprint = legacyFingerprint(
name = "redditAlertDialogsFingerprint", name = "redditAlertDialogsFingerprint",

View File

@ -2,19 +2,26 @@ package app.revanced.patches.reddit.layout.subredditdialog
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE 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.extension.Constants.PATCHES_PATH
import app.revanced.patches.reddit.utils.patch.PatchList.REMOVE_SUBREDDIT_DIALOG import app.revanced.patches.reddit.utils.patch.PatchList.REMOVE_SUBREDDIT_DIALOG
import app.revanced.patches.reddit.utils.resourceid.sharedResourceIdPatch
import app.revanced.patches.reddit.utils.settings.is_2024_41_or_greater import app.revanced.patches.reddit.utils.settings.is_2024_41_or_greater
import app.revanced.patches.reddit.utils.settings.is_2025_01_or_greater import app.revanced.patches.reddit.utils.settings.is_2025_01_or_greater
import app.revanced.patches.reddit.utils.settings.is_2025_05_or_greater import app.revanced.patches.reddit.utils.settings.is_2025_05_or_greater
import app.revanced.patches.reddit.utils.settings.is_2025_06_or_greater 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.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.findFreeRegister
import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.fingerprint.mutableClassOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@ -32,7 +39,10 @@ val subRedditDialogPatch = bytecodePatch(
) { ) {
compatibleWith(COMPATIBLE_PACKAGE) compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(settingsPatch) dependsOn(
settingsPatch,
sharedResourceIdPatch,
)
execute { execute {
@ -70,17 +80,52 @@ val subRedditDialogPatch = bytecodePatch(
} }
if (is_2025_01_or_greater) { if (is_2025_01_or_greater) {
nsfwAlertEmitFingerprint.methodOrThrow().apply { arrayOf(
val hasBeenVisitedIndex = indexOfHasBeenVisitedInstruction(this) nsfwAlertEmitFingerprint,
val hasBeenVisitedRegister = nsfwAlertObserverFingerprint
getInstruction<OneRegisterInstruction>(hasBeenVisitedIndex + 1).registerA ).forEach { fingerprint ->
fingerprint.methodOrThrow().apply {
val getOverIndex = indexOfGetOverInstruction(this)
val getOverRegister = getInstruction<FiveRegisterInstruction>(getOverIndex).registerC
val freeRegister = findFreeRegister(getOverIndex, getOverRegister)
addInstructions( val returnIndex = indexOfFirstInstructionOrThrow(getOverIndex, Opcode.RETURN_OBJECT)
hasBeenVisitedIndex + 2, """ val jumpIndex = indexOfFirstInstructionReversedOrThrow(returnIndex, Opcode.SGET_OBJECT)
invoke-static {v$hasBeenVisitedRegister}, $EXTENSION_CLASS_DESCRIPTOR->spoofHasBeenVisitedStatus(Z)Z
move-result v$hasBeenVisitedRegister addInstructionsWithLabels(
""" getOverIndex, """
) invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->removeNSFWDialog()Z
move-result v$freeRegister
if-nez v$freeRegister, :jump
""", ExternalLabel("jump", getInstruction(jumpIndex))
)
}
}
var hookCount = 0
nsfwAlertBuilderFingerprint.mutableClassOrThrow().let {
it.methods.forEach { method ->
method.apply {
val showIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "show"
}
if (showIndex >= 0) {
val dialogRegister = getInstruction<OneRegisterInstruction>(showIndex + 1).registerA
addInstruction(
showIndex + 2,
"invoke-static {v$dialogRegister}, $EXTENSION_CLASS_DESCRIPTOR->dismissNSFWDialog(Ljava/lang/Object;)V"
)
hookCount++
}
}
}
}
if (hookCount == 0) {
throw PatchException("Failed to find hook method")
} }
} }