diff --git a/extensions/instagram/src/main/java/app/revanced/extension/instagram/misc/download/DownloadMediaPatch.java b/extensions/instagram/src/main/java/app/revanced/extension/instagram/misc/download/DownloadMediaPatch.java new file mode 100644 index 0000000000..96474c2a59 --- /dev/null +++ b/extensions/instagram/src/main/java/app/revanced/extension/instagram/misc/download/DownloadMediaPatch.java @@ -0,0 +1,21 @@ +package app.revanced.extension.instagram.misc.download; + +@SuppressWarnings("unused") +public class DownloadMediaPatch { + + /** + * Injection point. + * Always return true to allow downloading all media regardless of creator settings. + */ + public static boolean isDownloadAllowed() { + return true; + } + + /** + * Injection point. + * Force third-party downloads to be enabled. + */ + public static int forceThirdPartyDownloadsEnabled(int originalValue) { + return 1; + } +} diff --git a/extensions/instagram/src/main/java/app/revanced/extension/instagram/profile/CopyBioTextPatch.java b/extensions/instagram/src/main/java/app/revanced/extension/instagram/profile/CopyBioTextPatch.java new file mode 100644 index 0000000000..8868a79880 --- /dev/null +++ b/extensions/instagram/src/main/java/app/revanced/extension/instagram/profile/CopyBioTextPatch.java @@ -0,0 +1,17 @@ +package app.revanced.extension.instagram.profile; + +import android.widget.TextView; + +@SuppressWarnings("unused") +public class CopyBioTextPatch { + + /** + * Injection point. + * Makes the bio TextView selectable and copyable. + */ + public static void makeBioTextSelectable(TextView bioTextView) { + if (bioTextView != null) { + bioTextView.setTextIsSelectable(true); + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/feed/autorefresh/DisableFeedAutoRefreshPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/autorefresh/DisableFeedAutoRefreshPatch.kt new file mode 100644 index 0000000000..4df907c4c9 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/autorefresh/DisableFeedAutoRefreshPatch.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.instagram.feed.autorefresh + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val disableFeedAutoRefreshPatch = bytecodePatch( + name = "Disable feed auto-refresh", + description = "Disables automatic feed refresh when returning to the app or scrolling to top.", + use = false, +) { + compatibleWith("com.instagram.android") + + apply { + pullToRefreshMethod.returnEarly() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/feed/autorefresh/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/autorefresh/Fingerprints.kt new file mode 100644 index 0000000000..3e44f103d7 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/autorefresh/Fingerprints.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.instagram.feed.autorefresh + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.pullToRefreshMethod by gettingFirstMethodDeclaratively("disable_pull_to_refresh") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/feed/scroll/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/scroll/Fingerprints.kt new file mode 100644 index 0000000000..d23493e356 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/scroll/Fingerprints.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.instagram.feed.scroll + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.scrollToTopMethod by gettingFirstMethodDeclaratively("feed/scroll_to_top") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/feed/scroll/KeepScrollPositionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/scroll/KeepScrollPositionPatch.kt new file mode 100644 index 0000000000..71d8429167 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/feed/scroll/KeepScrollPositionPatch.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.instagram.feed.scroll + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val keepScrollPositionPatch = bytecodePatch( + name = "Keep scroll position", + description = "Prevents the feed from automatically scrolling to the top when returning to the app.", + use = false, +) { + compatibleWith("com.instagram.android") + + apply { + scrollToTopMethod.returnEarly() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/gesture/DisableDoubleTapToLikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/gesture/DisableDoubleTapToLikePatch.kt new file mode 100644 index 0000000000..aeef45dd14 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/gesture/DisableDoubleTapToLikePatch.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.instagram.gesture + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val disableDoubleTapToLikePatch = bytecodePatch( + name = "Disable double-tap to like", + description = "Disables the double-tap gesture to like posts in the feed.", + use = false, +) { + compatibleWith("com.instagram.android") + + apply { + doubleTapToLikeMethod.returnEarly() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/gesture/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/gesture/Fingerprints.kt new file mode 100644 index 0000000000..4011f657da --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/gesture/Fingerprints.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.instagram.gesture + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.doubleTapToLikeMethod by gettingFirstMethodDeclaratively("NUX_TYPE_DOUBLE_TAP_TO_LIKE") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/AnonymousStoryViewingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/AnonymousStoryViewingPatch.kt index 123ada7c2f..ddcacf2914 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/AnonymousStoryViewingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/AnonymousStoryViewingPatch.kt @@ -17,7 +17,7 @@ val anonymousStoryViewingPatch = bytecodePatch( compatibleWith("com.instagram.android") apply { - // Prevent the hashmap of the seen media to be filled - setMediaSeenHashmapMethod.returnEarly() + // Prevent seen state from being written to the server + setMediaSeenMethod.returnEarly() } } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/Fingerprints.kt index a7027aa61e..b9c6263031 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/ghost/story/Fingerprints.kt @@ -1,11 +1,6 @@ package app.revanced.patches.instagram.ghost.story import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.returnType -internal val BytecodePatchContext.setMediaSeenHashmapMethod by gettingFirstMethodDeclaratively("media/seen/") { - parameterTypes() - returnType("V") -} +internal val BytecodePatchContext.setMediaSeenMethod by gettingFirstMethodDeclaratively("visual_media_seen") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/comments/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/comments/Fingerprints.kt new file mode 100644 index 0000000000..b67c62d98b --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/comments/Fingerprints.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.instagram.hide.comments + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.commentButtonMethod by gettingFirstMethodDeclaratively("feed_comment_button") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/comments/HideCommentButtonPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/comments/HideCommentButtonPatch.kt new file mode 100644 index 0000000000..3c9778b4f4 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/comments/HideCommentButtonPatch.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.instagram.hide.comments + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val hideCommentButtonPatch = bytecodePatch( + name = "Hide comment button", + description = "Hides the comment icon button on feed posts, reels, and stories.", + use = false, +) { + compatibleWith("com.instagram.android") + + apply { + commentButtonMethod.returnEarly() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt index a1f4f1fab0..0567b99cbe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt @@ -1,21 +1,6 @@ package app.revanced.patches.instagram.hide.suggestions -import app.revanced.patcher.composingFirstMethod -import app.revanced.patcher.instructions -import app.revanced.patcher.invoke +import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.unorderedAllOf -internal val FEED_ITEM_KEYS_TO_BE_HIDDEN = arrayOf( - "clips_netego", - "stories_netego", - "in_feed_survey", - "bloks_netego", - "suggested_igd_channels", - "suggested_top_accounts", - "suggested_users", -) - -internal val BytecodePatchContext.feedItemParseFromJsonMethodMatch by composingFirstMethod("feed_item_type") { - instructions(predicates = unorderedAllOf(predicates = FEED_ITEM_KEYS_TO_BE_HIDDEN.map { it() }.toTypedArray())) -} +internal val BytecodePatchContext.feedItemParseFromJsonMethod by gettingFirstMethodDeclaratively("feed_item_type") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContentPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContentPatch.kt index f82335e186..1936ba0d28 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContentPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContentPatch.kt @@ -1,25 +1,18 @@ package app.revanced.patches.instagram.hide.suggestions -import app.revanced.patcher.extensions.getInstruction -import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.returnEarly @Suppress("unused") val hideSuggestedContentPatch = bytecodePatch( name = "Hide suggested content", - description = "Hides suggested stories, reels, threads and survey from feed (Suggested posts will still be shown).", + description = "Hides suggested stories, reels, threads and survey from feed.", use = false, ) { compatibleWith("com.instagram.android") apply { - feedItemParseFromJsonMethodMatch.method.apply { - feedItemParseFromJsonMethodMatch.indices[0].forEach { targetStringIndex -> - val targetStringRegister = getInstruction(targetStringIndex).registerA - - replaceInstruction(targetStringIndex, "const-string v$targetStringRegister, \"BOGUS\"") - } - } + // Return early from feed item parsing to skip suggested content + feedItemParseFromJsonMethod.returnEarly() } } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/download/DownloadMediaPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/download/DownloadMediaPatch.kt new file mode 100644 index 0000000000..662f3fc539 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/download/DownloadMediaPatch.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.instagram.misc.download + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val downloadMediaPatch = bytecodePatch( + name = "Download media", + description = "Allows downloading all media (photos, videos, reels) regardless of creator's download settings.", + use = false, +) { + compatibleWith("com.instagram.android") + + apply { + downloadAllowedMethod.returnEarly(true) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/download/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/download/Fingerprints.kt new file mode 100644 index 0000000000..c3cb7ce41b --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/download/Fingerprints.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.instagram.misc.download + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.downloadAllowedMethod by gettingFirstMethodDeclaratively("clips_download_allowed_toggle_auto") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/profile/copybio/CopyBioTextPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/profile/copybio/CopyBioTextPatch.kt new file mode 100644 index 0000000000..404e4702ab --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/profile/copybio/CopyBioTextPatch.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.instagram.profile.copybio + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val copyBioTextPatch = bytecodePatch( + name = "Copy bio text", + description = "Makes user bio text selectable and copyable on profile pages.", + use = false, +) { + compatibleWith("com.instagram.android") + + apply { + profileBioMethod.returnEarly() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/profile/copybio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/profile/copybio/Fingerprints.kt new file mode 100644 index 0000000000..e8dc6dba3d --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/profile/copybio/Fingerprints.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.instagram.profile.copybio + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.profileBioMethod by gettingFirstMethodDeclaratively("profile_bio") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/reels/autoscroll/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/reels/autoscroll/Fingerprints.kt index a3c75efe92..3e949d48fc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/reels/autoscroll/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/reels/autoscroll/Fingerprints.kt @@ -1,24 +1,18 @@ package app.revanced.patches.instagram.reels.autoscroll import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.returnType /** * Matches the feature availability gate that determines * whether auto-scroll should be available for Reels. */ -internal val BytecodePatchContext.clipsAutoScrollFeatureCheckMethod by gettingFirstMethodDeclaratively("auto_scroll") { - returnType("Z") - parameterTypes("Lcom/instagram/common/session/UserSession;", "Z") -} +internal val BytecodePatchContext.clipsAutoScrollFeatureCheckMethod by gettingFirstMethodDeclaratively("auto_scroll") /** * Matches the toggle handler called when the user taps * the auto-scroll button. Contains analytics logging strings. */ internal val BytecodePatchContext.clipsAutoScrollToggleMethod by gettingFirstMethodDeclaratively( - "auto_scroll", - "instagram_clips_viewer_autoplay_tap", + "clips_viewer_autoscroll", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt index 443d60d155..38a7692bb0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt @@ -15,6 +15,6 @@ val enableLocationStickerRedesignPatch = bytecodePatch( // The gate method reads a MobileConfig boolean flag and returns it directly. // Returning early with true bypasses the flag check entirely, // enabling the redesigned sticker styles regardless of server configuration. - locationStickerRedesignGateMethodMatch.method.returnEarly(true) + locationStickerRedesignGateMethod.returnEarly(true) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt index 0972d692c9..c38d32751d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt @@ -1,16 +1,6 @@ -package app.revanced.patches.instagram.story.locationsticker - -import app.revanced.patcher.composingFirstMethod -import app.revanced.patcher.instructions -import app.revanced.patcher.invoke -import app.revanced.patcher.patch.BytecodePatchContext - -// MobileConfig boolean key that gates the redesigned location sticker styles. -// The method containing this constant reads the flag and returns it directly, -// making it the sole control point for the feature. The key is stable across -// app updates as MobileConfig keys are server-assigned constants. -private const val LOCATION_STICKER_REDESIGN_CONFIG_KEY = 0x8105a100041e0dL - -internal val BytecodePatchContext.locationStickerRedesignGateMethodMatch by composingFirstMethod { - instructions(LOCATION_STICKER_REDESIGN_CONFIG_KEY()) -} +package app.revanced.patches.instagram.story.locationsticker + +import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext + +internal val BytecodePatchContext.locationStickerRedesignGateMethod by gettingFirstMethodDeclaratively("map_location_sticker_fragment")