Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
be2b144
fix(Instagram - Change sharing domain): Display patch option (#6089)
brosssh Oct 9, 2025
2d928e0
chore: Release v5.42.2-dev.1 [skip ci]
semantic-release-bot Oct 9, 2025
a98e8f7
chore: Sync translations (#6097)
github-actions[bot] Oct 10, 2025
5484625
fix(X / Twitter - Change Link Sharing Domain): Change link domain of …
Leo40Git Oct 10, 2025
a0e2c5c
chore: Release v5.42.2-dev.2 [skip ci]
semantic-release-bot Oct 10, 2025
6555f6e
fix(YouTube - Custom branding): Do not add a broken custom icon if th…
LisoUseInAIKyrios Oct 11, 2025
a8c4bdb
chore: Release v5.42.2-dev.3 [skip ci]
semantic-release-bot Oct 11, 2025
50f0b9c
feat(Instagram): Add `Hide suggested content` patch (#6075)
Swakshan Oct 11, 2025
4547ecb
chore: Release v5.43.0-dev.1 [skip ci]
semantic-release-bot Oct 11, 2025
5bd0f11
chore: Sync translations (#6117)
github-actions[bot] Oct 14, 2025
10ea250
fix(YouTube - Custom branding): Use ReVanced icon for status bar noti…
LisoUseInAIKyrios Oct 14, 2025
566875e
chore: Release v5.43.0-dev.2 [skip ci]
semantic-release-bot Oct 14, 2025
95eee59
fix(Custom branding): Use white notification icon for expanded status…
LisoUseInAIKyrios Oct 14, 2025
bf73ac8
chore: Release v5.43.0-dev.3 [skip ci]
semantic-release-bot Oct 14, 2025
0c19dba
fix(YouTube - Force original audio): Do not use translated audio if s…
LisoUseInAIKyrios Oct 14, 2025
068d029
refactor: Use notNull delegate to prevent wasting more time in the fu…
LisoUseInAIKyrios Oct 14, 2025
e8522d7
chore: Release v5.43.0-dev.4 [skip ci]
semantic-release-bot Oct 14, 2025
a55560d
chore: Sync translations (#6118)
github-actions[bot] Oct 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
# [5.43.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.43.0-dev.3...v5.43.0-dev.4) (2025-10-14)


### Bug Fixes

* **YouTube - Force original audio:** Do not use translated audio if stream spoofing is off and force audio is on ([0c19dba](https://github.com/ReVanced/revanced-patches/commit/0c19dbaf30bcb95a29448d98b028ebeea54cc7d3))

# [5.43.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.43.0-dev.2...v5.43.0-dev.3) (2025-10-14)


### Bug Fixes

* **Custom branding:** Use white notification icon for expanded status bar panel ([95eee59](https://github.com/ReVanced/revanced-patches/commit/95eee59a87a680e212a3ba06e1afefee8d91ee9d))

# [5.43.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.43.0-dev.1...v5.43.0-dev.2) (2025-10-14)


### Bug Fixes

* **YouTube - Custom branding:** Use ReVanced icon for status bar notification icon ([#6108](https://github.com/ReVanced/revanced-patches/issues/6108)) ([10ea250](https://github.com/ReVanced/revanced-patches/commit/10ea250d4a91f8ab3b7f865612a403fc93a857b5))

# [5.43.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.42.2-dev.3...v5.43.0-dev.1) (2025-10-11)


### Features

* **Instagram:** Add `Hide suggested content` patch ([#6075](https://github.com/ReVanced/revanced-patches/issues/6075)) ([50f0b9c](https://github.com/ReVanced/revanced-patches/commit/50f0b9c5eee95ff5f9974e344802e1d2a4aab47b))

## [5.42.2-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.42.2-dev.2...v5.42.2-dev.3) (2025-10-11)


### Bug Fixes

* **YouTube - Custom branding:** Do not add a broken custom icon if the user provides an invalid custom icon path ([6555f6e](https://github.com/ReVanced/revanced-patches/commit/6555f6e6f8b52c2f1ddab1f52c6704cd2d8cfc12))

## [5.42.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.42.2-dev.1...v5.42.2-dev.2) (2025-10-10)


### Bug Fixes

* **X / Twitter - Change Link Sharing Domain:** Change link domain of share copy action ([#6091](https://github.com/ReVanced/revanced-patches/issues/6091)) ([5484625](https://github.com/ReVanced/revanced-patches/commit/54846253d748f4e7e30b2bba427c7d2fb9c341e2))

## [5.42.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.42.1...v5.42.2-dev.1) (2025-10-09)


### Bug Fixes

* **Instagram - Change sharing domain:** Display patch option ([#6089](https://github.com/ReVanced/revanced-patches/issues/6089)) ([be2b144](https://github.com/ReVanced/revanced-patches/commit/be2b144cc9c4108ec37e16f3dd20573d88ffaa2b))

## [5.42.1](https://github.com/ReVanced/revanced-patches/compare/v5.42.0...v5.42.1) (2025-10-08)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import android.widget.Toolbar;

import app.revanced.extension.music.settings.MusicActivityHook;
import app.revanced.extension.shared.GmsCoreSupport;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;

/**
Expand All @@ -30,6 +32,17 @@ protected void initialize() {
preferenceScreen = getPreferenceScreen();
Utils.sortPreferenceGroups(preferenceScreen);
setPreferenceScreenToolbar(preferenceScreen);

// Clunky work around until preferences are custom classes that manage themselves.
// Custom branding only works with non-root install. But the preferences must be
// added during patched because of difficulties detecting during patching if it's
// a root install. So instead the non-functional preferences are removed during
// runtime if the app is mount (root) installation.
if (GmsCoreSupport.isPackageNameOriginal()) {
removePreferences(
BaseSettings.CUSTOM_BRANDING_ICON.key,
BaseSettings.CUSTOM_BRANDING_NAME.key);
}
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package app.revanced.extension.shared.patches;

import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import app.revanced.extension.shared.GmsCoreSupport;
import app.revanced.extension.shared.Logger;
Expand All @@ -29,28 +32,56 @@ public class CustomBrandingPatch {
// The most that can be done is to hide a theme from the UI and keep the alias with dummy data.
public enum BrandingTheme {
/**
* Original unpatched icon. Must be first enum.
* Original unpatched icon.
*/
ORIGINAL("revanced_original"),
ROUNDED("revanced_rounded"),
MINIMAL("revanced_minimal"),
SCALED("revanced_scaled"),
ORIGINAL,
ROUNDED,
MINIMAL,
SCALED,
/**
* User provided custom icon. Must be the last enum.
* User provided custom icon.
*/
CUSTOM("revanced_custom");

public final String themeAlias;

BrandingTheme(String themeAlias) {
this.themeAlias = themeAlias;
}
CUSTOM;

private String packageAndNameIndexToClassAlias(String packageName, int appIndex) {
if (appIndex <= 0) {
throw new IllegalArgumentException("App index starts at index 1");
}
return packageName + '.' + themeAlias + '_' + appIndex;
return packageName + ".revanced_" + name().toLowerCase(Locale.US) + '_' + appIndex;
}
}

private static final int notificationSmallIcon;

static {
BrandingTheme branding = BaseSettings.CUSTOM_BRANDING_ICON.get();
if (branding == BrandingTheme.ORIGINAL) {
notificationSmallIcon = 0;
} else {
// Original icon is quantum_ic_video_youtube_white_24
String iconName = "revanced_notification_icon";
if (branding == BrandingTheme.CUSTOM) {
iconName += "_custom";
}

notificationSmallIcon = Utils.getResourceIdentifier(iconName, "drawable");
if (notificationSmallIcon == 0) {
Logger.printException(() -> "Could not load notification small icon");
}
}
}

/**
* Injection point.
*/
public static void setNotificationIcon(Notification.Builder builder) {
try {
if (notificationSmallIcon != 0) {
builder.setSmallIcon(notificationSmallIcon)
.setColor(Color.TRANSPARENT); // Remove YT red tint.
}
} catch (Exception ex) {
Logger.printException(() -> "setNotificationIcon failure", ex);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.TypedValue;
import android.view.ViewGroup;
Expand All @@ -22,6 +23,24 @@

@SuppressWarnings({"deprecation", "NewApi"})
public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {

/**
* Removes the list of preferences from this fragment, if they exist.
* @param keys Preference keys.
*/
protected void removePreferences(String ... keys) {
for (String key : keys) {
Preference pref = findPreference(key);
if (pref != null) {
PreferenceGroup parent = pref.getParent();
if (parent != null) {
Logger.printDebug(() -> "Removing preference: " + key);
parent.removePreference(pref);
}
}
}
}

/**
* Sets toolbar for all nested preference screens.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@

@SuppressWarnings("unused")
public final class ChangeLinkSharingDomainPatch {
private static final String DOMAIN_NAME = "https://fxtwitter.com";
private static final String LINK_FORMAT = "%s/%s/status/%s";

/**
* Injection point.
* Method is modified during patching. Do not change.
*/
public static String formatResourceLink(Object... formatArgs) {
String username = (String) formatArgs[0];
String tweetId = (String) formatArgs[1];
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
private static String getShareDomain() {
return "";
}

/**
* Injection point.
*/
public static String formatLink(long tweetId, String username) {
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
return String.format(LINK_FORMAT, getShareDomain(), username, tweetId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import android.preference.PreferenceScreen;
import android.widget.Toolbar;

import app.revanced.extension.shared.GmsCoreSupport;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
import app.revanced.extension.youtube.settings.YouTubeActivityHook;

Expand All @@ -30,6 +32,17 @@ protected void initialize() {
preferenceScreen = getPreferenceScreen();
Utils.sortPreferenceGroups(preferenceScreen);
setPreferenceScreenToolbar(preferenceScreen);

// Clunky work around until preferences are custom classes that manage themselves.
// Custom branding only works with non-root install. But the preferences must be
// added during patched because of difficulties detecting during patching if it's
// a root install. So instead the non-functional preferences are removed during
// runtime if the app is mount (root) installation.
if (GmsCoreSupport.isPackageNameOriginal()) {
removePreferences(
BaseSettings.CUSTOM_BRANDING_ICON.key,
BaseSettings.CUSTOM_BRANDING_NAME.key);
}
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
version = 5.42.1
version = 5.43.0-dev.4
6 changes: 5 additions & 1 deletion patches/api/patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ public final class app/revanced/patches/instagram/feed/LimitFeedToFollowedProfil
}

public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
public static final fun getHideExportFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getHideExploreFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/instagram/hide/navigation/HideNavigationButtonsKt {
Expand All @@ -280,6 +280,10 @@ public final class app/revanced/patches/instagram/hide/stories/HideStoriesKt {
public static final fun getHideStoriesPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/instagram/hide/suggestions/HideSuggestedContentKt {
public static final fun getHideSuggestedContent ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/instagram/misc/devmenu/EnableDeveloperMenuPatchKt {
public static final fun getEnableDeveloperMenuPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package app.revanced.patches.instagram.hide.explore

import app.revanced.patcher.fingerprint

internal const val EXPLORE_KEY_TO_BE_HIDDEN = "sectional_items"

internal val exploreResponseJsonParserFingerprint = fingerprint {
strings("sectional_items", "ExploreTopicalFeedResponse")
strings(EXPLORE_KEY_TO_BE_HIDDEN, "ExploreTopicalFeedResponse")
custom { method, _ -> method.name == "parseFromJson" }
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
package app.revanced.patches.instagram.hide.explore

import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction

context(BytecodePatchContext)
internal fun Fingerprint.replaceJsonFieldWithBogus(
key: String,
) {
val targetStringIndex = stringMatches!!.first { match -> match.string == key }.index
val targetStringRegister = method.getInstruction<OneRegisterInstruction>(targetStringIndex).registerA

/**
* Replacing the JSON key we want to skip with a random string that is not a valid JSON key.
* This way the feeds array will never be populated.
* Received JSON keys that are not handled are simply ignored, so there are no side effects.
*/
method.replaceInstruction(
targetStringIndex,
"const-string v$targetStringRegister, \"BOGUS\"",
)
}

@Suppress("unused")
val hideExportFeedPatch = bytecodePatch(
val hideExploreFeedPatch = bytecodePatch(
name = "Hide explore feed",
description = "Hides posts and reels from the explore/search page.",
use = false
use = false,
) {
compatibleWith("com.instagram.android")

execute {
exploreResponseJsonParserFingerprint.method.apply {
val sectionalItemStringIndex = exploreResponseJsonParserFingerprint.stringMatches!!.first().index
val sectionalItemStringRegister = getInstruction<OneRegisterInstruction>(sectionalItemStringIndex).registerA

/**
* Replacing the JSON key we want to skip with a random string that is not a valid JSON key.
* This way the feeds array will never be populated.
* Received JSON keys that are not handled are simply ignored, so there are no side effects.
*/
replaceInstruction(
sectionalItemStringIndex,
"const-string v$sectionalItemStringRegister, \"BOGUS\""
)
}
exploreResponseJsonParserFingerprint.replaceJsonFieldWithBogus(EXPLORE_KEY_TO_BE_HIDDEN)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app.revanced.patches.instagram.hide.suggestions

import app.revanced.patcher.fingerprint

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 feedItemParseFromJsonFingerprint = fingerprint {
strings(*FEED_ITEM_KEYS_TO_BE_HIDDEN, "FeedItem")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package app.revanced.patches.instagram.hide.suggestions

import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.instagram.hide.explore.replaceJsonFieldWithBogus

@Suppress("unused")
val hideSuggestedContent = bytecodePatch(
name = "Hide suggested content",
description = "Hides suggested stories, reels, threads and survey from feed (Suggested posts will still be shown).",
use = false,
) {
compatibleWith("com.instagram.android")

execute {
FEED_ITEM_KEYS_TO_BE_HIDDEN.forEach { key ->
feedItemParseFromJsonFingerprint.replaceJsonFieldWithBogus(key)
}
}
}
Loading
Loading