feat(Reddit): Remove version constraint

This commit is contained in:
inotia00 2024-12-21 11:34:59 +09:00
parent 370d85adad
commit 7f72395c36
24 changed files with 354 additions and 200 deletions

View File

@ -17,6 +17,7 @@ import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstStringInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@ -113,9 +114,10 @@ val adsPatch = bytecodePatch(
// AdElementConverter is conveniently responsible for inserting all feed ads.
// By removing the appending instruction no ad posts gets appended to the feed.
newAdPostFingerprint.methodOrThrow().apply {
val targetIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z"
val stringIndex = indexOfFirstStringInstructionOrThrow("android_feed_freeform_render_variant")
val targetIndex = indexOfFirstInstructionOrThrow(stringIndex) {
opcode == Opcode.INVOKE_VIRTUAL
&& getReference<MethodReference>()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z"
}
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)

View File

@ -1,9 +1,12 @@
package app.revanced.patches.reddit.ad
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val commentAdsFingerprint = legacyFingerprint(
name = "commentAdsFingerprint",
@ -35,9 +38,7 @@ internal val adPostFingerprint = legacyFingerprint(
"uxExperiences"
),
customFingerprint = { method, classDef ->
method.definingClass.endsWith("/Listing;") &&
method.name == "<init>" &&
classDef.sourceFile == "Listing.kt"
classDef.type.endsWith("/Listing;")
},
)
@ -45,10 +46,14 @@ internal val newAdPostFingerprint = legacyFingerprint(
name = "newAdPostFingerprint",
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(Opcode.INVOKE_VIRTUAL),
strings = listOf(
"chain",
"feedElement"
"feedElement",
"android_feed_freeform_render_variant",
),
customFingerprint = { _, classDef -> classDef.sourceFile == "AdElementConverter.kt" },
customFingerprint = { method, _ ->
method.indexOfFirstInstruction {
getReference<MethodReference>()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z"
} >= 0
},
)

View File

@ -8,7 +8,17 @@ internal val communityRecommendationSectionFingerprint = legacyFingerprint(
name = "communityRecommendationSectionFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf("feedContext"),
)
internal val communityRecommendationSectionParentFingerprint = legacyFingerprint(
name = "communityRecommendationSectionParentFingerprint",
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf("community_recomendation_section_"),
customFingerprint = { method, _ ->
method.definingClass.endsWith("/CommunityRecommendationSection;")
method.definingClass.startsWith("Lcom/reddit/onboardingfeedscomponents/communityrecommendation/impl/") &&
method.name == "key"
}
)

View File

@ -24,7 +24,7 @@ val recommendedCommunitiesPatch = bytecodePatch(
dependsOn(settingsPatch)
execute {
communityRecommendationSectionFingerprint.methodOrThrow().apply {
communityRecommendationSectionFingerprint.methodOrThrow(communityRecommendationSectionParentFingerprint).apply {
addInstructionsWithLabels(
0,
"""

View File

@ -1,12 +1,55 @@
package app.revanced.patches.reddit.layout.navigation
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val bottomNavScreenFingerprint = legacyFingerprint(
name = "bottomNavScreenFingerprint",
returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { method, _ ->
method.definingClass == "Lcom/reddit/launch/bottomnav/BottomNavScreen;" &&
indexOfGetDimensionPixelSizeInstruction(method) >= 0
}
)
fun indexOfGetDimensionPixelSizeInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.toString() == "Landroid/content/res/Resources;->getDimensionPixelSize(I)I"
}
internal val bottomNavScreenHandlerFingerprint = legacyFingerprint(
name = "bottomNavScreenHandlerFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L", "L", "Z", "Landroid/view/ViewGroup;", "L"),
customFingerprint = { method, _ ->
indexOfGetItemsInstruction(method) >= 0 &&
indexOfSetSelectedItemTypeInstruction(method) >= 0
}
)
fun indexOfGetItemsInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "getItems"
}
fun indexOfSetSelectedItemTypeInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "setSelectedItemType"
}
internal val bottomNavScreenOnGlobalLayoutFingerprint = legacyFingerprint(
name = "bottomNavScreenOnGlobalLayoutFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
@ -14,8 +57,7 @@ internal val bottomNavScreenFingerprint = legacyFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
),
customFingerprint = { method, classDef ->
method.name == "onGlobalLayout" &&
classDef.type.startsWith("Lcom/reddit/launch/bottomnav/BottomNavScreen\$")
customFingerprint = { methodDef, _ ->
methodDef.name == "onGlobalLayout"
}
)

View File

@ -1,38 +1,77 @@
package app.revanced.patches.reddit.layout.navigation
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
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.HIDE_NAVIGATION_BUTTONS
import app.revanced.patches.reddit.utils.settings.is_2024_26_or_greater
import app.revanced.patches.reddit.utils.settings.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.fingerprint.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.fingerprint.resolvable
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
private const val EXTENSION_METHOD_DESCRIPTOR =
"$PATCHES_PATH/NavigationButtonsPatch;->hideNavigationButtons(Landroid/view/ViewGroup;)V"
private const val EXTENSION_CLASS_DESCRIPTOR =
"$PATCHES_PATH/NavigationButtonsPatch;"
@Suppress("unused")
val navigationButtonsPatch = bytecodePatch(
HIDE_NAVIGATION_BUTTONS.title,
HIDE_NAVIGATION_BUTTONS.summary,
false,
) {
compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(settingsPatch)
execute {
bottomNavScreenFingerprint.matchOrThrow().let {
it.method.apply {
val startIndex = it.patternMatch!!.startIndex
val targetRegister =
getInstruction<FiveRegisterInstruction>(startIndex).registerC
addInstruction(
startIndex + 1,
"invoke-static {v$targetRegister}, $EXTENSION_METHOD_DESCRIPTOR"
if (is_2024_26_or_greater) {
println("WARNING: \"Hide navigation buttons\" patch is not supported in this version. Use Reddit 2024.25.3 or earlier.")
return@execute
}
if (bottomNavScreenFingerprint.resolvable()) {
val bottomNavScreenMutableClass = with (bottomNavScreenFingerprint.methodOrThrow()) {
val startIndex = indexOfGetDimensionPixelSizeInstruction(this)
val targetIndex = indexOfFirstInstructionOrThrow(startIndex, Opcode.NEW_INSTANCE)
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference.toString()
classBy { it.type == targetReference }
?.mutableClass
?: throw ClassNotFoundException("Failed to find class $targetReference")
}
bottomNavScreenOnGlobalLayoutFingerprint.second.matchOrNull(bottomNavScreenMutableClass)?.let {
it.method.apply {
val startIndex = it.patternMatch!!.startIndex
val targetRegister =
getInstruction<FiveRegisterInstruction>(startIndex).registerC
addInstruction(
startIndex + 1,
"invoke-static {v$targetRegister}, $EXTENSION_CLASS_DESCRIPTOR->hideNavigationButtons(Landroid/view/ViewGroup;)V"
)
}
}
} else {
// Legacy method.
bottomNavScreenHandlerFingerprint.methodOrThrow().apply {
val targetIndex = indexOfGetItemsInstruction(this) + 1
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $EXTENSION_CLASS_DESCRIPTOR->hideNavigationButtons(Ljava/util/List;)Ljava/util/List;
move-result-object v$targetRegister
"""
)
}
}

View File

@ -5,9 +5,8 @@ import app.revanced.util.fingerprint.legacyFingerprint
internal val premiumIconFingerprint = legacyFingerprint(
name = "premiumIconFingerprint",
returnType = "Z",
customFingerprint = { method, classDef ->
method.definingClass.endsWith("/MyAccount;") &&
method.name == "isPremiumSubscriber" &&
classDef.sourceFile == "MyAccount.kt"
customFingerprint = { method, _ ->
method.definingClass == "Lcom/reddit/domain/model/MyAccount;" &&
method.name == "isPremiumSubscriber"
}
)

View File

@ -1,17 +1,37 @@
package app.revanced.patches.reddit.layout.recentlyvisited
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
internal val communityDrawerPresenterConstructorFingerprint = legacyFingerprint(
name = "communityDrawerPresenterConstructorFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf("matureFeedFeatures", "communityDrawerSettings"),
customFingerprint = { method, _ ->
indexOfHeaderItemInstruction(method) >= 0
}
)
fun indexOfHeaderItemInstruction(method: Method) =
method.indexOfFirstInstruction {
getReference<FieldReference>()?.name == "RECENTLY_VISITED"
}
internal val communityDrawerPresenterFingerprint = legacyFingerprint(
name = "communityDrawerPresenterFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(Opcode.AGET),
customFingerprint = { method, _ ->
method.definingClass.endsWith("/CommunityDrawerPresenter;")
}
opcodes = listOf(
Opcode.XOR_INT_2ADDR,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
)
)

View File

@ -8,15 +8,12 @@ import app.revanced.patches.reddit.utils.extension.Constants.PATCHES_PATH
import app.revanced.patches.reddit.utils.patch.PatchList.HIDE_RECENTLY_VISITED_SHELF
import app.revanced.patches.reddit.utils.settings.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.findMethodOrThrow
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
private const val EXTENSION_METHOD_DESCRIPTOR =
"$PATCHES_PATH/RecentlyVisitedShelfPatch;" +
@ -33,23 +30,21 @@ val recentlyVisitedShelfPatch = bytecodePatch(
dependsOn(settingsPatch)
execute {
val communityDrawerPresenterMethod = communityDrawerPresenterFingerprint.methodOrThrow()
val constructorMethod = findMethodOrThrow(communityDrawerPresenterMethod.definingClass)
val recentlyVisitedReference = with(constructorMethod) {
val recentlyVisitedFieldIndex = indexOfFirstInstructionOrThrow {
getReference<FieldReference>()?.name == "RECENTLY_VISITED"
}
val recentlyVisitedReference = with (communityDrawerPresenterConstructorFingerprint.methodOrThrow()) {
val recentlyVisitedFieldIndex = indexOfHeaderItemInstruction(this)
val recentlyVisitedObjectIndex =
indexOfFirstInstructionOrThrow(
recentlyVisitedFieldIndex,
Opcode.IPUT_OBJECT
)
getInstruction<ReferenceInstruction>(recentlyVisitedObjectIndex).reference
indexOfFirstInstructionOrThrow(recentlyVisitedFieldIndex, Opcode.IPUT_OBJECT)
getInstruction<ReferenceInstruction>(recentlyVisitedObjectIndex).reference.toString()
}
communityDrawerPresenterMethod.apply {
val recentlyVisitedObjectIndex = indexOfFirstInstructionOrThrow {
getReference<FieldReference>()?.toString() == recentlyVisitedReference.toString()
}
communityDrawerPresenterFingerprint.methodOrThrow(communityDrawerPresenterConstructorFingerprint).apply {
val recentlyVisitedObjectIndex =
indexOfFirstInstructionOrThrow {
(this as? ReferenceInstruction)?.reference?.toString() == recentlyVisitedReference
}
arrayOf(
indexOfFirstInstructionOrThrow(
recentlyVisitedObjectIndex,
@ -65,9 +60,9 @@ val recentlyVisitedShelfPatch = bytecodePatch(
addInstructions(
staticIndex + 2, """
invoke-static {v$insertRegister}, $EXTENSION_METHOD_DESCRIPTOR
move-result-object v$insertRegister
"""
invoke-static {v$insertRegister}, $EXTENSION_METHOD_DESCRIPTOR
move-result-object v$insertRegister
"""
)
}
}

View File

@ -1,16 +1,13 @@
package app.revanced.patches.reddit.layout.screenshotpopup
import app.revanced.patches.reddit.utils.resourceid.screenShotShareBanner
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
internal val screenshotTakenBannerFingerprint = legacyFingerprint(
name = "screenshotTakenBannerFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literals = listOf(screenShotShareBanner),
customFingerprint = { _, classDef ->
classDef.sourceFile == "ScreenshotTakenBanner.kt"
parameters = listOf("Landroidx/compose/runtime/", "I"),
customFingerprint = { method, classDef ->
classDef.type.endsWith("\$ScreenshotTakenBannerKt\$lambda-1\$1;") &&
method.name == "invoke"
}
)

View File

@ -7,7 +7,6 @@ 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.sharedResourceIdPatch
import app.revanced.patches.reddit.utils.settings.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.fingerprint.methodOrThrow
@ -22,10 +21,7 @@ val screenshotPopupPatch = bytecodePatch(
) {
compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(
sharedResourceIdPatch,
settingsPatch
)
dependsOn(settingsPatch)
execute {
screenshotTakenBannerFingerprint.methodOrThrow().apply {

View File

@ -1,18 +1,27 @@
package app.revanced.patches.reddit.layout.subredditdialog
import app.revanced.patches.reddit.utils.resourceid.cancelButton
import app.revanced.patches.reddit.utils.resourceid.textAppearanceRedditBaseOldButtonColored
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val frequentUpdatesSheetScreenFingerprint = legacyFingerprint(
name = "frequentUpdatesSheetScreenFingerprint",
returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literals = listOf(cancelButton),
opcodes = listOf(
Opcode.CONST,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ
),
customFingerprint = { _, classDef ->
classDef.sourceFile == "FrequentUpdatesSheetScreen.kt"
classDef.type == "Lcom/reddit/screens/pager/FrequentUpdatesSheetScreen;"
}
)
@ -20,8 +29,14 @@ internal val redditAlertDialogsFingerprint = legacyFingerprint(
name = "redditAlertDialogsFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literals = listOf(textAppearanceRedditBaseOldButtonColored),
customFingerprint = { _, classDef ->
classDef.sourceFile == "RedditAlertDialogs.kt"
customFingerprint = { method, _ ->
method.definingClass.startsWith("Lcom/reddit/screen/dialog/") &&
indexOfSetBackgroundTintListInstruction(method) >= 0
}
)
fun indexOfSetBackgroundTintListInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "setBackgroundTintList"
}

View File

@ -6,15 +6,16 @@ import app.revanced.patcher.patch.bytecodePatch
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.REMOVE_SUBREDDIT_DIALOG
import app.revanced.patches.reddit.utils.resourceid.cancelButton
import app.revanced.patches.reddit.utils.resourceid.sharedResourceIdPatch
import app.revanced.patches.reddit.utils.resourceid.textAppearanceRedditBaseOldButtonColored
import app.revanced.patches.reddit.utils.settings.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.fingerprint.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"$PATCHES_PATH/RemoveSubRedditDialogPatch;"
@ -26,29 +27,29 @@ val subRedditDialogPatch = bytecodePatch(
) {
compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(
sharedResourceIdPatch,
settingsPatch
)
dependsOn(settingsPatch)
execute {
frequentUpdatesSheetScreenFingerprint.methodOrThrow().apply {
val cancelButtonViewIndex =
indexOfFirstLiteralInstructionOrThrow(cancelButton) + 2
val cancelButtonViewRegister =
getInstruction<OneRegisterInstruction>(cancelButtonViewIndex).registerA
frequentUpdatesSheetScreenFingerprint.matchOrThrow().let {
it.method.apply {
val cancelButtonViewIndex = it.patternMatch!!.startIndex + 2
val cancelButtonViewRegister =
getInstruction<OneRegisterInstruction>(cancelButtonViewIndex).registerA
addInstruction(
cancelButtonViewIndex + 1,
"invoke-static {v$cancelButtonViewRegister}, $EXTENSION_CLASS_DESCRIPTOR->dismissDialog(Landroid/view/View;)V"
)
addInstruction(
cancelButtonViewIndex + 1,
"invoke-static {v$cancelButtonViewRegister}, $EXTENSION_CLASS_DESCRIPTOR->dismissDialog(Landroid/view/View;)V"
)
}
}
redditAlertDialogsFingerprint.methodOrThrow().apply {
val backgroundTintIndex = indexOfSetBackgroundTintListInstruction(this)
val insertIndex =
indexOfFirstLiteralInstructionOrThrow(
textAppearanceRedditBaseOldButtonColored
) + 1
indexOfFirstInstructionOrThrow(backgroundTintIndex) {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "setTextAppearance"
}
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
addInstruction(

View File

@ -1,6 +1,5 @@
package app.revanced.patches.reddit.layout.toolbar
import app.revanced.patches.reddit.utils.resourceid.toolBarNavSearchCtaContainer
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
@ -10,7 +9,7 @@ internal val homePagerScreenFingerprint = legacyFingerprint(
returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/view/LayoutInflater;", "Landroid/view/ViewGroup;"),
literals = listOf(toolBarNavSearchCtaContainer),
strings = listOf("recapNavEntryPointDelegate"),
customFingerprint = { method, _ ->
method.definingClass.endsWith("/HomePagerScreen;")
}

View File

@ -5,12 +5,11 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.reddit.utils.extension.Constants.PATCHES_PATH
import app.revanced.patches.reddit.utils.patch.PatchList.HIDE_TOOLBAR_BUTTON
import app.revanced.patches.reddit.utils.resourceid.sharedResourceIdPatch
import app.revanced.patches.reddit.utils.resourceid.toolBarNavSearchCtaContainer
import app.revanced.patches.reddit.utils.settings.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.fingerprint.matchOrThrow
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
private const val EXTENSION_METHOD_DESCRIPTOR =
@ -21,22 +20,21 @@ private const val EXTENSION_METHOD_DESCRIPTOR =
val toolBarButtonPatch = bytecodePatch {
// compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(
sharedResourceIdPatch,
settingsPatch
)
dependsOn(settingsPatch)
execute {
homePagerScreenFingerprint.methodOrThrow().apply {
val targetIndex =
indexOfFirstLiteralInstructionOrThrow(toolBarNavSearchCtaContainer) + 3
val targetRegister =
getInstruction<OneRegisterInstruction>(targetIndex - 1).registerA
homePagerScreenFingerprint.matchOrThrow().let {
it.method.apply {
val stringIndex = it.stringMatches!!.first().index
val insertIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.CHECK_CAST)
val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
targetIndex,
"invoke-static {v$targetRegister}, $EXTENSION_METHOD_DESCRIPTOR"
)
addInstruction(
insertIndex,
"invoke-static {v$insertRegister}, $EXTENSION_METHOD_DESCRIPTOR"
)
}
}
updatePatchStatus(

View File

@ -1,9 +1,26 @@
package app.revanced.patches.reddit.misc.openlink
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
internal val customReportsFingerprint = legacyFingerprint(
name = "customReportsFingerprint",
returnType = "V",
strings = listOf("https://www.crisistextline.org/", "screenNavigator"),
customFingerprint = { method, _ ->
indexOfScreenNavigatorInstruction(method) >= 0
}
)
fun indexOfScreenNavigatorInstruction(method: Method) =
method.indexOfFirstInstruction {
(this as? ReferenceInstruction)?.reference?.toString()?.contains("Landroid/app/Activity;Landroid/net/Uri;") == true
}
internal val screenNavigatorFingerprint = legacyFingerprint(
name = "screenNavigatorFingerprint",

View File

@ -7,7 +7,6 @@ import app.revanced.patches.reddit.utils.extension.Constants.PATCHES_PATH
import app.revanced.patches.reddit.utils.patch.PatchList.OPEN_LINKS_DIRECTLY
import app.revanced.patches.reddit.utils.settings.settingsPatch
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
import app.revanced.util.fingerprint.methodOrThrow
private const val EXTENSION_METHOD_DESCRIPTOR =
"$PATCHES_PATH/OpenLinksDirectlyPatch;" +
@ -21,10 +20,13 @@ val openLinksDirectlyPatch = bytecodePatch(
) {
compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(settingsPatch)
dependsOn(
settingsPatch,
screenNavigatorMethodResolverPatch
)
execute {
screenNavigatorFingerprint.methodOrThrow().addInstructions(
screenNavigatorMethod.addInstructions(
0, """
invoke-static {p2}, $EXTENSION_METHOD_DESCRIPTOR
move-result-object p2

View File

@ -24,10 +24,13 @@ val openLinksExternallyPatch = bytecodePatch(
) {
compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(settingsPatch)
dependsOn(
settingsPatch,
screenNavigatorMethodResolverPatch
)
execute {
screenNavigatorFingerprint.methodOrThrow().apply {
screenNavigatorMethod.apply {
val insertIndex = indexOfFirstStringInstructionOrThrow("uri") + 2
addInstructionsWithLabels(

View File

@ -0,0 +1,22 @@
package app.revanced.patches.reddit.misc.openlink
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getWalkerMethod
lateinit var screenNavigatorMethod: MutableMethod
val screenNavigatorMethodResolverPatch = bytecodePatch(
description = "screenNavigatorMethodResolverPatch"
) {
execute {
screenNavigatorMethod =
// ~ Reddit 2024.25.3
screenNavigatorFingerprint.second.methodOrNull
// Reddit 2024.26.1 ~
?: with (customReportsFingerprint.methodOrThrow()) {
getWalkerMethod(indexOfScreenNavigatorInstruction(this))
}
}
}

View File

@ -1,13 +1,21 @@
package app.revanced.patches.reddit.misc.tracking.url
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val shareLinkFormatterFingerprint = legacyFingerprint(
name = "shareLinkFormatterFingerprint",
returnType = "Ljava/lang/String;",
parameters = listOf("Ljava/lang/String;", "Ljava/util/Map;"),
customFingerprint = { method, classDef ->
method.definingClass.startsWith("Lcom/reddit/sharing/") &&
classDef.sourceFile == "UrlUtil.kt"
customFingerprint = { method, _ ->
indexOfClearQueryInstruction(method) >= 0
}
)
fun indexOfClearQueryInstruction(method: Method) =
method.indexOfFirstInstruction {
getReference<MethodReference>()?.toString() == "Landroid/net/Uri${'$'}Builder;->clearQuery()Landroid/net/Uri${'$'}Builder;"
}

View File

@ -4,11 +4,10 @@ import app.revanced.patcher.patch.PackageName
import app.revanced.patcher.patch.VersionName
internal object Constants {
internal const val REDDIT_PACKAGE_NAME = "com.reddit.frontpage"
val COMPATIBLE_PACKAGE: Pair<PackageName, Set<VersionName>?> = Pair(
"com.reddit.frontpage",
setOf(
"2023.12.0",
"2024.17.0"
)
REDDIT_PACKAGE_NAME,
null
)
}

View File

@ -1,49 +0,0 @@
package app.revanced.patches.reddit.utils.resourceid
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.shared.mapping.ResourceType.ID
import app.revanced.patches.shared.mapping.ResourceType.STRING
import app.revanced.patches.shared.mapping.ResourceType.STYLE
import app.revanced.patches.shared.mapping.get
import app.revanced.patches.shared.mapping.resourceMappingPatch
import app.revanced.patches.shared.mapping.resourceMappings
var cancelButton = -1L
private set
var labelAcknowledgements = -1L
private set
var screenShotShareBanner = -1L
private set
var textAppearanceRedditBaseOldButtonColored = -1L
private set
var toolBarNavSearchCtaContainer = -1L
private set
internal val sharedResourceIdPatch = resourcePatch(
description = "sharedResourceIdPatch"
) {
dependsOn(resourceMappingPatch)
execute {
cancelButton = resourceMappings[
ID,
"cancel_button",
]
labelAcknowledgements = resourceMappings[
STRING,
"label_acknowledgements"
]
screenShotShareBanner = resourceMappings[
STRING,
"screenshot_share_banner_title"
]
textAppearanceRedditBaseOldButtonColored = resourceMappings[
STYLE,
"TextAppearance.RedditBase.OldButton.Colored"
]
toolBarNavSearchCtaContainer = resourceMappings[
ID,
"toolbar_nav_search_cta_container"
]
}
}

View File

@ -1,7 +1,6 @@
package app.revanced.patches.reddit.utils.settings
import app.revanced.patches.reddit.utils.extension.Constants.EXTENSION_PATH
import app.revanced.patches.reddit.utils.resourceid.labelAcknowledgements
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
@ -10,9 +9,8 @@ import com.android.tools.smali.dexlib2.Opcode
internal val acknowledgementsLabelBuilderFingerprint = legacyFingerprint(
name = "acknowledgementsLabelBuilderFingerprint",
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroidx/preference/Preference;"),
literals = listOf(labelAcknowledgements),
strings = listOf("onboardingAnalytics"),
customFingerprint = { method, _ ->
method.definingClass.startsWith("Lcom/reddit/screen/settings/preferences/")
}
@ -32,6 +30,16 @@ internal val ossLicensesMenuActivityOnCreateFingerprint = legacyFingerprint(
}
)
internal val redditInternalFeaturesFingerprint = legacyFingerprint(
name = "redditInternalFeaturesFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf("RELEASE"),
customFingerprint = { methodDef, _ ->
!methodDef.definingClass.startsWith("Lcom/")
}
)
internal val settingsStatusLoadFingerprint = legacyFingerprint(
name = "settingsStatusLoadFingerprint",
customFingerprint = { method, _ ->

View File

@ -4,7 +4,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patcher.patch.stringOption
@ -14,15 +13,18 @@ import app.revanced.patches.reddit.utils.extension.Constants.EXTENSION_PATH
import app.revanced.patches.reddit.utils.extension.sharedExtensionPatch
import app.revanced.patches.reddit.utils.patch.PatchList
import app.revanced.patches.reddit.utils.patch.PatchList.SETTINGS_FOR_REDDIT
import app.revanced.patches.reddit.utils.resourceid.labelAcknowledgements
import app.revanced.patches.shared.sharedSettingFingerprint
import app.revanced.util.fingerprint.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstStringInstructionOrThrow
import app.revanced.util.valueOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import kotlin.io.path.exists
private const val EXTENSION_METHOD_DESCRIPTOR =
@ -31,11 +33,29 @@ private const val EXTENSION_METHOD_DESCRIPTOR =
private lateinit var acknowledgementsLabelBuilderMethod: MutableMethod
private lateinit var settingsStatusLoadMethod: MutableMethod
var is_2024_26_or_greater = false
private set
private val settingsBytecodePatch = bytecodePatch(
description = "settingsBytecodePatch"
) {
execute {
/**
* Set version info
*/
redditInternalFeaturesFingerprint.methodOrThrow().apply {
val versionIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.CONST_STRING
&& (this as? BuilderInstruction21c)?.reference.toString().startsWith("202")
}
val versionNumber = getInstruction<BuilderInstruction21c>(versionIndex).reference.toString().replace(".", "").toInt()
is_2024_26_or_greater = 2024260 <= versionNumber
}
/**
* Set SharedPrefCategory
*/
@ -52,8 +72,8 @@ private val settingsBytecodePatch = bytecodePatch(
/**
* Replace settings label
*/
acknowledgementsLabelBuilderMethod = acknowledgementsLabelBuilderFingerprint
.methodOrThrow()
acknowledgementsLabelBuilderMethod =
acknowledgementsLabelBuilderFingerprint.methodOrThrow()
/**
* Initialize settings activity
@ -77,8 +97,11 @@ private val settingsBytecodePatch = bytecodePatch(
internal fun updateSettingsLabel(label: String) =
acknowledgementsLabelBuilderMethod.apply {
val insertIndex =
indexOfFirstLiteralInstructionOrThrow(labelAcknowledgements) + 3
val stringIndex = indexOfFirstStringInstructionOrThrow("onboardingAnalytics")
val insertIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "getString"
} + 2
val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
@ -134,22 +157,25 @@ val settingsPatch = resourcePatch(
val settingsLabel = settingsLabelOption
.valueOrThrow()
arrayOf("preferences.xml", "preferences_logged_in.xml").forEach { targetXML ->
arrayOf(
"preferences.xml",
"preferences_logged_in.xml",
"preferences_logged_in_old.xml",
).forEach { targetXML ->
val resDirectory = get("res")
val targetXml = resDirectory.resolve("xml").resolve(targetXML).toPath()
if (!targetXml.exists())
throw PatchException("The preferences can not be found.")
if (targetXml.exists()) {
val preference = get("res/xml/$targetXML")
val preference = get("res/xml/$targetXML")
preference.writeText(
preference.readText()
.replace(
"\"@drawable/icon_text_post\" android:title=\"@string/label_acknowledgements\"",
"\"@drawable/icon_beta_planet\" android:title=\"$settingsLabel\""
)
)
preference.writeText(
preference.readText()
.replace(
"\"@drawable/icon_text_post\" android:title=\"@string/label_acknowledgements\"",
"\"@drawable/icon_beta_planet\" android:title=\"$settingsLabel\""
)
)
}
}
updateSettingsLabel(settingsLabel)