Compare commits

..

2 Commits

Author SHA1 Message Date
Pun Butrach
12b819d20e ci: Schedule Crowdin to runs weekly instead of every 12 hours (#6466) 2026-01-12 02:40:19 +01:00
Pun Butrach
004b5908db build: Use Gradle credentials system (#6467) 2026-01-11 16:59:48 +01:00
622 changed files with 6915 additions and 7180 deletions

View File

@@ -25,7 +25,8 @@ jobs:
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ORG_GRADLE_PROJECT_githubPackagesUsername: ${{ env.GITHUB_ACTOR }}
ORG_GRADLE_PROJECT_githubPackagesPassword: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew :patches:buildAndroid --no-daemon
- name: Upload artifacts

View File

@@ -2,7 +2,7 @@ name: Pull strings
on:
schedule:
- cron: "0 */12 * * *"
- cron: "0 0 * * 0"
workflow_dispatch:
jobs:

View File

@@ -31,7 +31,8 @@ jobs:
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ORG_GRADLE_PROJECT_githubPackagesUsername: ${{ env.GITHUB_ACTOR }}
ORG_GRADLE_PROJECT_githubPackagesPassword: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew :patches:buildAndroid clean
- name: Setup Node.js

View File

@@ -11,7 +11,6 @@ import android.widget.Toolbar;
import app.revanced.extension.music.settings.preference.MusicPreferenceFragment;
import app.revanced.extension.music.settings.search.MusicSearchViewController;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;
@@ -47,7 +46,15 @@ public class MusicActivityHook extends BaseActivityHook {
// Override the default YouTube Music theme to increase start padding of list items.
// Custom style located in resources/music/values/style.xml
activity.setTheme(Utils.getResourceIdentifierOrThrow(
ResourceType.STYLE, "Theme.ReVanced.YouTubeMusic.Settings"));
"Theme.ReVanced.YouTubeMusic.Settings", "style"));
}
/**
* Returns the resource ID for the YouTube Music settings layout.
*/
@Override
protected int getContentViewResourceId() {
return LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR;
}
/**

View File

@@ -1,57 +0,0 @@
package app.revanced.extension.shared;
import java.util.HashMap;
import java.util.Map;
public enum ResourceType {
ANIM("anim"),
ANIMATOR("animator"),
ARRAY("array"),
ATTR("attr"),
BOOL("bool"),
COLOR("color"),
DIMEN("dimen"),
DRAWABLE("drawable"),
FONT("font"),
FRACTION("fraction"),
ID("id"),
INTEGER("integer"),
INTERPOLATOR("interpolator"),
LAYOUT("layout"),
MENU("menu"),
MIPMAP("mipmap"),
NAVIGATION("navigation"),
PLURALS("plurals"),
RAW("raw"),
STRING("string"),
STYLE("style"),
STYLEABLE("styleable"),
TRANSITION("transition"),
VALUES("values"),
XML("xml");
private static final Map<String, ResourceType> VALUE_MAP;
static {
ResourceType[] values = values();
VALUE_MAP = new HashMap<>(2 * values.length);
for (ResourceType type : values) {
VALUE_MAP.put(type.value, type);
}
}
public final String value;
public static ResourceType fromValue(String value) {
ResourceType type = VALUE_MAP.get(value);
if (type == null) {
throw new IllegalArgumentException("Unknown resource type: " + value);
}
return type;
}
ResourceType(String value) {
this.value = value;
}
}

View File

@@ -32,11 +32,7 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.Toolbar;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
@@ -47,10 +43,8 @@ import java.text.Collator;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -82,8 +76,6 @@ public class Utils {
@Nullable
private static Boolean isDarkModeEnabled;
private static boolean appIsUsingBoldIcons;
// Cached Collator instance with its locale.
@Nullable
private static Locale cachedCollatorLocale;
@@ -156,12 +148,12 @@ public class Utils {
/**
* Hide a view by setting its layout height and width to 1dp.
*
* @param setting The setting to check for hiding the view.
* @param condition The setting to check for hiding the view.
* @param view The view to hide.
*/
public static void hideViewBy0dpUnderCondition(BooleanSetting setting, View view) {
if (hideViewBy0dpUnderCondition(setting.get(), view)) {
Logger.printDebug(() -> "View hidden by setting: " + setting);
public static void hideViewBy0dpUnderCondition(BooleanSetting condition, View view) {
if (hideViewBy0dpUnderCondition(condition.get(), view)) {
Logger.printDebug(() -> "View hidden by setting: " + condition);
}
}
@@ -173,47 +165,22 @@ public class Utils {
*/
public static boolean hideViewBy0dpUnderCondition(boolean condition, View view) {
if (condition) {
hideViewBy0dp(view);
hideViewByLayoutParams(view);
return true;
}
return false;
}
/**
* Hide a view by setting its layout params to 0x0
* @param view The view to hide.
*/
public static void hideViewBy0dp(View view) {
if (view instanceof LinearLayout) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, 0);
view.setLayoutParams(layoutParams);
} else if (view instanceof FrameLayout) {
FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(0, 0);
view.setLayoutParams(layoutParams2);
} else if (view instanceof RelativeLayout) {
RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(0, 0);
view.setLayoutParams(layoutParams3);
} else if (view instanceof Toolbar) {
Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(0, 0);
view.setLayoutParams(layoutParams4);
} else {
ViewGroup.LayoutParams params = view.getLayoutParams();
params.width = 0;
params.height = 0;
view.setLayoutParams(params);
}
}
/**
* Hide a view by setting its visibility to GONE.
*
* @param setting The setting to check for hiding the view.
* @param condition The setting to check for hiding the view.
* @param view The view to hide.
*/
public static void hideViewUnderCondition(BooleanSetting setting, View view) {
if (hideViewUnderCondition(setting.get(), view)) {
Logger.printDebug(() -> "View hidden by setting: " + setting);
public static void hideViewUnderCondition(BooleanSetting condition, View view) {
if (hideViewUnderCondition(condition.get(), view)) {
Logger.printDebug(() -> "View hidden by setting: " + condition);
}
}
@@ -232,14 +199,14 @@ public class Utils {
return false;
}
public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting setting, View view) {
if (hideViewByRemovingFromParentUnderCondition(setting.get(), view)) {
Logger.printDebug(() -> "View hidden by setting: " + setting);
public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting condition, View view) {
if (hideViewByRemovingFromParentUnderCondition(condition.get(), view)) {
Logger.printDebug(() -> "View hidden by setting: " + condition);
}
}
public static boolean hideViewByRemovingFromParentUnderCondition(boolean condition, View view) {
if (condition) {
public static boolean hideViewByRemovingFromParentUnderCondition(boolean setting, View view) {
if (setting) {
ViewParent parent = view.getParent();
if (parent instanceof ViewGroup parentGroup) {
parentGroup.removeView(view);
@@ -311,13 +278,12 @@ public class Utils {
* @return zero, if the resource is not found.
*/
@SuppressLint("DiscouragedApi")
public static int getResourceIdentifier(Context context, @Nullable ResourceType type, String resourceIdentifierName) {
return context.getResources().getIdentifier(resourceIdentifierName,
type == null ? null : type.value, context.getPackageName());
public static int getResourceIdentifier(Context context, String resourceIdentifierName, @Nullable String type) {
return context.getResources().getIdentifier(resourceIdentifierName, type, context.getPackageName());
}
public static int getResourceIdentifierOrThrow(Context context, @Nullable ResourceType type, String resourceIdentifierName) {
final int resourceId = getResourceIdentifier(context, type, resourceIdentifierName);
public static int getResourceIdentifierOrThrow(Context context, String resourceIdentifierName, @Nullable String type) {
final int resourceId = getResourceIdentifier(context, resourceIdentifierName, type);
if (resourceId == 0) {
throw new Resources.NotFoundException("No resource id exists with name: " + resourceIdentifierName
+ " type: " + type);
@@ -327,44 +293,48 @@ public class Utils {
/**
* @return zero, if the resource is not found.
* @see #getResourceIdentifierOrThrow(ResourceType, String)
* @see #getResourceIdentifierOrThrow(String, String)
*/
public static int getResourceIdentifier(@Nullable ResourceType type, String resourceIdentifierName) {
return getResourceIdentifier(getContext(), type, resourceIdentifierName);
public static int getResourceIdentifier(String resourceIdentifierName, @Nullable String type) {
return getResourceIdentifier(getContext(), resourceIdentifierName, type);
}
/**
* @return zero, if the resource is not found.
* @see #getResourceIdentifier(ResourceType, String)
* @return The resource identifier, or throws an exception if not found.
*/
public static int getResourceIdentifierOrThrow(@Nullable ResourceType type, String resourceIdentifierName) {
return getResourceIdentifierOrThrow(getContext(), type, resourceIdentifierName);
public static int getResourceIdentifierOrThrow(String resourceIdentifierName, @Nullable String type) {
final int resourceId = getResourceIdentifier(getContext(), resourceIdentifierName, type);
if (resourceId == 0) {
throw new Resources.NotFoundException("No resource id exists with name: " + resourceIdentifierName
+ " type: " + type);
}
return resourceId;
}
public static int getResourceInteger(String resourceIdentifierName) throws Resources.NotFoundException {
return getContext().getResources().getInteger(getResourceIdentifierOrThrow(ResourceType.INTEGER, resourceIdentifierName));
return getContext().getResources().getInteger(getResourceIdentifierOrThrow(resourceIdentifierName, "integer"));
}
public static Animation getResourceAnimation(String resourceIdentifierName) throws Resources.NotFoundException {
return AnimationUtils.loadAnimation(getContext(), getResourceIdentifierOrThrow(ResourceType.ANIM, resourceIdentifierName));
return AnimationUtils.loadAnimation(getContext(), getResourceIdentifierOrThrow(resourceIdentifierName, "anim"));
}
@ColorInt
public static int getResourceColor(String resourceIdentifierName) throws Resources.NotFoundException {
//noinspection deprecation
return getContext().getResources().getColor(getResourceIdentifierOrThrow(ResourceType.COLOR, resourceIdentifierName));
return getContext().getResources().getColor(getResourceIdentifierOrThrow(resourceIdentifierName, "color"));
}
public static int getResourceDimensionPixelSize(String resourceIdentifierName) throws Resources.NotFoundException {
return getContext().getResources().getDimensionPixelSize(getResourceIdentifierOrThrow(ResourceType.DIMEN, resourceIdentifierName));
return getContext().getResources().getDimensionPixelSize(getResourceIdentifierOrThrow(resourceIdentifierName, "dimen"));
}
public static float getResourceDimension(String resourceIdentifierName) throws Resources.NotFoundException {
return getContext().getResources().getDimension(getResourceIdentifierOrThrow(ResourceType.DIMEN, resourceIdentifierName));
return getContext().getResources().getDimension(getResourceIdentifierOrThrow(resourceIdentifierName, "dimen"));
}
public static String[] getResourceStringArray(String resourceIdentifierName) throws Resources.NotFoundException {
return getContext().getResources().getStringArray(getResourceIdentifierOrThrow(ResourceType.ARRAY, resourceIdentifierName));
return getContext().getResources().getStringArray(getResourceIdentifierOrThrow(resourceIdentifierName, "array"));
}
public interface MatchFilter<T> {
@@ -375,7 +345,7 @@ public class Utils {
* Includes sub children.
*/
public static <R extends View> R getChildViewByResourceName(View view, String str) {
var child = view.findViewById(Utils.getResourceIdentifierOrThrow(ResourceType.ID, str));
var child = view.findViewById(Utils.getResourceIdentifierOrThrow(str, "id"));
//noinspection unchecked
return (R) child;
}
@@ -832,21 +802,6 @@ public class Utils {
window.setBackgroundDrawable(null); // Remove default dialog background
}
/**
* @return If the unpatched app is currently using bold icons.
*/
public static boolean appIsUsingBoldIcons() {
return appIsUsingBoldIcons;
}
/**
* Controls if ReVanced bold icons are shown in various places.
* @param boldIcons If the app is currently using bold icons.
*/
public static void setAppIsUsingBoldIcons(boolean boldIcons) {
appIsUsingBoldIcons = boldIcons;
}
/**
* Sets the theme light color used by the app.
*/
@@ -1208,18 +1163,4 @@ public class Utils {
public static float clamp(float value, float lower, float upper) {
return Math.max(lower, Math.min(value, upper));
}
/**
* @param maxSize The maximum number of elements to keep in the map.
* @return A {@link LinkedHashMap} that automatically evicts the oldest entry
* when the size exceeds {@code maxSize}.
*/
public static <T, V> Map<T, V> createSizeRestrictedMap(int maxSize) {
return new LinkedHashMap<>(2 * maxSize) {
@Override
protected boolean removeEldestEntry(Entry eldest) {
return size() > maxSize;
}
};
}
}

View File

@@ -23,7 +23,6 @@ import androidx.annotation.Nullable;
import java.util.Collection;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.ui.CustomDialog;
@@ -129,7 +128,7 @@ abstract class Check {
// Add icon to the dialog.
ImageView iconView = new ImageView(activity);
iconView.setImageResource(Utils.getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_ic_dialog_alert"));
"revanced_ic_dialog_alert", "drawable"));
iconView.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
iconView.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(

View File

@@ -15,6 +15,7 @@ import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public abstract class BaseFixRedgifsApiPatch implements Interceptor {
protected static BaseFixRedgifsApiPatch INSTANCE;
public abstract String getDefaultUserAgent();

View File

@@ -13,7 +13,6 @@ import java.util.Locale;
import app.revanced.extension.shared.GmsCoreSupport;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
@@ -66,7 +65,7 @@ public class CustomBrandingPatch {
iconName += "_custom";
}
notificationSmallIcon = Utils.getResourceIdentifier(ResourceType.DRAWABLE, iconName);
notificationSmallIcon = Utils.getResourceIdentifier(iconName, "drawable");
if (notificationSmallIcon == 0) {
Logger.printException(() -> "Could not load notification small icon");
}

View File

@@ -13,7 +13,6 @@ import android.widget.TextView;
import android.widget.Toolbar;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
import app.revanced.extension.shared.ui.Dim;
@@ -26,13 +25,13 @@ import app.revanced.extension.shared.ui.Dim;
public abstract class BaseActivityHook extends Activity {
private static final int ID_REVANCED_SETTINGS_FRAGMENTS =
getResourceIdentifierOrThrow(ResourceType.ID, "revanced_settings_fragments");
getResourceIdentifierOrThrow("revanced_settings_fragments", "id");
private static final int ID_REVANCED_TOOLBAR_PARENT =
getResourceIdentifierOrThrow(ResourceType.ID, "revanced_toolbar_parent");
getResourceIdentifierOrThrow("revanced_toolbar_parent", "id");
public static final int LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR =
getResourceIdentifierOrThrow(ResourceType.LAYOUT, "revanced_settings_with_toolbar");
getResourceIdentifierOrThrow("revanced_settings_with_toolbar", "layout");
private static final int STRING_REVANCED_SETTINGS_TITLE =
getResourceIdentifierOrThrow(ResourceType.STRING, "revanced_settings_title");
getResourceIdentifierOrThrow("revanced_settings_title", "string");
/**
* Layout parameters for the toolbar, extracted from the dummy toolbar.
@@ -124,18 +123,16 @@ public abstract class BaseActivityHook extends Activity {
toolBarParent.addView(toolbar, 0);
}
/**
* Returns the resource ID for the content view layout.
*/
protected int getContentViewResourceId() {
return LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR;
}
/**
* Customizes the activity's theme.
*/
protected abstract void customizeActivityTheme(Activity activity);
/**
* Returns the resource ID for the content view layout.
*/
protected abstract int getContentViewResourceId();
/**
* Returns the background color for the toolbar.
*/

View File

@@ -5,8 +5,6 @@ import static java.lang.Boolean.TRUE;
import static app.revanced.extension.shared.patches.CustomBrandingPatch.BrandingTheme;
import static app.revanced.extension.shared.settings.Setting.parent;
import app.revanced.extension.shared.Logger;
/**
* Settings shared across multiple apps.
* <p>
@@ -26,19 +24,10 @@ public class BaseSettings {
* Use the icons declared in the preferences created during patching. If no icons or styles are declared then this setting does nothing.
*/
public static final BooleanSetting SHOW_MENU_ICONS = new BooleanSetting("revanced_show_menu_icons", TRUE, true);
/**
* Do not use this setting directly. Instead use {@link app.revanced.extension.shared.Utils#appIsUsingBoldIcons()}
*/
public static final BooleanSetting SETTINGS_DISABLE_BOLD_ICONS = new BooleanSetting("revanced_settings_disable_bold_icons", FALSE, true);
public static final BooleanSetting SETTINGS_SEARCH_HISTORY = new BooleanSetting("revanced_settings_search_history", TRUE, true);
public static final StringSetting SETTINGS_SEARCH_ENTRIES = new StringSetting("revanced_settings_search_entries", "");
/**
* The first time the app was launched with no previous app data (either a clean install, or after wiping app data).
*/
public static final LongSetting FIRST_TIME_APP_LAUNCHED = new LongSetting("revanced_last_time_app_was_launched", -1L, false, false);
//
// Settings shared by YouTube and YouTube Music.
//
@@ -55,13 +44,4 @@ public class BaseSettings {
public static final IntegerSetting CUSTOM_BRANDING_NAME = new IntegerSetting("revanced_custom_branding_name", 1, true);
public static final StringSetting DISABLED_FEATURE_FLAGS = new StringSetting("revanced_disabled_feature_flags", "", true, parent(DEBUG));
static {
final long now = System.currentTimeMillis();
if (FIRST_TIME_APP_LAUNCHED.get() < 0) {
Logger.printInfo(() -> "First launch of installation with no prior app data");
FIRST_TIME_APP_LAUNCHED.save(now);
}
}
}

View File

@@ -23,7 +23,6 @@ import androidx.annotation.Nullable;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.BooleanSetting;
@@ -104,16 +103,10 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
* so all app specific {@link Setting} instances are loaded before this method returns.
*/
protected void initialize() {
String preferenceResourceName;
if (BaseSettings.SHOW_MENU_ICONS.get()) {
preferenceResourceName = Utils.appIsUsingBoldIcons()
? "revanced_prefs_icons_bold"
: "revanced_prefs_icons";
} else {
preferenceResourceName = "revanced_prefs";
}
final var identifier = Utils.getResourceIdentifier(ResourceType.XML, preferenceResourceName);
String preferenceResourceName = BaseSettings.SHOW_MENU_ICONS.get()
? "revanced_prefs_icons"
: "revanced_prefs";
final var identifier = Utils.getResourceIdentifier(preferenceResourceName, "xml");
if (identifier == 0) return;
addPreferencesFromResource(identifier);

View File

@@ -31,7 +31,6 @@ import java.util.Locale;
import java.util.regex.Pattern;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.StringSetting;
@@ -82,13 +81,13 @@ public class ColorPickerPreference extends EditTextPreference {
private boolean opacitySliderEnabled = false;
public static final int ID_REVANCED_COLOR_PICKER_VIEW =
getResourceIdentifierOrThrow(ResourceType.ID, "revanced_color_picker_view");
getResourceIdentifierOrThrow("revanced_color_picker_view", "id");
public static final int ID_PREFERENCE_COLOR_DOT =
getResourceIdentifierOrThrow(ResourceType.ID, "preference_color_dot");
getResourceIdentifierOrThrow("preference_color_dot", "id");
public static final int LAYOUT_REVANCED_COLOR_DOT_WIDGET =
getResourceIdentifierOrThrow(ResourceType.LAYOUT, "revanced_color_dot_widget");
getResourceIdentifierOrThrow("revanced_color_dot_widget", "layout");
public static final int LAYOUT_REVANCED_COLOR_PICKER =
getResourceIdentifierOrThrow(ResourceType.LAYOUT, "revanced_color_picker");
getResourceIdentifierOrThrow("revanced_color_picker", "layout");
/**
* Removes non valid hex characters, converts to all uppercase,

View File

@@ -20,7 +20,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.CustomDialog;
@@ -31,18 +30,14 @@ import app.revanced.extension.shared.ui.CustomDialog;
@SuppressWarnings({"unused", "deprecation"})
public class CustomDialogListPreference extends ListPreference {
public static final int ID_REVANCED_CHECK_ICON = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_check_icon");
public static final int ID_REVANCED_CHECK_ICON_PLACEHOLDER = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_check_icon_placeholder");
public static final int ID_REVANCED_ITEM_TEXT = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_item_text");
public static final int LAYOUT_REVANCED_CUSTOM_LIST_ITEM_CHECKED = getResourceIdentifierOrThrow(
ResourceType.LAYOUT, "revanced_custom_list_item_checked");
public static final int DRAWABLE_CHECKMARK = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_custom_checkmark");
public static final int DRAWABLE_CHECKMARK_BOLD = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_custom_checkmark_bold");
public static final int ID_REVANCED_CHECK_ICON =
getResourceIdentifierOrThrow("revanced_check_icon", "id");
public static final int ID_REVANCED_CHECK_ICON_PLACEHOLDER =
getResourceIdentifierOrThrow("revanced_check_icon_placeholder", "id");
public static final int ID_REVANCED_ITEM_TEXT =
getResourceIdentifierOrThrow("revanced_item_text", "id");
public static final int LAYOUT_REVANCED_CUSTOM_LIST_ITEM_CHECKED =
getResourceIdentifierOrThrow("revanced_custom_list_item_checked", "layout");
private String staticSummary = null;
private CharSequence[] highlightedEntriesForDialog = null;
@@ -130,13 +125,9 @@ public class CustomDialogListPreference extends ListPreference {
LayoutInflater inflater = LayoutInflater.from(getContext());
view = inflater.inflate(layoutResourceId, parent, false);
holder = new SubViewDataContainer();
holder.checkIcon = view.findViewById(ID_REVANCED_CHECK_ICON);
holder.placeholder = view.findViewById(ID_REVANCED_CHECK_ICON_PLACEHOLDER);
holder.itemText = view.findViewById(ID_REVANCED_ITEM_TEXT);
holder.checkIcon = view.findViewById(ID_REVANCED_CHECK_ICON);
holder.checkIcon.setImageResource(Utils.appIsUsingBoldIcons()
? DRAWABLE_CHECKMARK_BOLD
: DRAWABLE_CHECKMARK
);
view.setTag(holder);
} else {
holder = (SubViewDataContainer) view.getTag();

View File

@@ -38,7 +38,6 @@ import java.util.Set;
import java.util.TreeSet;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.patches.EnableDebuggingPatch;
import app.revanced.extension.shared.settings.BaseSettings;
@@ -53,26 +52,25 @@ import app.revanced.extension.shared.ui.Dim;
public class FeatureFlagsManagerPreference extends Preference {
private static final int DRAWABLE_REVANCED_SETTINGS_SELECT_ALL =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_select_all");
getResourceIdentifierOrThrow("revanced_settings_select_all", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_DESELECT_ALL =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_deselect_all");
getResourceIdentifierOrThrow("revanced_settings_deselect_all", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_COPY_ALL =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_copy_all");
getResourceIdentifierOrThrow("revanced_settings_copy_all", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_ONE =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_right_one");
getResourceIdentifierOrThrow("revanced_settings_arrow_right_one", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_DOUBLE =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_right_double");
getResourceIdentifierOrThrow("revanced_settings_arrow_right_double", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_ONE =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_left_one");
getResourceIdentifierOrThrow("revanced_settings_arrow_left_one", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_DOUBLE =
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_left_double");
getResourceIdentifierOrThrow("revanced_settings_arrow_left_double", "drawable");
/**
* Flags to hide from the UI.
*/
private static final Set<Long> FLAGS_TO_IGNORE = Set.of(
45386834L, // 'You' tab settings icon.
45685201L // Bold icons. Forcing off interferes with patch changes and YT icons are broken.
45386834L // 'You' tab settings icon.
);
/**

View File

@@ -17,11 +17,9 @@ import android.widget.Toolbar;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.shared.settings.BaseSettings;
@SuppressWarnings({"deprecation", "NewApi"})
public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
@@ -135,10 +133,8 @@ public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
*/
@SuppressLint("UseCompatLoadingForDrawables")
public static Drawable getBackButtonDrawable() {
final int backButtonResource = Utils.getResourceIdentifierOrThrow(ResourceType.DRAWABLE,
Utils.appIsUsingBoldIcons()
? "revanced_settings_toolbar_arrow_left_bold"
: "revanced_settings_toolbar_arrow_left");
final int backButtonResource = Utils.getResourceIdentifierOrThrow(
"revanced_settings_toolbar_arrow_left", "drawable");
Drawable drawable = Utils.getContext().getResources().getDrawable(backButtonResource);
customizeBackButtonDrawable(drawable);
return drawable;

View File

@@ -16,7 +16,6 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
@@ -39,18 +38,18 @@ public abstract class BaseSearchResultItem {
// Get the corresponding layout resource ID.
public int getLayoutResourceId() {
return switch (this) {
case REGULAR, URL_LINK -> getResourceIdentifier("revanced_preference_search_result_regular");
case SWITCH -> getResourceIdentifier("revanced_preference_search_result_switch");
case LIST -> getResourceIdentifier("revanced_preference_search_result_list");
case COLOR_PICKER -> getResourceIdentifier("revanced_preference_search_result_color");
case GROUP_HEADER -> getResourceIdentifier("revanced_preference_search_result_group_header");
case NO_RESULTS -> getResourceIdentifier("revanced_preference_search_no_result");
case REGULAR, URL_LINK -> getResourceIdentifier("revanced_preference_search_result_regular");
case SWITCH -> getResourceIdentifier("revanced_preference_search_result_switch");
case LIST -> getResourceIdentifier("revanced_preference_search_result_list");
case COLOR_PICKER -> getResourceIdentifier("revanced_preference_search_result_color");
case GROUP_HEADER -> getResourceIdentifier("revanced_preference_search_result_group_header");
case NO_RESULTS -> getResourceIdentifier("revanced_preference_search_no_result");
};
}
private static int getResourceIdentifier(String name) {
// Placeholder for actual resource identifier retrieval.
return Utils.getResourceIdentifierOrThrow(ResourceType.LAYOUT, name);
return Utils.getResourceIdentifierOrThrow(name, "layout");
}
}

View File

@@ -1,6 +1,7 @@
package app.revanced.extension.shared.settings.search;
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
import static app.revanced.extension.shared.settings.search.BaseSearchViewController.DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
@@ -32,7 +33,6 @@ import java.lang.reflect.Method;
import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
@@ -54,15 +54,15 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
protected static final int PAUSE_BETWEEN_BLINKS = 100;
protected static final int ID_PREFERENCE_TITLE = getResourceIdentifierOrThrow(
ResourceType.ID, "preference_title");
"preference_title", "id");
protected static final int ID_PREFERENCE_SUMMARY = getResourceIdentifierOrThrow(
ResourceType.ID, "preference_summary");
"preference_summary", "id");
protected static final int ID_PREFERENCE_PATH = getResourceIdentifierOrThrow(
ResourceType.ID, "preference_path");
"preference_path", "id");
protected static final int ID_PREFERENCE_SWITCH = getResourceIdentifierOrThrow(
ResourceType.ID, "preference_switch");
"preference_switch", "id");
protected static final int ID_PREFERENCE_COLOR_DOT = getResourceIdentifierOrThrow(
ResourceType.ID, "preference_color_dot");
"preference_color_dot", "id");
protected static class RegularViewHolder {
TextView titleView;
@@ -275,7 +275,7 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
holder.titleView.setText(item.highlightedTitle);
holder.summaryView.setText(item.highlightedSummary);
holder.summaryView.setVisibility(TextUtils.isEmpty(item.highlightedSummary) ? View.GONE : View.VISIBLE);
holder.iconView.setImageResource(BaseSearchViewController.getSearchIcon());
holder.iconView.setImageResource(DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON);
}
/**

View File

@@ -14,7 +14,6 @@ import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
@@ -38,7 +37,6 @@ import java.util.Set;
import java.util.regex.Pattern;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
@@ -72,29 +70,14 @@ public abstract class BaseSearchViewController {
protected static final int MAX_SEARCH_RESULTS = 50; // Maximum number of search results displayed.
protected static final int ID_REVANCED_SEARCH_VIEW = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_search_view");
protected static final int ID_REVANCED_SEARCH_VIEW_CONTAINER = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_search_view_container");
protected static final int ID_ACTION_SEARCH = getResourceIdentifierOrThrow(
ResourceType.ID, "action_search");
protected static final int ID_REVANCED_SETTINGS_FRAGMENTS = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_settings_fragments");
private static final int DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_search_icon");
private static final int DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON_BOLD = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_search_icon_bold");
protected static final int MENU_REVANCED_SEARCH_MENU = getResourceIdentifierOrThrow(
ResourceType.MENU, "revanced_search_menu");
/**
* @return The search icon, either bold or not bold, depending on the ReVanced UI setting.
*/
public static int getSearchIcon() {
return Utils.appIsUsingBoldIcons()
? DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON_BOLD
: DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON;
}
protected static final int ID_REVANCED_SEARCH_VIEW = getResourceIdentifierOrThrow("revanced_search_view", "id");
protected static final int ID_REVANCED_SEARCH_VIEW_CONTAINER = getResourceIdentifierOrThrow("revanced_search_view_container", "id");
protected static final int ID_ACTION_SEARCH = getResourceIdentifierOrThrow("action_search", "id");
protected static final int ID_REVANCED_SETTINGS_FRAGMENTS = getResourceIdentifierOrThrow("revanced_settings_fragments", "id");
public static final int DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON =
getResourceIdentifierOrThrow("revanced_settings_search_icon", "drawable");
protected static final int MENU_REVANCED_SEARCH_MENU =
getResourceIdentifierOrThrow("revanced_search_menu", "menu");
/**
* Constructs a new BaseSearchViewController instance.
@@ -129,7 +112,7 @@ public abstract class BaseSearchViewController {
// Retrieve SearchView and container from XML.
searchView = activity.findViewById(ID_REVANCED_SEARCH_VIEW);
EditText searchEditText = searchView.findViewById(Utils.getResourceIdentifierOrThrow(
null, "android:id/search_src_text"));
"android:id/search_src_text", null));
// Disable fullscreen keyboard mode.
searchEditText.setImeOptions(searchEditText.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
@@ -265,10 +248,6 @@ public abstract class BaseSearchViewController {
}
return false;
});
// Set bold icon if needed.
MenuItem search = toolbar.getMenu().findItem(ID_ACTION_SEARCH);
search.setIcon(getSearchIcon());
}
/**
@@ -545,7 +524,7 @@ public abstract class BaseSearchViewController {
noResultsPreference.setTitle(str("revanced_settings_search_no_results_title", query));
noResultsPreference.setSummary(str("revanced_settings_search_no_results_summary"));
noResultsPreference.setSelectable(false);
noResultsPreference.setIcon(getSearchIcon());
noResultsPreference.setIcon(DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON);
filteredSearchItems.add(new BaseSearchResultItem.PreferenceSearchItem(noResultsPreference, "", Collections.emptyList()));
}

View File

@@ -24,8 +24,6 @@ import java.util.Deque;
import java.util.LinkedList;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.BulletPointPreference;
import app.revanced.extension.shared.ui.CustomDialog;
@@ -39,35 +37,25 @@ public class SearchHistoryManager {
private static final int MAX_HISTORY_SIZE = 5; // Maximum history items stored.
private static final int ID_CLEAR_HISTORY_BUTTON = getResourceIdentifierOrThrow(
ResourceType.ID, "clear_history_button");
"clear_history_button", "id");
private static final int ID_HISTORY_TEXT = getResourceIdentifierOrThrow(
ResourceType.ID, "history_text");
private static final int ID_HISTORY_ICON = getResourceIdentifierOrThrow(
ResourceType.ID, "history_icon");
"history_text", "id");
private static final int ID_DELETE_ICON = getResourceIdentifierOrThrow(
ResourceType.ID, "delete_icon");
"delete_icon", "id");
private static final int ID_EMPTY_HISTORY_TITLE = getResourceIdentifierOrThrow(
ResourceType.ID, "empty_history_title");
"empty_history_title", "id");
private static final int ID_EMPTY_HISTORY_SUMMARY = getResourceIdentifierOrThrow(
ResourceType.ID, "empty_history_summary");
"empty_history_summary", "id");
private static final int ID_SEARCH_HISTORY_HEADER = getResourceIdentifierOrThrow(
ResourceType.ID, "search_history_header");
"search_history_header", "id");
private static final int ID_SEARCH_TIPS_SUMMARY = getResourceIdentifierOrThrow(
ResourceType.ID, "revanced_settings_search_tips_summary");
"revanced_settings_search_tips_summary", "id");
private static final int LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_SCREEN = getResourceIdentifierOrThrow(
ResourceType.LAYOUT, "revanced_preference_search_history_screen");
"revanced_preference_search_history_screen", "layout");
private static final int LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_ITEM = getResourceIdentifierOrThrow(
ResourceType.LAYOUT, "revanced_preference_search_history_item");
"revanced_preference_search_history_item", "layout");
private static final int ID_SEARCH_HISTORY_LIST = getResourceIdentifierOrThrow(
ResourceType.ID, "search_history_list");
private static final int ID_SEARCH_REMOVE_ICON = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_search_remove");
private static final int ID_SEARCH_REMOVE_ICON_BOLD = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_search_remove_bold");
private static final int ID_SEARCH_ARROW_TIME_ICON = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_arrow_time");
private static final int ID_SEARCH_ARROW_TIME_ICON_BOLD = getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_settings_arrow_time_bold");
"search_history_list", "id");
private final Deque<String> searchHistory;
private final Activity activity;
@@ -109,8 +97,7 @@ public class SearchHistoryManager {
// Inflate search history layout.
LayoutInflater inflater = LayoutInflater.from(activity);
View historyView = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_SCREEN,
searchHistoryContainer, false);
View historyView = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_SCREEN, searchHistoryContainer, false);
searchHistoryContainer.addView(historyView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT));
@@ -333,29 +320,17 @@ public class SearchHistoryManager {
public void notifyDataSetChanged() {
container.removeAllViews();
for (String query : history) {
View view = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_ITEM,
container, false);
View view = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_ITEM, container, false);
TextView historyText = view.findViewById(ID_HISTORY_TEXT);
ImageView deleteIcon = view.findViewById(ID_DELETE_ICON);
historyText.setText(query);
// Set click listener for main item (select query).
view.setOnClickListener(v -> onSelectHistoryItemListener.onSelectHistoryItem(query));
// Set history icon.
ImageView historyIcon = view.findViewById(ID_HISTORY_ICON);
historyIcon.setImageResource(Utils.appIsUsingBoldIcons()
? ID_SEARCH_ARROW_TIME_ICON_BOLD
: ID_SEARCH_ARROW_TIME_ICON
);
TextView historyText = view.findViewById(ID_HISTORY_TEXT);
historyText.setText(query);
// Set click listener for delete icon.
ImageView deleteIcon = view.findViewById(ID_DELETE_ICON);
deleteIcon.setImageResource(Utils.appIsUsingBoldIcons()
? ID_SEARCH_REMOVE_ICON_BOLD
: ID_SEARCH_REMOVE_ICON
);
deleteIcon.setOnClickListener(v -> createAndShowDialog(
query,
str("revanced_settings_search_remove_message"),

View File

@@ -16,6 +16,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -82,15 +83,22 @@ public class StreamingDataRequest {
*/
private static final int MAX_MILLISECONDS_TO_WAIT_FOR_FETCH = 20 * 1000;
/**
* Cache limit must be greater than the maximum number of videos open at once,
* which theoretically is more than 4 (3 Shorts + one regular minimized video).
* But instead use a much larger value, to handle if a video viewed a while ago
* is somehow still referenced. Each stream is a small array of Strings
* so memory usage is not a concern.
*/
private static final Map<String, StreamingDataRequest> cache = Collections.synchronizedMap(
Utils.createSizeRestrictedMap(50));
new LinkedHashMap<>(100) {
/**
* Cache limit must be greater than the maximum number of videos open at once,
* which theoretically is more than 4 (3 Shorts + one regular minimized video).
* But instead use a much larger value, to handle if a video viewed a while ago
* is somehow still referenced. Each stream is a small array of Strings
* so memory usage is not a concern.
*/
private static final int CACHE_LIMIT = 50;
@Override
protected boolean removeEldestEntry(Entry eldest) {
return size() > CACHE_LIMIT; // Evict the oldest entry if over the cache limit.
}
});
/**
* Strings found in the response if the video is a livestream.

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.spotify.layout.hide.createbutton;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.spotify.shared.ComponentFilters.ComponentFilter;
import app.revanced.extension.spotify.shared.ComponentFilters.ResourceIdComponentFilter;
import app.revanced.extension.spotify.shared.ComponentFilters.StringComponentFilter;
@@ -17,7 +16,7 @@ public final class HideCreateButtonPatch {
* The main approach used is matching the resource id for the Create button title.
*/
private static final List<ComponentFilter> CREATE_BUTTON_COMPONENT_FILTERS = List.of(
new ResourceIdComponentFilter(ResourceType.STRING, "navigationbar_musicappitems_create_title"),
new ResourceIdComponentFilter("navigationbar_musicappitems_create_title", "string"),
// Temporary fallback and fix for APKs merged with AntiSplit-M not having resources properly encoded,
// and thus getting the resource identifier for the Create button title always return 0.
// FIXME: Remove this once the above issue is no longer relevant.
@@ -29,7 +28,7 @@ public final class HideCreateButtonPatch {
* Used in older versions of the app.
*/
private static final ResourceIdComponentFilter OLD_CREATE_BUTTON_COMPONENT_FILTER =
new ResourceIdComponentFilter(ResourceType.STRING, "bottom_navigation_bar_create_tab_title");
new ResourceIdComponentFilter("bottom_navigation_bar_create_tab_title", "string");
/**
* Injection point. This method is called on every navigation bar item to check whether it is the Create button.

View File

@@ -3,7 +3,6 @@ package app.revanced.extension.spotify.shared;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
public final class ComponentFilters {
@@ -20,26 +19,21 @@ public final class ComponentFilters {
public static final class ResourceIdComponentFilter implements ComponentFilter {
public final String resourceName;
public final ResourceType resourceType;
public final String resourceType;
// Android resources are always positive, so -1 is a valid sentinel value to indicate it has not been loaded.
// 0 is returned when a resource has not been found.
private int resourceId = -1;
@Nullable
private String stringfiedResourceId;
@Deprecated
public ResourceIdComponentFilter(String resourceName, String resourceType) {
this(ResourceType.valueOf(resourceType), resourceName);
}
public ResourceIdComponentFilter(ResourceType resourceType, String resourceName) {
this.resourceName = resourceName;
this.resourceType = resourceType;
}
public int getResourceId() {
if (resourceId == -1) {
resourceId = Utils.getResourceIdentifier(resourceType, resourceName);
resourceId = Utils.getResourceIdentifier(resourceName, resourceType);
}
return resourceId;
}

View File

@@ -1,18 +1,14 @@
package app.revanced.extension.twitch;
import app.revanced.extension.shared.ResourceType;
public class Utils {
/* Called from SettingsPatch smali */
public static int getStringId(String name) {
return app.revanced.extension.shared.Utils.getResourceIdentifier(
ResourceType.STRING, name);
return app.revanced.extension.shared.Utils.getResourceIdentifier(name, "string");
}
/* Called from SettingsPatch smali */
public static int getDrawableId(String name) {
return app.revanced.extension.shared.Utils.getResourceIdentifier(
ResourceType.DRAWABLE, name);
return app.revanced.extension.shared.Utils.getResourceIdentifier(name, "drawable");
}
}

View File

@@ -4,21 +4,19 @@ import static app.revanced.extension.twitch.Utils.getStringId;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.twitch.settings.preference.TwitchPreferenceFragment;
import tv.twitch.android.feature.settings.menu.SettingsMenuGroup;
import tv.twitch.android.settings.SettingsActivity;
import java.util.ArrayList;
import java.util.List;
/**
* Hooks AppCompatActivity to inject a custom {@link TwitchPreferenceFragment}.
*/
@@ -110,7 +108,7 @@ public class TwitchActivityHook {
base.getFragmentManager()
.beginTransaction()
.replace(Utils.getResourceIdentifier(ResourceType.ID, "fragment_container"), fragment)
.replace(Utils.getResourceIdentifier("fragment_container", "id"), fragment)
.commit();
return true;
}

View File

@@ -528,8 +528,14 @@ public final class AlternativeThumbnailsPatch {
* Cache used to verify if an alternative thumbnails exists for a given video id.
*/
@GuardedBy("itself")
private static final Map<String, VerifiedQualities> altVideoIdLookup =
Utils.createSizeRestrictedMap(1000);
private static final Map<String, VerifiedQualities> altVideoIdLookup = new LinkedHashMap<>(100) {
private static final int CACHE_LIMIT = 1000;
@Override
protected boolean removeEldestEntry(Entry eldest) {
return size() > CACHE_LIMIT; // Evict the oldest entry if over the cache limit.
}
};
private static VerifiedQualities getVerifiedQualities(@NonNull String videoId, boolean returnNullIfDoesNotExist) {
synchronized (altVideoIdLookup) {

View File

@@ -7,7 +7,6 @@ import androidx.annotation.Nullable;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
@@ -51,7 +50,7 @@ public class ChangeHeaderPatch {
return null;
}
final int identifier = Utils.getResourceIdentifier(ResourceType.ATTR, attributeName);
final int identifier = Utils.getResourceIdentifier(attributeName, "attr");
if (identifier == 0) {
// Should never happen.
Logger.printException(() -> "Could not find attribute: " + drawableName);
@@ -72,7 +71,7 @@ public class ChangeHeaderPatch {
? "_dark"
: "_light");
final int identifier = Utils.getResourceIdentifier(ResourceType.DRAWABLE, drawableFullName);
final int identifier = Utils.getResourceIdentifier(drawableFullName, "drawable");
if (identifier != 0) {
return Utils.getContext().getDrawable(identifier);
}

View File

@@ -21,7 +21,7 @@ public final class DownloadsPatch {
/**
* Injection point.
*/
public static void setMainActivity(Activity mainActivity) {
public static void activityCreated(Activity mainActivity) {
activityRef = new WeakReference<>(mainActivity);
}

View File

@@ -1,24 +0,0 @@
package app.revanced.extension.youtube.patches;
import java.util.Map;
import app.revanced.extension.shared.Logger;
@SuppressWarnings("unused")
public class FixContentProviderPatch {
/**
* Injection point.
*/
public static void removeNullMapEntries(Map<?, ?> map) {
map.entrySet().removeIf(entry -> {
Object value = entry.getValue();
if (value == null) {
Logger.printDebug(() -> "Removing content provider key with null value: " + entry.getKey());
return true;
}
return false;
});
}
}

View File

@@ -7,7 +7,6 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
@@ -30,15 +29,6 @@ public final class HidePlayerOverlayButtonsPatch {
return Settings.HIDE_CAST_BUTTON.get() ? View.GONE : original;
}
/**
* Injection point.
*/
public static boolean getCastButtonOverrideV2(boolean original) {
if (Settings.HIDE_CAST_BUTTON.get()) return false;
return original;
}
/**
* Injection point.
*/
@@ -50,10 +40,10 @@ public final class HidePlayerOverlayButtonsPatch {
= Settings.HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS.get();
private static final int PLAYER_CONTROL_PREVIOUS_BUTTON_TOUCH_AREA_ID = getResourceIdentifierOrThrow(
ResourceType.ID, "player_control_previous_button_touch_area");
"player_control_previous_button_touch_area", "id");
private static final int PLAYER_CONTROL_NEXT_BUTTON_TOUCH_AREA_ID = getResourceIdentifierOrThrow(
ResourceType.ID, "player_control_next_button_touch_area");
"player_control_next_button_touch_area", "id");
/**
* Injection point.

View File

@@ -4,17 +4,7 @@ import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
public class HideSeekbarPatch {
/**
* Injection point.
*/
public static boolean hideSeekbar() {
return Settings.HIDE_SEEKBAR.get();
}
/**
* Injection point.
*/
public static boolean useFullscreenLargeSeekbar(boolean original) {
return Settings.FULLSCREEN_LARGE_SEEKBAR.get();
}
}

View File

@@ -15,7 +15,6 @@ import androidx.annotation.Nullable;
import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.youtube.settings.Settings;
@@ -116,7 +115,7 @@ public final class MiniplayerPatch {
* Resource is not present in older targets, and this field will be zero.
*/
private static final int MODERN_OVERLAY_SUBTITLE_TEXT
= Utils.getResourceIdentifier(ResourceType.ID, "modern_miniplayer_subtitle_text");
= Utils.getResourceIdentifier("modern_miniplayer_subtitle_text", "id");
private static final MiniplayerType CURRENT_TYPE = Settings.MINIPLAYER_TYPE.get();
@@ -379,19 +378,6 @@ public final class MiniplayerPatch {
return original;
}
/**
* Injection point.
*/
public static boolean allowBoldIcons(boolean original) {
if (CURRENT_TYPE == MINIMAL) {
// Minimal player does not have the correct pause/play icon (it's too large).
// Use the non bold icons instead.
return false;
}
return original;
}
/**
* Injection point.
*/

View File

@@ -5,11 +5,12 @@ import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButt
import android.os.Build;
import android.view.View;
import android.widget.TextView;
import java.util.EnumMap;
import java.util.Map;
import android.widget.TextView;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
@@ -29,13 +30,13 @@ public final class NavigationButtonsPatch {
private static final boolean SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON
= Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get();
private static final boolean DISABLE_TRANSLUCENT_STATUS_BAR
private static final Boolean DISABLE_TRANSLUCENT_STATUS_BAR
= Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get();
private static final boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT
private static final Boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT.get();
private static final boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
private static final Boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK.get();
/**
@@ -61,13 +62,6 @@ public final class NavigationButtonsPatch {
hideViewUnderCondition(Settings.HIDE_NAVIGATION_BUTTON_LABELS, navigationLabelsView);
}
/**
* Injection point.
*/
public static boolean useAnimatedNavigationButtons(boolean original) {
return Settings.NAVIGATION_BAR_ANIMATIONS.get();
}
/**
* Injection point.
*/

View File

@@ -20,6 +20,15 @@ public class OpenShortsInRegularPlayerPatch {
REGULAR_PLAYER_FULLSCREEN
}
static {
if (!VersionCheckPatch.IS_19_46_OR_GREATER
&& Settings.SHORTS_PLAYER_TYPE.get() == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN) {
// User imported newer settings to an older app target.
Logger.printInfo(() -> "Resetting " + Settings.SHORTS_PLAYER_TYPE);
Settings.SHORTS_PLAYER_TYPE.resetToDefault();
}
}
private static WeakReference<Activity> mainActivityRef = new WeakReference<>(null);
private static volatile boolean overrideBackPressToExit;

View File

@@ -24,20 +24,18 @@ public class OpenVideosFullscreenHookPatch {
/**
* Injection point.
*
* Returns negated value.
*/
public static boolean doNotOpenVideoFullscreenPortrait(boolean original) {
public static boolean openVideoFullscreenPortrait(boolean original) {
Boolean openFullscreen = openNextVideoFullscreen;
if (openFullscreen != null) {
openNextVideoFullscreen = null;
return !openFullscreen;
return openFullscreen;
}
if (!isFullScreenPatchIncluded()) {
return original;
}
return !Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
}
}

View File

@@ -42,7 +42,7 @@ public class PlayerControlsPatch {
Logger.printDebug(() -> "fullscreen button visibility: "
+ (visibility == View.VISIBLE ? "VISIBLE" :
visibility == View.GONE ? "GONE" : "INVISIBLE"));
visibility == View.GONE ? "GONE" : "INVISIBLE"));
fullscreenButtonVisibilityChanged(visibility == View.VISIBLE);
}

View File

@@ -1,29 +1,19 @@
package app.revanced.extension.youtube.patches;
import android.app.AlertDialog;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
/** @noinspection unused*/
public class RemoveViewerDiscretionDialogPatch {
/**
* Injection point.
*/
public static void confirmDialog(AlertDialog dialog) {
if (Settings.REMOVE_VIEWER_DISCRETION_DIALOG.get()) {
Logger.printDebug(() -> "Clicking alert dialog dismiss button");
final var button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
button.setSoundEffectsEnabled(false);
button.performClick();
if (!Settings.REMOVE_VIEWER_DISCRETION_DIALOG.get()) {
// Since the patch replaces the AlertDialog#show() method, we need to call the original method here.
dialog.show();
return;
}
// Since the patch replaces the AlertDialog#show() method, we need to call the original method here.
Logger.printDebug(() -> "Showing alert dialog");
dialog.show();
final var button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
button.setSoundEffectsEnabled(false);
button.performClick();
}
}

View File

@@ -13,11 +13,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Objects;
import java.util.Set;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilter;
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
import app.revanced.extension.youtube.settings.Settings;
@@ -133,10 +131,6 @@ public class ReturnYouTubeDislikePatch {
String conversionContextString = conversionContext.toString();
if (Settings.RYD_ENABLED.get()) { // FIXME: Remove this.
Logger.printDebug(() -> "RYD conversion context: " + conversionContext);
}
if (isRollingNumber && !conversionContextString.contains("video_action_bar.e")) {
return original;
}

View File

@@ -2,6 +2,8 @@ package app.revanced.extension.youtube.patches;
import android.app.Activity;
import androidx.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Objects;
@@ -76,7 +78,7 @@ public class ShortsAutoplayPatch {
/**
* Injection point.
*/
public static Enum<?> changeShortsRepeatBehavior(Enum<?> original) {
public static Enum<?> changeShortsRepeatBehavior(@Nullable Enum<?> original) {
try {
final boolean autoplay;
@@ -93,19 +95,19 @@ public class ShortsAutoplayPatch {
autoplay = Settings.SHORTS_AUTOPLAY.get();
}
Enum<?> overrideBehavior = (autoplay
final ShortsLoopBehavior behavior = autoplay
? ShortsLoopBehavior.SINGLE_PLAY
: ShortsLoopBehavior.REPEAT).ytEnumValue;
: ShortsLoopBehavior.REPEAT;
if (overrideBehavior != null) {
if (behavior.ytEnumValue != null) {
Logger.printDebug(() -> {
String name = (original == null ? "unknown (null)" : original.name());
return overrideBehavior == original
return behavior == original
? "Behavior setting is same as original. Using original: " + name
: "Changing Shorts repeat behavior from: " + name + " to: " + overrideBehavior.name();
: "Changing Shorts repeat behavior from: " + name + " to: " + behavior.name();
});
return overrideBehavior;
return behavior.ytEnumValue;
}
if (original == null) {
@@ -116,12 +118,13 @@ public class ShortsAutoplayPatch {
return unknown;
}
} catch (Exception ex) {
Logger.printException(() -> "changeShortsRepeatState failure", ex);
Logger.printException(() -> "changeShortsRepeatBehavior failure", ex);
}
return original;
}
/**
* Injection point.
*/

View File

@@ -19,12 +19,5 @@ public class VersionCheckPatch {
public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.00");
@Deprecated
public static final boolean IS_19_34_OR_GREATER = isVersionOrGreater("19.34.00");
public static final boolean IS_20_21_OR_GREATER = isVersionOrGreater("20.21.00");
public static final boolean IS_20_22_OR_GREATER = isVersionOrGreater("20.22.00");
public static final boolean IS_20_31_OR_GREATER = isVersionOrGreater("20.31.00");
public static final boolean IS_20_37_OR_GREATER = isVersionOrGreater("20.37.00");
public static final boolean IS_19_46_OR_GREATER = isVersionOrGreater("19.46.00");
}

View File

@@ -1,6 +1,5 @@
package app.revanced.extension.youtube.patches.components;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
@@ -39,6 +38,7 @@ final class ButtonsFilter extends Filter {
addPathCallbacks(
likeSubscribeGlow,
bufferFilterPathGroup,
new StringFilterGroup(
Settings.HIDE_LIKE_DISLIKE_BUTTON,
"|segmented_like_dislike_button"
@@ -57,12 +57,6 @@ final class ButtonsFilter extends Filter {
)
);
// FIXME: 20.22+ filtering of the action buttons doesn't work because
// the buffer is the same for all buttons.
if (!VersionCheckPatch.IS_20_22_OR_GREATER) {
addPathCallbacks(bufferFilterPathGroup);
}
bufferButtonsGroupList.addAll(
new ByteArrayFilterGroup(
Settings.HIDE_REPORT_BUTTON,
@@ -114,13 +108,11 @@ final class ButtonsFilter extends Filter {
}
private boolean isEveryFilterGroupEnabled() {
for (var group : pathCallbacks) {
for (var group : pathCallbacks)
if (!group.isEnabled()) return false;
}
for (var group : bufferButtonsGroupList) {
for (var group : bufferButtonsGroupList)
if (!group.isEnabled()) return false;
}
return true;
}

View File

@@ -1,6 +1,5 @@
package app.revanced.extension.youtube.patches.components;
import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_20_21_OR_GREATER;
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
import android.graphics.drawable.Drawable;
@@ -400,22 +399,20 @@ public final class LayoutComponentsFilter extends Filter {
* Injection point.
* Called from a different place then the other filters.
*/
public static boolean filterMixPlaylists(Object conversionContext, @Nullable byte[] buffer) {
// Edit: This hook may no longer be needed, and mix playlist filtering
// might be possible using the existing litho filters.
public static boolean filterMixPlaylists(Object conversionContext, @Nullable final byte[] bytes) {
try {
if (!Settings.HIDE_MIX_PLAYLISTS.get()) {
return false;
}
if (buffer == null) {
Logger.printDebug(() -> "buffer is null");
if (bytes == null) {
Logger.printDebug(() -> "bytes is null");
return false;
}
if (mixPlaylists.check(buffer).isFiltered()
if (mixPlaylists.check(bytes).isFiltered()
// Prevent hiding the description of some videos accidentally.
&& !mixPlaylistsBufferExceptions.check(buffer).isFiltered()
&& !mixPlaylistsBufferExceptions.check(bytes).isFiltered()
// Prevent playlist items being hidden, if a mix playlist is present in it.
// Check last since it requires creating a context string.
//
@@ -478,23 +475,11 @@ public final class LayoutComponentsFilter extends Filter {
: height;
}
private static final boolean HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED
= Settings.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS.get();
/**
* Injection point.
*/
public static void hideInRelatedVideos(View chipView) {
// Cannot use 0dp hide with later targets, otherwise the suggested videos
// can be shown in full screen mode.
// This behavior may also be present in earlier app targets.
if (IS_20_21_OR_GREATER) {
// FIXME: The filter bar is still briefly shown when dragging the suggested videos
// below the video player.
Utils.hideViewUnderCondition(HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED, chipView);
} else {
Utils.hideViewBy0dpUnderCondition(HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED, chipView);
}
Utils.hideViewBy0dpUnderCondition(Settings.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS, chipView);
}
private static final boolean HIDE_DOODLES_ENABLED = Settings.HIDE_DOODLES.get();
@@ -519,9 +504,7 @@ public final class LayoutComponentsFilter extends Filter {
&& NavigationBar.isSearchBarActive()
// Search bar can be active but behind the player.
&& !PlayerType.getCurrent().isMaximizedOrFullscreen()) {
// FIXME: "Show more" button is visible hidden,
// but an empty space remains that can be clicked.
Utils.hideViewBy0dp(view);
Utils.hideViewByLayoutParams(view);
}
}

View File

@@ -4,16 +4,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
@@ -78,15 +73,6 @@ public final class LithoFilterPatch {
}
}
/**
* Placeholder for actual filters.
*/
private static final class DummyFilter extends Filter { }
private static final Filter[] filters = new Filter[] {
new DummyFilter() // Replaced during patching, do not touch.
};
/**
* Litho layout fixed thread pool size override.
* <p>
@@ -104,50 +90,25 @@ public final class LithoFilterPatch {
private static final int LITHO_LAYOUT_THREAD_POOL_SIZE = 1;
/**
* 20.22+ cannot use the thread buffer, because frequently the buffer is not correct,
* especially for components that are recreated such as dragging off screen then back on screen.
* Instead, parse the identifier found near the start of the buffer and use that to
* identify the correct buffer to use when filtering.
* Placeholder for actual filters.
*/
private static final boolean EXTRACT_IDENTIFIER_FROM_BUFFER = VersionCheckPatch.IS_20_22_OR_GREATER;
private static final class DummyFilter extends Filter { }
/**
* Turns on additional logging, used for development purposes only.
*/
public static final boolean DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER = false;
private static final Filter[] filters = new Filter[] {
new DummyFilter() // Replaced patching, do not touch.
};
/**
* String suffix for components.
* Can be any of: ".eml", ".e-b", ".eml-js", "e-js-b"
*/
private static final String LITHO_COMPONENT_EXTENSION = ".e";
private static final byte[] LITHO_COMPONENT_EXTENSION_BYTES = LITHO_COMPONENT_EXTENSION.getBytes(StandardCharsets.US_ASCII);
private static final StringTrieSearch pathSearchTree = new StringTrieSearch();
private static final StringTrieSearch identifierSearchTree = new StringTrieSearch();
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
/**
* Because litho filtering is multi-threaded and the buffer is passed in from a different injection point,
* the buffer is saved to a ThreadLocal so each calling thread does not interfere with other threads.
* Used for 20.21 and lower.
*/
private static final ThreadLocal<byte[]> bufferThreadLocal = new ThreadLocal<>();
/**
* Identifier to protocol buffer mapping. Only used for 20.22+.
* Thread local is needed because filtering is multi-threaded and each thread can load
* a different component with the same identifier.
*/
private static final ThreadLocal<Map<String, byte[]>> identifierToBufferThread = new ThreadLocal<>();
/**
* Global shared buffer. Used only if the buffer is not found in the ThreadLocal.
*/
private static final Map<String, byte[]> identifierToBufferGlobal
= Collections.synchronizedMap(createIdentifierToBufferMap());
private static final StringTrieSearch pathSearchTree = new StringTrieSearch();
private static final StringTrieSearch identifierSearchTree = new StringTrieSearch();
static {
for (Filter filter : filters) {
filterUsingCallbacks(identifierSearchTree, filter,
@@ -199,107 +160,16 @@ public final class LithoFilterPatch {
}
}
private static Map<String, byte[]> createIdentifierToBufferMap() {
// It's unclear how many items should be cached. This is a guess.
return Utils.createSizeRestrictedMap(100);
}
/**
* Helper function that differs from {@link Character#isDigit(char)}
* as this only matches ascii and not unicode numbers.
*/
private static boolean isAsciiNumber(byte character) {
return '0' <= character && character <= '9';
}
private static boolean isAsciiLowerCaseLetter(byte character) {
return 'a' <= character && character <= 'z';
}
/**
* Injection point. Called off the main thread.
* Targets 20.22+
*/
public static void setProtoBuffer(byte[] buffer) {
if (DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER) {
StringBuilder builder = new StringBuilder();
LithoFilterParameters.findAsciiStrings(builder, buffer);
Logger.printDebug(() -> "New buffer: " + builder);
}
// Could use Boyer-Moore-Horspool since the string is ASCII and has a limited number of
// unique characters, but it seems to be slower since the extra overhead of checking the
// bad character array negates any performance gain of skipping a few extra subsearches.
int emlIndex = -1;
final int emlStringLength = LITHO_COMPONENT_EXTENSION_BYTES.length;
for (int i = 0, lastStartIndex = buffer.length - emlStringLength; i <= lastStartIndex; i++) {
boolean match = true;
for (int j = 0; j < emlStringLength; j++) {
if (buffer[i + j] != LITHO_COMPONENT_EXTENSION_BYTES[j]) {
match = false;
break;
}
}
if (match) {
emlIndex = i;
break;
}
}
if (emlIndex < 0) {
// Buffer is not used for creating a new litho component.
return;
}
int startIndex = emlIndex - 1;
while (startIndex > 0) {
final byte character = buffer[startIndex];
int startIndexFinal = startIndex;
if (isAsciiLowerCaseLetter(character) || isAsciiNumber(character) || character == '_') {
// Valid character for the first path element.
startIndex--;
} else {
startIndex++;
break;
}
}
// Strip away any numbers on the start of the identifier, which can
// be from random data in the buffer before the identifier starts.
while (true) {
final byte character = buffer[startIndex];
if (isAsciiNumber(character)) {
startIndex++;
} else {
break;
}
}
// Find the pipe character after the identifier.
int endIndex = -1;
for (int i = emlIndex, length = buffer.length; i < length; i++) {
if (buffer[i] == '|') {
endIndex = i;
break;
}
}
if (endIndex < 0) {
Logger.printException(() -> "Could not find buffer identifier");
return;
}
String identifier = new String(buffer, startIndex, endIndex - startIndex, StandardCharsets.US_ASCII);
if (DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER) {
Logger.printDebug(() -> "Found buffer for identifier: " + identifier);
}
identifierToBufferGlobal.put(identifier, buffer);
Map<String, byte[]> map = identifierToBufferThread.get();
if (map == null) {
map = createIdentifierToBufferMap();
identifierToBufferThread.set(map);
}
map.put(identifier, buffer);
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
// This is intentional, as it appears the buffer can be set once and then filtered multiple times.
// The buffer will be cleared from memory after a new buffer is set by the same thread,
// or when the calling thread eventually dies.
bufferThreadLocal.set(buffer);
}
/**
@@ -307,70 +177,46 @@ public final class LithoFilterPatch {
* Targets 20.21 and lower.
*/
public static void setProtoBuffer(@Nullable ByteBuffer buffer) {
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
// This is intentional, as it appears the buffer can be set once and then filtered multiple times.
// The buffer will be cleared from memory after a new buffer is set by the same thread,
// or when the calling thread eventually dies.
if (buffer == null || !buffer.hasArray()) {
// It appears the buffer can be cleared out just before the call to #filter()
// Ignore this null value and retain the last buffer that was set.
Logger.printDebug(() -> "Ignoring null or empty buffer: " + buffer);
} else {
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
// This is intentional, as it appears the buffer can be set once and then filtered multiple times.
// The buffer will be cleared from memory after a new buffer is set by the same thread,
// or when the calling thread eventually dies.
bufferThreadLocal.set(buffer.array());
setProtoBuffer(buffer.array());
}
}
/**
* Injection point.
*/
public static boolean isFiltered(String identifier, StringBuilder pathBuilder) {
public static boolean isFiltered(String lithoIdentifier, StringBuilder pathBuilder) {
try {
if (identifier.isEmpty() || pathBuilder.length() == 0) {
if (lithoIdentifier.isEmpty() && pathBuilder.length() == 0) {
return false;
}
byte[] buffer = null;
if (EXTRACT_IDENTIFIER_FROM_BUFFER) {
final int pipeIndex = identifier.indexOf('|');
if (pipeIndex >= 0) {
// If the identifier contains no pipe, then it's not an ".eml" identifier
// and the buffer is not uniquely identified. Typically this only happens
// for subcomponents where buffer filtering is not used.
String identifierKey = identifier.substring(0, pipeIndex);
var map = identifierToBufferThread.get();
if (map != null) {
buffer = map.get(identifierKey);
}
if (buffer == null) {
// Buffer for thread local not found. Use the last buffer found from any thread.
buffer = identifierToBufferGlobal.get(identifierKey);
if (DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER && buffer == null) {
// No buffer is found for some components, such as
// shorts_lockup_cell.eml on channel profiles.
// For now, just ignore this and filter without a buffer.
Logger.printException(() -> "Could not find global buffer for identifier: " + identifier);
}
}
}
} else {
buffer = bufferThreadLocal.get();
}
byte[] buffer = bufferThreadLocal.get();
// Potentially the buffer may have been null or never set up until now.
// Use an empty buffer so the litho id/path filters that do not use a buffer still work.
// Use an empty buffer so the litho id/path filters still work correctly.
if (buffer == null) {
buffer = EMPTY_BYTE_ARRAY;
}
String path = pathBuilder.toString();
LithoFilterParameters parameter = new LithoFilterParameters(identifier, path, buffer);
LithoFilterParameters parameter = new LithoFilterParameters(
lithoIdentifier, pathBuilder.toString(), buffer);
Logger.printDebug(() -> "Searching " + parameter);
return identifierSearchTree.matches(identifier, parameter)
|| pathSearchTree.matches(path, parameter);
if (identifierSearchTree.matches(parameter.identifier, parameter)) {
return true;
}
if (pathSearchTree.matches(parameter.path, parameter)) {
return true;
}
} catch (Exception ex) {
Logger.printException(() -> "isFiltered failure", ex);
}

View File

@@ -4,15 +4,15 @@ import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.TrieSearch;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.ReturnYouTubeDislikePatch;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.TrieSearch;
/**
* Searches for video id's in the proto buffer of Shorts dislike.
@@ -33,7 +33,18 @@ public final class ReturnYouTubeDislikeFilter extends Filter {
* Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry().
*/
@GuardedBy("itself")
private static final Map<String, Boolean> lastVideoIds = Utils.createSizeRestrictedMap(5);
private static final Map<String, Boolean> lastVideoIds = new LinkedHashMap<>() {
/**
* Number of video id's to keep track of for searching thru the buffer.
* A minimum value of 3 should be sufficient, but check a few more just in case.
*/
private static final int NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK = 5;
@Override
protected boolean removeEldestEntry(Entry eldest) {
return size() > NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK;
}
};
/**
* Injection point.

View File

@@ -11,7 +11,6 @@ import java.util.Arrays;
import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.NavigationBar;
import app.revanced.extension.youtube.shared.PlayerType;
@@ -224,11 +223,7 @@ public final class ShortsFilter extends Filter {
videoActionButton = new StringFilterGroup(
null,
// Can be any of:
// button.eml
// shorts_video_action_button.eml
// reel_action_button.eml
// reel_pivot_button.eml
// Can be simply 'button.e', 'shorts_video_action_button.e' or 'reel_action_button.e'
"button.e"
);
@@ -239,37 +234,31 @@ public final class ShortsFilter extends Filter {
addPathCallbacks(
shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionLabel, autoDubbedLabel,
suggestedAction, pausedOverlayButtons, channelBar, previewComment,
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar, previewComment,
fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
stickers, likeFountain, likeButton, dislikeButton, livePreview
);
// FIXME: The Shorts buffer is very different with 20.22+ and if any of these filters
// are enabled then all Shorts player vertical buttons are hidden.
if (!VersionCheckPatch.IS_20_22_OR_GREATER) {
addPathCallbacks(shortsActionBar);
//
// All other action buttons.
//
videoActionButtonBuffer.addAll(
new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_COMMENTS_BUTTON,
"reel_comment_button",
"youtube_shorts_comment_outline"
),
new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_SHARE_BUTTON,
"reel_share_button",
"youtube_shorts_share_outline"
),
new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_REMIX_BUTTON,
"reel_remix_button",
"youtube_shorts_remix_outline"
)
);
}
//
// All other action buttons.
//
videoActionButtonBuffer.addAll(
new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_COMMENTS_BUTTON,
"reel_comment_button",
"youtube_shorts_comment_outline"
),
new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_SHARE_BUTTON,
"reel_share_button",
"youtube_shorts_share_outline"
),
new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_REMIX_BUTTON,
"reel_remix_button",
"youtube_shorts_remix_outline"
)
);
//
// Suggested actions.

View File

@@ -21,6 +21,7 @@ public class RememberVideoQualityPatch {
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE;
public static boolean shouldRememberVideoQuality() {
BooleanSetting preference = ShortsPlayerState.isOpen()
? Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED

View File

@@ -1,85 +0,0 @@
package app.revanced.extension.youtube.patches.theme;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
/**
* Dynamic drawable that is either the regular or bolded ReVanced preference icon.
*
* This is needed because the YouTube ReVanced preference intent is an AndroidX preference,
* and AndroidX classes are not built into Android which makes programmatically changing
* the preference thru patching overly complex. This solves the problem by using a drawable
* wrapper to dynamically pick which icon drawable to use at runtime.
*/
@SuppressWarnings("unused")
public class ReVancedSettingsIconDynamicDrawable extends Drawable {
private final Drawable icon;
public ReVancedSettingsIconDynamicDrawable() {
final int resId = Utils.getResourceIdentifier(ResourceType.DRAWABLE,
Utils.appIsUsingBoldIcons()
? "revanced_settings_icon_bold"
: "revanced_settings_icon"
);
icon = Utils.getContext().getDrawable(resId);
}
@Override
public void draw(@NonNull Canvas canvas) {
icon.draw(canvas);
}
@Override
public void setAlpha(int alpha) {
icon.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
icon.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return icon.getOpacity();
}
@Override
public int getIntrinsicWidth() {
return icon.getIntrinsicWidth();
}
@Override
public int getIntrinsicHeight() {
return icon.getIntrinsicHeight();
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
icon.setBounds(left, top, right, bottom);
}
@Override
public void setBounds(@NonNull Rect bounds) {
super.setBounds(bounds);
icon.setBounds(bounds);
}
@Override
public void onBoundsChange(@NonNull Rect bounds) {
super.onBoundsChange(bounds);
icon.setBounds(bounds);
}
}

View File

@@ -16,7 +16,6 @@ import java.util.Arrays;
import java.util.Scanner;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.settings.Settings;
@@ -102,6 +101,16 @@ public final class SeekbarColorPatch {
return customSeekbarColor;
}
/**
* injection point.
*/
public static boolean useLotteLaunchSplashScreen(boolean original) {
// This method is only used for development purposes to force the old style launch screen.
// Forcing this off on some devices can cause unexplained startup crashes,
// where the lottie animation is still used even though this condition appears to bypass it.
return original; // false = drawable style, true = lottie style.
}
/**
* Injection point.
* Modern Lottie style animation.

View File

@@ -260,8 +260,7 @@ public class ReturnYouTubeDislike {
// middle separator
String middleSeparatorString = compactLayout
? " " + MIDDLE_SEPARATOR_CHARACTER + " "
: " \u2009\u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009\u2009 "; // u2009 = 'narrow space'
: " \u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009 "; // u2009 = 'narrow space' character
final int shapeInsertionIndex = middleSeparatorString.length() / 2;
Spannable middleSeparatorSpan = new SpannableString(middleSeparatorString);
ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
@@ -556,8 +555,7 @@ public class ReturnYouTubeDislike {
if (originalDislikeSpan != null && replacementLikeDislikeSpan != null
&& spansHaveEqualTextAndColor(original, originalDislikeSpan)) {
Logger.printDebug(() -> "Replacing span: " + original + " with " +
"previously created dislike span of data: " + videoId);
Logger.printDebug(() -> "Replacing span with previously created dislike span of data: " + videoId);
return replacementLikeDislikeSpan;
}

View File

@@ -45,7 +45,7 @@ import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrow
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailStillTime;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.patches.MiniplayerPatch;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider.SwipeOverlayStyle;
@@ -187,7 +187,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, new MiniplayerAnyModernAvailability());
public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerHideOverlayButtonsAvailability());
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, new MiniplayerHideSubtextsAvailability());
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, new MiniplayerHideRewindOrOverlayOpacityAvailability());
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, new MiniplayerPatch.MiniplayerHideRewindOrOverlayOpacityAvailability());
public static final IntegerSetting MINIPLAYER_WIDTH_DIP = new IntegerSetting("revanced_miniplayer_width_dip", 192, true, new MiniplayerAnyModernAvailability());
public static final IntegerSetting MINIPLAYER_OPACITY = new IntegerSetting("revanced_miniplayer_opacity", 100, true, new MiniplayerHideRewindOrOverlayOpacityAvailability());
@@ -288,7 +288,6 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_hide_notifications_button", FALSE, true);
public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true,
"revanced_switch_create_with_notifications_button_user_dialog_message");
public static final BooleanSetting NAVIGATION_BAR_ANIMATIONS = new BooleanSetting("revanced_navigation_bar_animations", FALSE);
public static final BooleanSetting DISABLE_TRANSLUCENT_STATUS_BAR = new BooleanSetting("revanced_disable_translucent_status_bar", FALSE, true,
"revanced_disable_translucent_status_bar_user_dialog_message");
public static final BooleanSetting DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT = new BooleanSetting("revanced_disable_translucent_navigation_bar_light", FALSE, true);
@@ -342,7 +341,6 @@ public class Settings extends BaseSettings {
public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", FALSE);
public static final BooleanSetting HIDE_SEEKBAR = new BooleanSetting("revanced_hide_seekbar", FALSE, true);
public static final BooleanSetting HIDE_SEEKBAR_THUMBNAIL = new BooleanSetting("revanced_hide_seekbar_thumbnail", FALSE, true);
public static final BooleanSetting FULLSCREEN_LARGE_SEEKBAR = new BooleanSetting("revanced_fullscreen_large_seekbar", FALSE);
public static final BooleanSetting HIDE_TIMESTAMP = new BooleanSetting("revanced_hide_timestamp", FALSE);
public static final BooleanSetting RESTORE_OLD_SEEKBAR_THUMBNAILS = new BooleanSetting("revanced_restore_old_seekbar_thumbnails", TRUE);
public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", FALSE);
@@ -477,13 +475,6 @@ public class Settings extends BaseSettings {
static {
// region Migration
// 20.37+ YT removed parts of the code for the legacy tablet miniplayer.
// This check must remain until the Tablet type is eventually removed.
if (VersionCheckPatch.IS_20_37_OR_GREATER && MINIPLAYER_TYPE.get() == MiniplayerType.TABLET) {
Logger.printInfo(() -> "Resetting miniplayer tablet type");
MINIPLAYER_TYPE.resetToDefault();
}
// Migrate renamed change header enums.
if (HEADER_LOGO.get() == HeaderLogo.REVANCED) {
HEADER_LOGO.save(HeaderLogo.ROUNDED);
@@ -526,14 +517,6 @@ public class Settings extends BaseSettings {
SPOOF_APP_VERSION.resetToDefault();
}
if (!BaseSettings.SETTINGS_DISABLE_BOLD_ICONS.get() && SPOOF_APP_VERSION.get()
&& SPOOF_APP_VERSION_TARGET.get().compareTo("19.35.00") <= 0) {
Logger.printInfo(() -> "Temporarily disabling bold icons that don't work with old spoof targets");
// Don't save and only temporarily overwrite the value so
// if spoofing is turned off the old setting value is used.
BooleanSetting.privateSetValue(BaseSettings.SETTINGS_DISABLE_BOLD_ICONS, false);
}
// VR 1.61 is not selectable in the settings, and it's selected by spoof stream patch if needed.
if (SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_1_61_48) {
SPOOF_VIDEO_STREAMS_CLIENT_TYPE.resetToDefault();

View File

@@ -7,7 +7,6 @@ import android.preference.PreferenceFragment;
import android.view.View;
import android.widget.Toolbar;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
@@ -16,28 +15,11 @@ import app.revanced.extension.youtube.settings.preference.YouTubePreferenceFragm
import app.revanced.extension.youtube.settings.search.YouTubeSearchViewController;
/**
* Hooks LicenseActivity to inject a custom {@link YouTubePreferenceFragment}
* with a toolbar and search functionality.
* Hooks LicenseActivity to inject a custom {@link YouTubePreferenceFragment} with a toolbar and search functionality.
*/
@SuppressWarnings("deprecation")
public class YouTubeActivityHook extends BaseActivityHook {
/**
* How much time has passed since the first launch of the app. Simple check to prevent
* forcing bold icons on first launch where the settings menu is partially broken
* due to missing icon resources the client has not yet received.
*/
private static final long MINIMUM_TIME_AFTER_FIRST_LAUNCH_BEFORE_ALLOWING_BOLD_ICONS = 30 * 1000; // 30 seconds.
private static final boolean USE_BOLD_ICONS = VersionCheckPatch.IS_20_31_OR_GREATER
&& !Settings.SETTINGS_DISABLE_BOLD_ICONS.get()
&& (System.currentTimeMillis() - Settings.FIRST_TIME_APP_LAUNCHED.get())
> MINIMUM_TIME_AFTER_FIRST_LAUNCH_BEFORE_ALLOWING_BOLD_ICONS;
static {
Utils.setAppIsUsingBoldIcons(USE_BOLD_ICONS);
}
private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.
/**
@@ -62,7 +44,15 @@ public class YouTubeActivityHook extends BaseActivityHook {
final var theme = Utils.isDarkModeEnabled()
? "Theme.YouTube.Settings.Dark"
: "Theme.YouTube.Settings";
activity.setTheme(Utils.getResourceIdentifierOrThrow(ResourceType.STYLE, theme));
activity.setTheme(Utils.getResourceIdentifierOrThrow(theme, "style"));
}
/**
* Returns the resource ID for the YouTube settings layout.
*/
@Override
protected int getContentViewResourceId() {
return LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR;
}
/**
@@ -165,12 +155,4 @@ public class YouTubeActivityHook extends BaseActivityHook {
public static boolean handleBackPress() {
return YouTubeSearchViewController.handleFinish(searchViewController);
}
/**
* Injection point.
*/
@SuppressWarnings("unused")
public static boolean useBoldIcons(boolean original) {
return USE_BOLD_ICONS;
}
}

View File

@@ -19,10 +19,8 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
@@ -74,7 +72,7 @@ public final class NavigationBar {
*/
public static boolean isSearchBarActive() {
View searchbarResults = searchBarResultsRef.get();
return searchbarResults != null && searchbarResults.isShown();
return searchbarResults != null && searchbarResults.getParent() != null;
}
public static boolean isBackButtonVisible() {
@@ -279,14 +277,12 @@ public final class NavigationBar {
}
/**
* Custom cairo notification filled icon to fix unpatched app missing resource.
* Use the bundled non cairo filled icon instead of a custom icon.
* Use the old non cairo filled icon, which is almost identical to
* the what would be the filled cairo icon.
*/
private static final int fillBellCairoBlack = Utils.getResourceIdentifier(ResourceType.DRAWABLE,
// The bold cairo notification filled icon is present,
// but YT still has not fixed the icon not associated to the enum.
VersionCheckPatch.IS_20_31_OR_GREATER && !Settings.SETTINGS_DISABLE_BOLD_ICONS.get()
? "yt_fill_experimental_bell_vd_theme_24"
: "revanced_fill_bell_cairo_black_24");
private static final int fillBellCairoBlack = Utils.getResourceIdentifier(
"yt_fill_bell_black_24", "drawable");
/**
* Injection point.
@@ -294,12 +290,13 @@ public final class NavigationBar {
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static void setCairoNotificationFilledIcon(EnumMap enumMap, Enum tabActivityCairo) {
// Show a popup informing this fix is no longer needed to those who might care.
if (BaseSettings.DEBUG.get() && enumMap.containsKey(tabActivityCairo)) {
Logger.printException(() -> "YouTube fixed the notification icons");
if (fillBellCairoBlack != 0) {
// Show a popup informing this fix is no longer needed to those who might care.
if (BaseSettings.DEBUG.get() && enumMap.containsKey(tabActivityCairo)) {
Logger.printException(() -> "YouTube fixed the cairo notification icons");
}
enumMap.putIfAbsent(tabActivityCairo, fillBellCairoBlack);
}
enumMap.putIfAbsent(tabActivityCairo, fillBellCairoBlack);
}
public enum NavigationButton {

View File

@@ -3,7 +3,6 @@ package app.revanced.extension.youtube.shared
import android.app.Activity
import android.view.View
import android.view.ViewGroup
import app.revanced.extension.shared.ResourceType
import app.revanced.extension.shared.Utils
import java.lang.ref.WeakReference
@@ -20,13 +19,13 @@ class PlayerControlsVisibilityObserverImpl(
* id of the direct parent of controls_layout, R.id.youtube_controls_overlay
*/
private val controlsLayoutParentId =
Utils.getResourceIdentifier(activity, ResourceType.ID, "youtube_controls_overlay")
Utils.getResourceIdentifier(activity, "youtube_controls_overlay", "id")
/**
* id of R.id.controls_layout
*/
private val controlsLayoutId =
Utils.getResourceIdentifier(activity, ResourceType.ID, "controls_layout")
Utils.getResourceIdentifier(activity, "controls_layout", "id")
/**
* reference to the controls layout view

View File

@@ -2,6 +2,7 @@ package app.revanced.extension.youtube.shared
import app.revanced.extension.shared.Logger
import app.revanced.extension.youtube.Event
import app.revanced.extension.youtube.patches.VideoInformation
/**
* Regular player type.

View File

@@ -24,6 +24,7 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -149,9 +150,9 @@ public class SegmentPlaybackController {
private static long skipSegmentButtonEndTime;
@Nullable
private static String timeWithoutSegments;
private static int seekbarAbsoluteLeft;
private static int seekbarAbsoluteRight;
private static int seekbarThickness;
private static int sponsorBarAbsoluteLeft;
private static int sponsorAbsoluteBarRight;
private static int sponsorBarThickness;
@Nullable
private static SponsorSegment lastSegmentSkipped;
@@ -907,13 +908,31 @@ public class SegmentPlaybackController {
* injection point.
*/
@SuppressWarnings("unused")
public static void setSeekbarRectangle(Rect seekbarRect) {
final int left = seekbarRect.left;
final int right = seekbarRect.right;
if (seekbarAbsoluteLeft != left || seekbarAbsoluteRight != right) {
Logger.printDebug(() -> "setSeekbarRectangle left: " + left + " right: " + right);
seekbarAbsoluteLeft = left;
seekbarAbsoluteRight = right;
public static void setSponsorBarRect(Object self) {
try {
Field field = self.getClass().getDeclaredField("replaceMeWithsetSponsorBarRect");
field.setAccessible(true);
Rect rect = (Rect) Objects.requireNonNull(field.get(self));
setSponsorBarAbsoluteLeft(rect);
setSponsorBarAbsoluteRight(rect);
} catch (Exception ex) {
Logger.printException(() -> "setSponsorBarRect failure", ex);
}
}
private static void setSponsorBarAbsoluteLeft(Rect rect) {
final int left = rect.left;
if (sponsorBarAbsoluteLeft != left) {
Logger.printDebug(() -> "setSponsorBarAbsoluteLeft: " + left);
sponsorBarAbsoluteLeft = left;
}
}
private static void setSponsorBarAbsoluteRight(Rect rect) {
final int right = rect.right;
if (sponsorAbsoluteBarRight != right) {
Logger.printDebug(() -> "setSponsorBarAbsoluteRight: " + right);
sponsorAbsoluteBarRight = right;
}
}
@@ -921,8 +940,8 @@ public class SegmentPlaybackController {
* injection point.
*/
@SuppressWarnings("unused")
public static void setSeekbarThickness(int thickness) {
seekbarThickness = thickness;
public static void setSponsorBarThickness(int thickness) {
sponsorBarThickness = thickness;
}
/**
@@ -932,7 +951,8 @@ public class SegmentPlaybackController {
public static String appendTimeWithoutSegments(String totalTime) {
try {
if (Settings.SB_ENABLED.get() && Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.get()
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)) {
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)
&& !isAdProgressTextVisible()) {
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages
return "\u202D" + totalTime + timeWithoutSegments; // u202D = left to right override
}
@@ -960,7 +980,6 @@ public class SegmentPlaybackController {
continue;
}
foundNonhighlightSegments = true;
long start = segment.start;
final long end = segment.end;
// To prevent nested segments from incorrectly counting additional time,
@@ -992,17 +1011,17 @@ public class SegmentPlaybackController {
* Injection point.
*/
@SuppressWarnings("unused")
public static void drawSegmentTimeBars(final Canvas canvas, final float posY) {
public static void drawSponsorTimeBars(final Canvas canvas, final float posY) {
try {
if (segments == null) return;
if (segments == null || isAdProgressTextVisible()) return;
final long videoLength = VideoInformation.getVideoLength();
if (videoLength <= 0) return;
final int thicknessDiv2 = seekbarThickness / 2; // Rounds down.
final float top = posY - (seekbarThickness - thicknessDiv2);
final int thicknessDiv2 = sponsorBarThickness / 2; // rounds down
final float top = posY - (sponsorBarThickness - thicknessDiv2);
final float bottom = posY + thicknessDiv2;
final float videoMillisecondsToPixels = (1f / videoLength) * (seekbarAbsoluteRight - seekbarAbsoluteLeft);
final float leftPadding = seekbarAbsoluteLeft;
final float videoMillisecondsToPixels = (1f / videoLength) * (sponsorAbsoluteBarRight - sponsorBarAbsoluteLeft);
final float leftPadding = sponsorBarAbsoluteLeft;
for (SponsorSegment segment : segments) {
final float left = leftPadding + segment.start * videoMillisecondsToPixels;

View File

@@ -1,26 +1,16 @@
package app.revanced.extension.youtube.sponsorblock.ui;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
@SuppressWarnings("unused")
public class CreateSegmentButton {
private static final int DRAWABLE_SB_LOGO = Utils.getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, Utils.appIsUsingBoldIcons()
? "revanced_sb_logo_bold"
: "revanced_sb_logo"
);
@Nullable
private static PlayerControlButton instance;
@@ -41,14 +31,6 @@ public class CreateSegmentButton {
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
null
);
// FIXME: Bold YT player icons are currently forced off.
// Enable this logic when the new player icons are not forced off.
ImageView icon = Utils.getChildViewByResourceName(controlsView,
"revanced_sb_create_segment_button");
if (false) {
icon.setImageResource(DRAWABLE_SB_LOGO);
}
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}

View File

@@ -16,7 +16,6 @@ import android.widget.ImageButton;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockUtils;
@@ -46,8 +45,8 @@ public final class NewSegmentLayout extends FrameLayout {
final int defStyleAttr, final int defStyleRes) {
super(context, attributeSet, defStyleAttr, defStyleRes);
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(context,
ResourceType.LAYOUT, "revanced_sb_new_segment"), this, true
LayoutInflater.from(context).inflate(
getResourceIdentifierOrThrow(context, "revanced_sb_new_segment", "layout"), this, true
);
initializeButton(
@@ -106,7 +105,7 @@ public final class NewSegmentLayout extends FrameLayout {
*/
private void initializeButton(final Context context, final String resourceIdentifierName,
final ButtonOnClickHandlerFunction handler, final String debugMessage) {
ImageButton button = findViewById(getResourceIdentifierOrThrow(context, ResourceType.ID, resourceIdentifierName));
ImageButton button = findViewById(getResourceIdentifierOrThrow(context, resourceIdentifierName, "id"));
// Add ripple effect
RippleDrawable rippleDrawable = new RippleDrawable(

View File

@@ -21,7 +21,6 @@ import androidx.annotation.NonNull;
import java.util.Objects;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
@@ -58,10 +57,11 @@ public class SkipSponsorButton extends FrameLayout {
public SkipSponsorButton(Context context, AttributeSet attributeSet, int defStyleAttr, int defStyleRes) {
super(context, attributeSet, defStyleAttr, defStyleRes);
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(context, ResourceType.LAYOUT, "revanced_sb_skip_sponsor_button"), this, true); // layout:skip_ad_button
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(context,
"revanced_sb_skip_sponsor_button", "layout"), this, true); // layout:skip_ad_button
setMinimumHeight(getResourceDimensionPixelSize("ad_skip_ad_button_min_height")); // dimen:ad_skip_ad_button_min_height
skipSponsorBtnContainer = Objects.requireNonNull(findViewById(getResourceIdentifierOrThrow(
context, ResourceType.ID, "revanced_sb_skip_sponsor_button_container"))); // id:skip_ad_button_container
context, "revanced_sb_skip_sponsor_button_container", "id"))); // id:skip_ad_button_container
background = new Paint();
background.setColor(getResourceColor("skip_ad_button_background_color")); // color:skip_ad_button_background_color);
@@ -72,7 +72,7 @@ public class SkipSponsorButton extends FrameLayout {
border.setStrokeWidth(getResourceDimension("ad_skip_ad_button_border_width")); // dimen:ad_skip_ad_button_border_width);
border.setStyle(Paint.Style.STROKE);
skipSponsorTextView = Objects.requireNonNull(findViewById(getResourceIdentifier(context, ResourceType.ID, "revanced_sb_skip_sponsor_button_text"))); // id:skip_ad_button_text;
skipSponsorTextView = Objects.requireNonNull(findViewById(getResourceIdentifier(context, "revanced_sb_skip_sponsor_button_text", "id"))); // id:skip_ad_button_text;
defaultBottomMargin = getResourceDimensionPixelSize("skip_button_default_bottom_margin"); // dimen:skip_button_default_bottom_margin
ctaBottomMargin = getResourceDimensionPixelSize("skip_button_cta_bottom_margin"); // dimen:skip_button_cta_bottom_margin

View File

@@ -1,6 +1,5 @@
package app.revanced.extension.youtube.sponsorblock.ui;
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
import android.content.Context;
@@ -16,7 +15,6 @@ import java.lang.ref.WeakReference;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.shared.PlayerType;
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
@@ -64,17 +62,16 @@ public class SponsorBlockViewController {
Context context = Utils.getContext();
RelativeLayout layout = new RelativeLayout(context);
layout.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
layout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(
ResourceType.LAYOUT, "revanced_sb_inline_sponsor_overlay"), layout);
"revanced_sb_inline_sponsor_overlay", "layout"), layout);
inlineSponsorOverlayRef = new WeakReference<>(layout);
viewGroup.addView(layout);
viewGroup.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
// Ensure SB buttons and controls are always on top, otherwise the end-screen cards can cover the skip button.
// ensure SB buttons and controls are always on top, otherwise the endscreen cards can cover the skip button
RelativeLayout layout = inlineSponsorOverlayRef.get();
if (layout != null) {
layout.bringToFront();
@@ -86,14 +83,14 @@ public class SponsorBlockViewController {
});
youtubeOverlaysLayoutRef = new WeakReference<>(viewGroup);
skipHighlightButtonRef = new WeakReference<>(Objects.requireNonNull(layout.findViewById(
getResourceIdentifier(ResourceType.ID, "revanced_sb_skip_highlight_button"))));
skipHighlightButtonRef = new WeakReference<>(layout.findViewById(getResourceIdentifierOrThrow(
"revanced_sb_skip_highlight_button", "id")));
skipSponsorButtonRef = new WeakReference<>(Objects.requireNonNull(layout.findViewById(
getResourceIdentifier(ResourceType.ID, "revanced_sb_skip_sponsor_button"))));
skipSponsorButtonRef = new WeakReference<>(layout.findViewById(getResourceIdentifierOrThrow(
"revanced_sb_skip_sponsor_button", "id")));
NewSegmentLayout newSegmentLayout = Objects.requireNonNull(layout.findViewById(
getResourceIdentifier(ResourceType.ID, "revanced_sb_new_segment_view")));
NewSegmentLayout newSegmentLayout = layout.findViewById(getResourceIdentifierOrThrow(
"revanced_sb_new_segment_view", "id"));
newSegmentLayoutRef = new WeakReference<>(newSegmentLayout);
newSegmentLayout.updateLayout();

View File

@@ -8,7 +8,6 @@ import android.view.MotionEvent
import android.view.ViewGroup
import app.revanced.extension.shared.Logger.printDebug
import app.revanced.extension.shared.Logger.printException
import app.revanced.extension.youtube.patches.VersionCheckPatch
import app.revanced.extension.youtube.settings.Settings
import app.revanced.extension.youtube.shared.PlayerType
import app.revanced.extension.youtube.swipecontrols.controller.AudioVolumeController
@@ -238,8 +237,6 @@ class SwipeControlsHostActivity : Activity() {
*/
@Suppress("unused")
@JvmStatic
fun allowSwipeChangeVideo(original: Boolean): Boolean =
// Feature can cause crashing if forced in newer targets.
!VersionCheckPatch.IS_20_22_OR_GREATER && Settings.SWIPE_CHANGE_VIDEO.get()
fun allowSwipeChangeVideo(original: Boolean): Boolean = Settings.SWIPE_CHANGE_VIDEO.get()
}
}

View File

@@ -3,7 +3,6 @@ package app.revanced.extension.youtube.swipecontrols.controller
import android.app.Activity
import android.util.TypedValue
import android.view.ViewGroup
import app.revanced.extension.shared.ResourceType
import app.revanced.extension.shared.Utils
import app.revanced.extension.youtube.swipecontrols.misc.Rectangle
import app.revanced.extension.youtube.swipecontrols.misc.applyDimension
@@ -57,8 +56,7 @@ class SwipeZonesController(
/**
* id for R.id.player_view
*/
private val playerViewId = Utils.getResourceIdentifier(
host, ResourceType.ID, "player_view")
private val playerViewId = Utils.getResourceIdentifier(host, "player_view", "id")
/**
* current bounding rectangle of the player

View File

@@ -14,13 +14,12 @@ import android.util.AttributeSet
import android.view.HapticFeedbackConstants
import android.view.View
import android.widget.RelativeLayout
import app.revanced.extension.shared.ResourceType
import app.revanced.extension.shared.StringRef.str
import app.revanced.extension.shared.Utils
import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider
import app.revanced.extension.youtube.swipecontrols.misc.SwipeControlsOverlay
import kotlin.math.max
import kotlin.math.min
import kotlin.math.max
import kotlin.math.round
/**
@@ -54,7 +53,7 @@ class SwipeControlsOverlayLayout(
// Function to retrieve drawable resources by name.
private fun getDrawable(name: String): Drawable {
val drawable = resources.getDrawable(
Utils.getResourceIdentifier(context, ResourceType.DRAWABLE, name),
Utils.getResourceIdentifier(context, name, "drawable"),
context.theme,
)
drawable.setTint(config.overlayTextColor)
@@ -87,7 +86,7 @@ class SwipeControlsOverlayLayout(
// Initialize horizontal progress bar.
val screenWidth = resources.displayMetrics.widthPixels
val layoutWidth = (screenWidth * 4 / 5) // Cap at ~360dp.
val layoutWidth = (screenWidth * 4 / 5).toInt() // Cap at ~360dp.
horizontalProgressView = HorizontalProgressView(
context,
config.overlayBackgroundOpacity,
@@ -631,7 +630,7 @@ class VerticalProgressView(
if (isMinimalStyle) {
canvas.drawText(displayText, textX, textStartY, textPaint)
} else {
val progressStartY = (iconEndY + padding)
val progressStartY = (iconEndY + padding).toFloat()
val progressEndY = textStartY - textPaint.textSize - padding
val progressHeight = progressEndY - progressStartY

View File

@@ -3,11 +3,8 @@ package app.revanced.extension.youtube.videoplayer;
import static app.revanced.extension.shared.StringRef.str;
import android.view.View;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
@@ -17,9 +14,9 @@ public class LoopVideoButton {
private static PlayerControlButton instance;
private static final int LOOP_VIDEO_ON = Utils.getResourceIdentifierOrThrow(
ResourceType.DRAWABLE, "revanced_loop_video_button_on");
"revanced_loop_video_button_on", "drawable");
private static final int LOOP_VIDEO_OFF = Utils.getResourceIdentifierOrThrow(
ResourceType.DRAWABLE,"revanced_loop_video_button_off");
"revanced_loop_video_button_off", "drawable");
/**
* Injection point.

View File

@@ -30,7 +30,6 @@ import java.util.ArrayList;
import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ResourceType;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch;

View File

@@ -1,22 +1,22 @@
[versions]
revanced-patcher = "22.0.0-local"
revanced-patcher = "21.0.0"
# Tracking https://github.com/google/smali/issues/64.
#noinspection GradleDependency
smali = "3.0.8"
smali = "3.0.5"
# 8.3.0 causes java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818.
#noinspection GradleDependency
agp = "8.2.2"
annotation = "1.9.1"
appcompat = "1.7.1"
okhttp = "5.3.2"
retrofit = "3.0.0"
appcompat = "1.7.0"
okhttp = "5.0.0-alpha.14"
retrofit = "2.11.0"
guava = "33.5.0-jre"
protobuf-javalite = "4.33.2"
protoc = "4.33.2"
protobuf = "0.9.6"
protobuf-javalite = "4.32.0"
protoc = "4.32.0"
protobuf = "0.9.5"
antlr4 = "4.13.2"
nanohttpd = "2.3.1"
apksig = "8.12.3"
apksig = "8.10.1"
[libraries]
annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }

View File

@@ -1,5 +1,6 @@
#Mon Jun 16 14:39:32 CEST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -76,6 +76,10 @@ public final class app/revanced/patches/all/misc/debugging/EnableAndroidDebuggin
public static final fun getEnableAndroidDebuggingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/all/misc/directory/ChangeDataDirectoryLocationPatchKt {
public static final fun getChangeDataDirectoryLocationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatchKt {
public static final fun getExportInternalDataDocumentsProviderPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
@@ -164,6 +168,10 @@ public final class app/revanced/patches/angulus/ads/RemoveAdsPatchKt {
public static final fun getAngulusPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/backdrops/misc/pro/ProUnlockPatchKt {
public static final fun getProUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/bandcamp/limitations/RemovePlayLimitsPatchKt {
public static final fun getRemovePlayLimitsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -252,6 +260,10 @@ public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatc
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/googlephotos/misc/preferences/RestoreHiddenBackUpWhileChargingTogglePatchKt {
public static final fun getRestoreHiddenBackUpWhileChargingTogglePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictionsKt {
public static final fun getRemoveDeviceRestrictionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -380,6 +392,14 @@ public final class app/revanced/patches/messenger/inbox/HideInboxSubtabsPatchKt
public static final fun getHideInboxSubtabsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatchKt {
public static final fun getDisableSwitchingEmojiToStickerPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatchKt {
public static final fun getDisableTypingIndicatorPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/messenger/layout/HideFacebookButtonPatchKt {
public static final fun getHideFacebookButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -392,6 +412,14 @@ public final class app/revanced/patches/messenger/misc/extension/ExtensionPatchK
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/messenger/navbar/RemoveMetaAITabPatchKt {
public static final fun getRemoveMetaAITabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/meta/ads/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatchKt {
public static final fun getForceEnglishLocalePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -412,6 +440,10 @@ public final class app/revanced/patches/music/interaction/permanentrepeat/Perman
public static final fun getPermanentRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatchKt {
public static final fun getPermanentShufflePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/layout/branding/CustomBrandingPatchKt {
public static final fun getCustomBrandingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
@@ -420,6 +452,10 @@ public final class app/revanced/patches/music/layout/buttons/HideButtonsKt {
public static final fun getHideButtons ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/layout/castbutton/HideCastButtonKt {
public static final fun getHideCastButton ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/layout/compactheader/HideCategoryBarKt {
public static final fun getHideCategoryBar ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -440,6 +476,11 @@ public final class app/revanced/patches/music/layout/theme/ThemePatchKt {
public static final fun getThemePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/layout/upgradebutton/HideUpgradeButtonPatchKt {
public static final fun getHideUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getRemoveUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatchKt {
public static final fun getBypassCertificateChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -520,6 +561,10 @@ public final class app/revanced/patches/netguard/broadcasts/removerestriction/Re
public static final fun getRemoveBroadcastsRestrictionPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/nunl/ads/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -528,6 +573,10 @@ public final class app/revanced/patches/nunl/firebase/SpoofCertificatePatchKt {
public static final fun getSpoofCertificatePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/nyx/misc/pro/UnlockProPatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatchKt {
public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -766,11 +815,16 @@ public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/
public static final fun getFixVideoDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatchKt {
public static final fun getFixVideoDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatchKt {
public static final fun getDisableScreenshotPopupPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatchKt {
public static final fun getUnlockPremiumIconPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getUnlockPremiumIconsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -808,24 +862,27 @@ public final class app/revanced/patches/shared/misc/extension/ExtensionHook {
}
public final class app/revanced/patches/shared/misc/extension/SharedExtensionPatchKt {
public static final fun activityOnCreateExtensionHook (Ljava/lang/String;)Lkotlin/jvm/functions/Function0;
public static final fun extensionHook (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lapp/revanced/patcher/Fingerprint;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
public static final fun extensionHook (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function0;
public static final fun extensionHook (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lapp/revanced/patcher/Fingerprint;ILjava/lang/Object;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function0;
public static final fun sharedExtensionPatch (Ljava/lang/String;[Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun sharedExtensionPatch ([Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
public static final fun sharedExtensionPatch (Ljava/lang/String;[Lapp/revanced/patches/shared/misc/extension/ExtensionHook;)Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun sharedExtensionPatch ([Lapp/revanced/patches/shared/misc/extension/ExtensionHook;)Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatchKt {
public static final fun getVerticalScrollPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/shared/misc/gms/FingerprintsKt {
public static final field GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME Ljava/lang/String;
}
public final class app/revanced/patches/shared/misc/gms/GmsCoreSupportPatchKt {
public static final fun gmsCoreSupportPatch (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun gmsCoreSupportPatch$default (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch;
public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch;
public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/shared/misc/hex/HexPatchBuilder : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
@@ -864,64 +921,23 @@ public final class app/revanced/patches/shared/misc/hex/Replacement {
}
public final class app/revanced/patches/shared/misc/mapping/ResourceElement {
public fun <init> (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;J)V
public final fun component1 ()Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()J
public final fun copy (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;J)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
public static synthetic fun copy$default (Lapp/revanced/patches/shared/misc/mapping/ResourceElement;Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;JILjava/lang/Object;)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
public final fun copy (Ljava/lang/String;Ljava/lang/String;J)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
public static synthetic fun copy$default (Lapp/revanced/patches/shared/misc/mapping/ResourceElement;Ljava/lang/String;Ljava/lang/String;JILjava/lang/Object;)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
public fun equals (Ljava/lang/Object;)Z
public final fun getId ()J
public final fun getName ()Ljava/lang/String;
public final fun getType ()Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public final fun getType ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatchKt {
public static final fun getResourceElements ()Ljava/util/Collection;
public static final fun getResourceId (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;)J
public static final fun get (Ljava/util/List;Ljava/lang/String;Ljava/lang/String;)J
public static final fun getResourceMappingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
public static final fun hasResourceId (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;)Z
public static final fun resourceLiteral (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter;
public static synthetic fun resourceLiteral$default (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter;
}
public final class app/revanced/patches/shared/misc/mapping/ResourceType : java/lang/Enum {
public static final field ANIM Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field ANIMATOR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field ARRAY Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field ATTR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field BOOL Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field COLOR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field Companion Lapp/revanced/patches/shared/misc/mapping/ResourceType$Companion;
public static final field DIMEN Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field DRAWABLE Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field FONT Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field FRACTION Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field ID Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field INTEGER Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field INTERPOLATOR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field LAYOUT Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field MENU Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field MIPMAP Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field NAVIGATION Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field PLURALS Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field RAW Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field STRING Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field STYLE Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field STYLEABLE Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field TRANSITION Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field VALUES Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final field XML Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getValue ()Ljava/lang/String;
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static fun values ()[Lapp/revanced/patches/shared/misc/mapping/ResourceType;
}
public final class app/revanced/patches/shared/misc/mapping/ResourceType$Companion {
public final fun fromValue (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/mapping/ResourceType;
public static final fun getResourceMappings ()Ljava/util/List;
}
public final class app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatchKt {
@@ -935,15 +951,15 @@ public final class app/revanced/patches/shared/misc/privacy/DisableSentryTelemet
public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt {
public static final fun overrideThemeColors (Ljava/lang/String;Ljava/lang/String;)V
public static final fun settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
public static final fun settingsPatch (Lkotlin/Pair;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
public static synthetic fun settingsPatch$default (Ljava/util/List;Ljava/util/Set;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
}
public abstract class app/revanced/patches/shared/misc/settings/preference/BasePreference {
public static final field Companion Lapp/revanced/patches/shared/misc/settings/preference/BasePreference$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getIcon ()Ljava/lang/String;
public final fun getIconBold ()Ljava/lang/String;
public final fun getKey ()Ljava/lang/String;
public final fun getLayout ()Ljava/lang/String;
public final fun getSummaryKey ()Ljava/lang/String;
@@ -967,10 +983,9 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
public abstract class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getIcon ()Ljava/lang/String;
public final fun getIconBold ()Ljava/lang/String;
public final fun getKey ()Ljava/lang/String;
public final fun getLayout ()Ljava/lang/String;
public final fun getPreferences ()Ljava/util/Set;
@@ -979,8 +994,8 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
}
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
public final fun getCategories ()Ljava/util/Set;
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
@@ -988,8 +1003,8 @@ public class app/revanced/patches/shared/misc/settings/preference/BasePreference
}
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen$Category : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
public fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/PreferenceCategory;
@@ -1008,8 +1023,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/InputTyp
}
public final class app/revanced/patches/shared/misc/settings/preference/IntentPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getIntent ()Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
public fun hashCode ()I
@@ -1039,22 +1054,22 @@ public final class app/revanced/patches/shared/misc/settings/preference/ListPref
}
public final class app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getSelectable ()Z
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
public class app/revanced/patches/shared/misc/settings/preference/PreferenceCategory : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getPreferences ()Ljava/util/Set;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
public class app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getPreferences ()Ljava/util/Set;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
@@ -1082,8 +1097,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/SummaryT
public final class app/revanced/patches/shared/misc/settings/preference/SwitchPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getSummaryOffKey ()Ljava/lang/String;
public final fun getSummaryOnKey ()Ljava/lang/String;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
@@ -1091,8 +1106,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/SwitchPr
public final class app/revanced/patches/shared/misc/settings/preference/TextPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getInputType ()Lapp/revanced/patches/shared/misc/settings/preference/InputType;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
@@ -1129,14 +1144,34 @@ public final class app/revanced/patches/soundcloud/offlinesync/EnableOfflineSync
public static final fun getEnableOfflineSync ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatchKt {
public static final fun getHideCreateButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/layout/theme/CustomThemePatchKt {
public static final fun getCustomThemePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt {
public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/extension/ExtensionPatchKt {
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/SpoofClientPatchKt {
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatchKt {
public static final fun getSpoofPackageInfoPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatchKt {
public static final fun getFixFacebookLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1153,6 +1188,10 @@ public final class app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunch
public static final fun getFixThirdPartyLaunchersWidgets ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/navbar/PremiumNavbarTabPatchKt {
public static final fun getPremiumNavbarTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/stocard/layout/HideOffersTabPatchKt {
public static final fun getHideOffersTabPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
@@ -1385,6 +1424,10 @@ public final class app/revanced/patches/twitter/misc/links/ChangeLinkSharingDoma
public static final fun getChangeLinkSharingDomainPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatchKt {
public static final fun getOpenLinksWithAppChooserPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/twitter/misc/links/SanitizeSharingLinksPatchKt {
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1397,6 +1440,10 @@ public final class app/revanced/patches/viber/misc/navbar/HideNavigationButtonsK
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/warnwetter/misc/firebasegetcert/FirebaseGetCertPatchKt {
public static final fun getFirebaseGetCertPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1405,6 +1452,10 @@ public final class app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnloc
public static final fun getPromoCodeUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/ad/general/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1426,6 +1477,7 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD
}
public final class app/revanced/patches/youtube/interaction/doubletap/DisableChapterSkipDoubleTapPatchKt {
public static final fun getDisableChapterSkipDoubleTapPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getDisableDoubleTapActionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1502,7 +1554,15 @@ public final class app/revanced/patches/youtube/layout/hide/fullscreenambientmod
}
public final class app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatchKt {
public static final fun getAlbumCardId ()J
public static final fun getBarContainerHeightId ()J
public static final fun getCrowdfundingBoxId ()J
public static final fun getExpandButtonDownId ()J
public static final fun getFabButtonId ()J
public static final fun getFilterBarHeightId ()J
public static final fun getHideLayoutComponentsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getRelatedChipCloudMarginId ()J
public static final fun getYouTubeLogo ()J
}
public final class app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatchKt {
@@ -1521,6 +1581,10 @@ public final class app/revanced/patches/youtube/layout/hide/rollingnumber/Disabl
public static final fun getDisableRollingNumberAnimationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatchKt {
public static final fun getHideSeekbarPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatchKt {
public static final fun getHideShortsComponentsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1529,6 +1593,10 @@ public final class app/revanced/patches/youtube/layout/hide/signintotvpopup/Disa
public static final fun getDisableSignInToTvPopupPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatchKt {
public static final fun getDisableSuggestedVideoEndScreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/hide/time/HideTimestampPatchKt {
public static final fun getHideTimestampPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1541,6 +1609,14 @@ public final class app/revanced/patches/youtube/layout/panels/popup/PlayerPopupP
public static final fun getPlayerPopupPanelsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatchKt {
public static final fun getPlayerControlsBackgroundPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt {
public static final fun getOpenVideosFullscreen ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatchKt {
public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1595,6 +1671,15 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl
public static final fun getDisableResumingShortsOnStartupPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt {
public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/layout/theme/LithoColorHookPatchKt {
public static final fun getLithoColorHookPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getLithoColorOverrideHook ()Lkotlin/jvm/functions/Function2;
}
public final class app/revanced/patches/youtube/layout/theme/ThemePatchKt {
public static final fun getThemePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1611,6 +1696,10 @@ public final class app/revanced/patches/youtube/misc/announcements/Announcements
public static final fun getAnnouncementsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatchKt {
public static final fun getAutoRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatchKt {
public static final fun getBackgroundPlaybackPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1631,6 +1720,14 @@ public final class app/revanced/patches/youtube/misc/extension/SharedExtensionPa
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatchKt {
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatchKt {
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/fix/playbackspeed/FIxPlaybackSpeedWhilePlayingPatchKt {
public static final fun getFixPlaybackSpeedWhilePlayingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1682,6 +1779,7 @@ public final class app/revanced/patches/youtube/misc/playercontrols/PlayerContro
public final class app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatchKt {
public static final fun getAddBottomControl ()Lkotlin/jvm/functions/Function1;
public static final fun getPlayerControlsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getPlayerControlsResourcePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
public static final fun initializeBottomControl (Ljava/lang/String;)V
public static final fun injectVisibilityCheckCall (Ljava/lang/String;)V
}
@@ -1692,6 +1790,9 @@ public final class app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPa
public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPatchKt {
public static final fun getVersionCheckPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
public static final fun is_19_03_or_greater ()Z
public static final fun is_19_04_or_greater ()Z
public static final fun is_19_16_or_greater ()Z
public static final fun is_19_17_or_greater ()Z
public static final fun is_19_18_or_greater ()Z
public static final fun is_19_23_or_greater ()Z
@@ -1716,20 +1817,10 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat
public static final fun is_20_10_or_greater ()Z
public static final fun is_20_14_or_greater ()Z
public static final fun is_20_15_or_greater ()Z
public static final fun is_20_19_or_greater ()Z
public static final fun is_20_20_or_greater ()Z
public static final fun is_20_21_or_greater ()Z
public static final fun is_20_22_or_greater ()Z
public static final fun is_20_26_or_greater ()Z
public static final fun is_20_28_or_greater ()Z
public static final fun is_20_30_or_greater ()Z
public static final fun is_20_31_or_greater ()Z
public static final fun is_20_34_or_greater ()Z
public static final fun is_20_37_or_greater ()Z
public static final fun is_20_39_or_greater ()Z
public static final fun is_20_41_or_greater ()Z
public static final fun is_20_45_or_greater ()Z
public static final fun is_20_46_or_greater ()Z
}
public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt {
public static final fun getRemoveTrackingQueryParameterPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/privacy/SanitizeSharingLinksPatchKt {
@@ -1771,6 +1862,10 @@ public final class app/revanced/patches/youtube/misc/spoof/UserAgentClientSpoofP
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatchKt {
public static final fun getZoomHapticsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatchKt {
public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1779,6 +1874,10 @@ public final class app/revanced/patches/youtube/video/codecs/DisableVideoCodecsP
public static final fun getDisableVideoCodecsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/video/hdr/DisableHdrPatchKt {
public static final fun getDisableHdrPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/video/information/VideoInformationPatchKt {
public static final fun getVideoInformationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun userSelectedPlaybackSpeedHook (Ljava/lang/String;Ljava/lang/String;)V
@@ -1835,6 +1934,14 @@ public final class app/revanced/patches/youtube/video/videoid/VideoIdPatchKt {
public static final fun hookVideoId (Ljava/lang/String;)V
}
public final class app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatchKt {
public static final fun getRestoreOldVideoQualityMenuPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatchKt {
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/util/BytecodeUtilsKt {
public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/util/smali/ExternalLabel;)V
@@ -1892,7 +1999,6 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;J)V
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Void;)V
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V
@@ -1902,7 +2008,6 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;J)V
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Void;)V
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V

View File

@@ -12,12 +12,6 @@ patches {
}
}
repositories {
mavenLocal()
gradlePluginPortal()
google()
}
dependencies {
// Required due to smali, or build fails. Can be removed once smali is bumped.
implementation(libs.guava)
@@ -49,22 +43,16 @@ tasks {
kotlin {
compilerOptions {
freeCompilerArgs.addAll(
"-Xexplicit-backing-fields",
"-Xcontext-parameters"
)
freeCompilerArgs = listOf("-Xcontext-receivers")
}
}
publishing {
repositories {
maven {
name = "GitHubPackages"
name = "githubPackages"
url = uri("https://maven.pkg.github.com/revanced/revanced-patches")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
credentials(PasswordCredentials::class)
}
}
}

View File

@@ -1,14 +1,14 @@
package app.revanced.patches.all.misc.activity.exportall
import app.revanced.patcher.patch.creatingResourcePatch
import app.revanced.patcher.patch.resourcePatch
@Suppress("unused", "ObjectPropertyName")
val `"Export all activities"` by creatingResourcePatch(
@Suppress("unused")
val exportAllActivitiesPatch = resourcePatch(
name = "Export all activities",
description = "Makes all app activities exportable.",
use = false,
) {
apply {
execute {
val exportedFlag = "android:exported"
document("AndroidManifest.xml").use { document ->

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.all.misc.adb
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
@@ -26,27 +26,31 @@ private val SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE = ImmutableMetho
"I"
)
private val getIntMethodReferences = listOf(
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE
)
private fun MethodReference.anyMethodSignatureMatches(vararg anyOf: MethodReference): Boolean {
return anyOf.any {
MethodUtil.methodSignaturesMatch(it, this)
}
}
@Suppress("unused", "ObjectPropertyName")
val `Hide ADB status` by creatingBytecodePatch(
@Suppress("unused")
val hideAdbStatusPatch = bytecodePatch(
name = "Hide ADB status",
description = "Hides enabled development settings and/or ADB.",
use = false,
) {
extendWith("extensions/all/misc/adb/hide-adb.rve")
dependsOn(
transformInstructionsPatch(
filterMap = filterMap@{ classDef, method, instruction, instructionIndex ->
val reference = instruction
.takeIf { it.opcode == Opcode.INVOKE_STATIC }
?.getReference<MethodReference>()
?.takeIf { reference ->
getIntMethodReferences.any { MethodUtil.methodSignaturesMatch(it, reference) }
?.takeIf {
it.anyMethodSignatureMatches(
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE
)
}
?: return@filterMap null

View File

@@ -1,17 +1,18 @@
package app.revanced.patches.all.misc.appicon
import app.revanced.patcher.patch.creatingResourcePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.util.asSequence
import app.revanced.util.childElementsSequence
import org.w3c.dom.Element
import java.util.logging.Logger
import org.w3c.dom.Element
@Suppress("unused", "ObjectPropertyName")
val `Hide app icon` by creatingResourcePatch(
@Suppress("unused")
val hideAppIconPatch = resourcePatch(
name = "Hide app icon",
description = "Hides the app icon from the Android launcher.",
use = false,
) {
apply {
execute {
document("AndroidManifest.xml").use { document ->
var changed = false
@@ -25,7 +26,6 @@ val `Hide app icon` by creatingResourcePatch(
"action" -> if (child.getAttribute("android:name") == "android.intent.action.MAIN") {
hasMainAction = true
}
"category" -> if (child.getAttribute("android:name") == "android.intent.category.LAUNCHER") {
launcherCategory = child
}

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.all.misc.build
import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.util.getReference

View File

@@ -11,148 +11,172 @@ val spoofBuildInfoPatch = bytecodePatch(
use = false,
) {
val board by stringOption(
key = "board",
default = null,
name = "Board",
title = "Board",
description = "The name of the underlying board, like \"goldfish\".",
)
val bootloader by stringOption(
key = "bootloader",
default = null,
name = "Bootloader",
title = "Bootloader",
description = "The system bootloader version number.",
)
val brand by stringOption(
key = "brand",
default = null,
name = "Brand",
title = "Brand",
description = "The consumer-visible brand with which the product/hardware will be associated, if any.",
)
val cpuAbi by stringOption(
key = "cpu-abi",
default = null,
name = "CPU ABI",
title = "CPU ABI",
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead.",
)
val cpuAbi2 by stringOption(
key = "cpu-abi-2",
default = null,
name = "CPU ABI 2",
title = "CPU ABI 2",
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead.",
)
val device by stringOption(
key = "device",
default = null,
name = "Device",
title = "Device",
description = "The name of the industrial design.",
)
val display by stringOption(
key = "display",
default = null,
name = "Display",
title = "Display",
description = "A build ID string meant for displaying to the user.",
)
val fingerprint by stringOption(
key = "fingerprint",
default = null,
name = "Fingerprint",
title = "Fingerprint",
description = "A string that uniquely identifies this build.",
)
val hardware by stringOption(
key = "hardware",
default = null,
name = "Hardware",
title = "Hardware",
description = "The name of the hardware (from the kernel command line or /proc).",
)
val host by stringOption(
key = "host",
default = null,
name = "Host",
title = "Host",
description = "The host.",
)
val id by stringOption(
key = "id",
default = null,
name = "ID",
title = "ID",
description = "Either a changelist number, or a label like \"M4-rc20\".",
)
val manufacturer by stringOption(
key = "manufacturer",
default = null,
name = "Manufacturer",
title = "Manufacturer",
description = "The manufacturer of the product/hardware.",
)
val model by stringOption(
key = "model",
default = null,
name = "Model",
title = "Model",
description = "The end-user-visible name for the end product.",
)
val odmSku by stringOption(
key = "odm-sku",
default = null,
name = "ODM SKU",
title = "ODM SKU",
description = "The SKU of the device as set by the original design manufacturer (ODM).",
)
val product by stringOption(
key = "product",
default = null,
name = "Product",
title = "Product",
description = "The name of the overall product.",
)
val radio by stringOption(
key = "radio",
default = null,
name = "Radio",
title = "Radio",
description = "This field was deprecated in API level 15. " +
"The radio firmware version is frequently not available when this class is initialized, " +
"leading to a blank or \"unknown\" value for this string. Use getRadioVersion() instead.",
"The radio firmware version is frequently not available when this class is initialized, " +
"leading to a blank or \"unknown\" value for this string. Use getRadioVersion() instead.",
)
val serial by stringOption(
key = "serial",
default = null,
name = "Serial",
title = "Serial",
description = "This field was deprecated in API level 26. Use getSerial() instead.",
)
val sku by stringOption(
key = "sku",
default = null,
name = "SKU",
title = "SKU",
description = "The SKU of the hardware (from the kernel command line).",
)
val socManufacturer by stringOption(
key = "soc-manufacturer",
default = null,
name = "SOC manufacturer",
title = "SOC manufacturer",
description = "The manufacturer of the device's primary system-on-chip.",
)
val socModel by stringOption(
key = "soc-model",
default = null,
name = "SOC model",
title = "SOC model",
description = "The model name of the device's primary system-on-chip.",
)
val tags by stringOption(
key = "tags",
default = null,
name = "Tags",
title = "Tags",
description = "Comma-separated tags describing the build, like \"unsigned,debug\".",
)
val time by longOption(
key = "time",
default = null,
name = "Time",
title = "Time",
description = "The time at which the build was produced, given in milliseconds since the UNIX epoch.",
)
val type by stringOption(
key = "type",
default = null,
name = "Type",
title = "Type",
description = "The type of build, like \"user\" or \"eng\".",
)
val user by stringOption(
key = "user",
default = null,
name = "User",
title = "User",
description = "The user.",
)
@@ -184,6 +208,7 @@ val spoofBuildInfoPatch = bytecodePatch(
type,
user,
)
}
},
)
}

View File

@@ -2,8 +2,8 @@
package app.revanced.patches.all.misc.connectivity.location.hide
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.fromMethodReference
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
@@ -11,8 +11,9 @@ import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Suppress("unused", "ObjectPropertyName")
val `Hide mock location` by creatingBytecodePatch(
@Suppress("unused")
val hideMockLocationPatch = bytecodePatch(
name = "Hide mock location",
description = "Prevents the app from knowing the device location is being mocked by a third party app.",
use = false,
) {

View File

@@ -1,18 +1,18 @@
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.intOption
import app.revanced.patcher.patch.stringOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
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.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.mutable.MutableMethod
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.*
import java.util.Locale
@Suppress("unused")
val spoofSimProviderPatch = bytecodePatch(
@@ -23,11 +23,13 @@ val spoofSimProviderPatch = bytecodePatch(
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }
fun isoCountryPatchOption(
name: String,
key: String,
title: String,
) = stringOption(
name,
key,
null,
countries,
title,
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
false,
validator = { it: String? -> it == null || it.uppercase() in countries.values },
@@ -35,29 +37,39 @@ val spoofSimProviderPatch = bytecodePatch(
fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999)
val networkCountryIso by isoCountryPatchOption("Network ISO country code")
val networkCountryIso by isoCountryPatchOption(
"networkCountryIso",
"Network ISO country code",
)
val networkOperator by intOption(
name = "MCC+MNC network operator code",
key = "networkOperator",
title = "MCC+MNC network operator code",
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the network operator.",
validator = { isMccMncValid(it) }
)
val networkOperatorName by stringOption(
name = "Network operator name",
key = "networkOperatorName",
title = "Network operator name",
description = "The full name of the network operator.",
)
val simCountryIso by isoCountryPatchOption("SIM ISO country code")
val simCountryIso by isoCountryPatchOption(
"simCountryIso",
"SIM ISO country code",
)
val simOperator by intOption(
name = "MCC+MNC SIM operator code",
key = "simOperator",
title = "MCC+MNC SIM operator code",
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the SIM operator.",
validator = { isMccMncValid(it) }
)
val simOperatorName by stringOption(
name = "SIM operator name",
key = "simOperatorName",
title = "SIM operator name",
description = "The full name of the SIM operator.",
)

View File

@@ -9,6 +9,9 @@ import app.revanced.util.getNode
import org.w3c.dom.Element
import java.io.File
val customNetworkSecurityPatch = resourcePatch(
name = "Custom network security",
description = "Allows trusting custom certificate authorities for a specific domain.",
@@ -16,21 +19,24 @@ val customNetworkSecurityPatch = resourcePatch(
) {
val targetDomains by stringsOption(
name = "Target domains",
key = "targetDomains",
title = "Target domains",
description = "List of domains to which the custom trust configuration will be applied (one domain per entry).",
default = listOf("example.com"),
required = true
)
val includeSubdomains by booleanOption(
name = "Include subdomains",
key = "includeSubdomains",
title = "Include subdomains",
description = "Applies the configuration to all subdomains of the target domains.",
default = false,
required = true
)
val customCAFilePaths by stringsOption(
name = "Custom CA file paths",
key = "customCAFilePaths",
title = "Custom CA file paths",
description = """
List of paths to files in PEM or DER format (one file path per entry).
@@ -45,29 +51,37 @@ val customNetworkSecurityPatch = resourcePatch(
)
val allowUserCerts by booleanOption(
name = "Trust user added CAs",
key = "allowUserCerts",
title = "Trust user added CAs",
description = "Makes an app trust certificates from the Android user store for the specified domains, and if the option \"Include Subdomains\" is enabled then also the subdomains.",
default = false,
required = true
)
val allowSystemCerts by booleanOption(
name = "Trust system CAs",
key = "allowSystemCerts",
title = "Trust system CAs",
description = "Makes an app trust certificates from the Android system store for the specified domains, and and if the option \"Include Subdomains\" is enabled then also the subdomains.",
default = true,
required = true
)
val allowCleartextTraffic by booleanOption(
name = "Allow cleartext traffic (HTTP)",
key = "allowCleartextTraffic",
title = "Allow cleartext traffic (HTTP)",
description = "Allows unencrypted HTTP traffic for the specified domains, and if \"Include Subdomains\" is enabled then also the subdomains.",
default = false,
required = true
)
val overridePins by booleanOption(
name = "Override certificate pinning",
key = "overridePins",
title = "Override certificate pinning",
description = "Overrides certificate pinning for the specified domains and their subdomains if the option \"Include Subdomains\" is enabled to allow inspecting app traffic via a proxy.",
default = false,
required = true
)
@@ -118,7 +132,7 @@ ${trustAnchorsXML.trimEnd()}
}
apply {
execute {
val nscFileNameBare = "network_security_config"
val resXmlDir = "res/xml"
val resRawDir = "res/raw"

View File

@@ -1,14 +1,14 @@
package app.revanced.patches.all.misc.debugging
import app.revanced.patcher.patch.creatingResourcePatch
import app.revanced.patcher.patch.resourcePatch
import org.w3c.dom.Element
@Suppress("ObjectPropertyName", "unused")
val `Enable Android debugging` by creatingResourcePatch(
val enableAndroidDebuggingPatch = resourcePatch(
name = "Enable Android debugging",
description = "Enables Android debugging capabilities. This can slow down the app.",
use = false,
) {
apply {
execute {
document("AndroidManifest.xml").use { document ->
val applicationNode =
document

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.all.misc.directory
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.directory.documentsprovider.exportInternalDataDocumentsProviderPatch
@Suppress("unused")
@Deprecated(
"Superseded by internalDataDocumentsProviderPatch",
ReplaceWith("internalDataDocumentsProviderPatch"),
)
val changeDataDirectoryLocationPatch = bytecodePatch(
// name = "Change data directory location",
description = "Changes the data directory in the application from " +
"the app internal storage directory to /sdcard/android/data accessible by root-less devices." +
"Using this patch can cause unexpected issues with some apps.",
use = false,
) {
dependsOn(exportInternalDataDocumentsProviderPatch)
}

View File

@@ -18,7 +18,7 @@ val exportInternalDataDocumentsProviderPatch = resourcePatch(
},
)
apply {
execute {
val documentsProviderClass =
"app.revanced.extension.all.misc.directory.documentsprovider.InternalDataDocumentsProvider"
@@ -28,7 +28,7 @@ val exportInternalDataDocumentsProviderPatch = resourcePatch(
.asSequence()
.any { it.attributes.getNamedItem("android:name")?.nodeValue == documentsProviderClass }
) {
return@apply
return@execute
}
val authority =

View File

@@ -14,7 +14,8 @@ val hexPatch = rawResourcePatch(
use = false,
) {
val replacements by stringsOption(
name = "Replacements",
key = "replacements",
title = "Replacements",
description = """
Hexadecimal patterns to search for and replace with another in a target file.

View File

@@ -1,13 +1,14 @@
package app.revanced.patches.all.misc.interaction.gestures
import app.revanced.patcher.patch.creatingResourcePatch
import app.revanced.patcher.patch.resourcePatch
@Suppress("unused", "ObjectPropertyName")
val `Predictive back gesture` by creatingResourcePatch(
@Suppress("unused")
val predictiveBackGesturePatch = resourcePatch(
name = "Predictive back gesture",
description = "Enables the predictive back gesture introduced on Android 13.",
use = false,
) {
apply {
execute {
val flag = "android:enableOnBackInvokedCallback"
document("AndroidManifest.xml").use { document ->

View File

@@ -1,21 +1,20 @@
@file:Suppress("ObjectPropertyName")
package app.revanced.patches.all.misc.network
import app.revanced.patcher.patch.creatingResourcePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.debugging.enableAndroidDebuggingPatch
import app.revanced.util.Utils.trimIndentMultiline
import org.w3c.dom.Element
import java.io.File
@Suppress("unused")
val `Override certificate pinning` by creatingResourcePatch(
val overrideCertificatePinningPatch = resourcePatch(
name = "Override certificate pinning",
description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
use = false,
) {
dependsOn(enableAndroidDebuggingPatch)
apply {
execute {
val resXmlDirectory = get("res/xml")
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.

View File

@@ -33,9 +33,10 @@ val changePackageNamePatch = resourcePatch(
use = false,
) {
packageNameOption = stringOption(
key = "packageName",
default = "Default",
values = mapOf("Default" to "Default"),
name = "Package name",
title = "Package name",
description = "The name of the package to rename the app to.",
required = true,
) {
@@ -43,20 +44,22 @@ val changePackageNamePatch = resourcePatch(
}
val updatePermissions by booleanOption(
key = "updatePermissions",
default = false,
name = "Update permissions",
title = "Update permissions",
description = "Update compatibility receiver permissions. " +
"Enabling this can fix installation errors, but this can also break features in certain apps.",
)
val updateProviders by booleanOption(
key = "updateProviders",
default = false,
name = "Update providers",
title = "Update providers",
description = "Update provider names declared by the app. " +
"Enabling this can fix installation errors, but this can also break features in certain apps.",
)
afterDependents {
finalize {
/**
* Apps that are confirmed to not work correctly with this patch.
* This is not an exhaustive list, and is only the apps with
@@ -77,7 +80,7 @@ val changePackageNamePatch = resourcePatch(
val packageName = manifest.getAttribute("package")
if (incompatibleAppPackages.contains(packageName)) {
return@afterDependents Logger.getLogger(this::class.java.name).severe(
return@finalize Logger.getLogger(this::class.java.name).severe(
"'$packageName' does not work correctly with \"Change package name\"",
)
}

View File

@@ -1,9 +1,10 @@
package app.revanced.patches.all.misc.playintegrity
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference

View File

@@ -215,8 +215,8 @@ fun addResources(
* @see addResourcesPatch
*/
fun addResources(
patch: Patch,
parseIds: (Patch) -> Map<AppId, Set<PatchId>> = {
patch: Patch<*>,
parseIds: (Patch<*>) -> Map<AppId, Set<PatchId>> = {
val patchId = patch.name ?: throw PatchException("Patch has no name")
val packages = patch.compatiblePackages ?: throw PatchException("Patch has no compatible packages")
@@ -273,9 +273,9 @@ val addResourcesPatch = resourcePatch(
from the temporary map to addResourcesPatch.
After all patches that depend on addResourcesPatch have been executed,
addResourcesPatch#afterDependents is finally called to add all staged resources to the app.
addResourcesPatch#finalize is finally called to add all staged resources to the app.
*/
apply {
execute {
stagedResources = buildMap {
/**
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
@@ -324,7 +324,7 @@ val addResourcesPatch = resourcePatch(
// Stage all resources to a temporary map.
// Staged resources consumed by addResourcesPatch#invoke(Patch)
// are later used in addResourcesPatch#afterDependents.
// are later used in addResourcesPatch#finalize.
try {
val addStringResources = { source: Value, dest: Value ->
addResources(source, dest, "strings", StringResource::fromNode)
@@ -343,7 +343,7 @@ val addResourcesPatch = resourcePatch(
* Adds all resources staged in [addResourcesPatch] to the app.
* This is called after all patches that depend on [addResourcesPatch] have been executed.
*/
afterDependents {
finalize {
operator fun MutableMap<String, Pair<Document, Node>>.invoke(
value: Value,
resource: BaseResource,
@@ -359,7 +359,7 @@ val addResourcesPatch = resourcePatch(
}
getOrPut(resourceFileName) {
this@afterDependents["res/$value/$resourceFileName.xml"].also {
this@finalize["res/$value/$resourceFileName.xml"].also {
it.parentFile?.mkdirs()
if (it.createNewFile()) {

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.all.misc.screencapture
import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
@@ -10,7 +10,7 @@ import org.w3c.dom.Element
private val removeCaptureRestrictionResourcePatch = resourcePatch(
description = "Sets allowAudioPlaybackCapture in manifest to true.",
) {
apply {
execute {
document("AndroidManifest.xml").use { document ->
// Get the application node.
val applicationNode =
@@ -28,8 +28,9 @@ private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/extension/all/misc/screencapture/removerestriction/RemoveScreenCaptureRestrictionPatch"
private const val EXTENSION_CLASS_DESCRIPTOR = "$EXTENSION_CLASS_DESCRIPTOR_PREFIX;"
@Suppress("unused", "ObjectPropertyName")
val `Remove screen capture restriction` by creatingBytecodePatch(
@Suppress("unused")
val removeScreenCaptureRestrictionPatch = bytecodePatch(
name = "Remove screen capture restriction",
description = "Removes the restriction of capturing audio from apps that normally wouldn't allow it.",
use = false,
) {

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.all.misc.screenshot
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
@@ -13,8 +13,9 @@ private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/extension/all/misc/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
private const val EXTENSION_CLASS_DESCRIPTOR = "$EXTENSION_CLASS_DESCRIPTOR_PREFIX;"
@Suppress("unused", "ObjectPropertyName")
val `Remove screenshot restriction` by creatingBytecodePatch(
@Suppress("unused")
val removeScreenshotRestrictionPatch = bytecodePatch(
name = "Remove screenshot restriction",
description = "Removes the restriction of taking screenshots in apps that normally wouldn't allow it.",
use = false,
) {

View File

@@ -13,11 +13,11 @@ val removeShareTargetsPatch = resourcePatch(
description = "Removes share targets like directly sharing to a frequent contact.",
use = false,
) {
apply {
execute {
try {
document("res/xml/shortcuts.xml")
} catch (_: FileNotFoundException) {
return@apply Logger.getLogger(this::class.java.name).warning(
return@execute Logger.getLogger(this::class.java.name).warning(
"The app has no shortcuts. No changes applied.")
}.use { document ->
val rootNode = document.getNode("shortcuts") as? Element ?: return@use

View File

@@ -22,7 +22,8 @@ val enableRomSignatureSpoofing = resourcePatch(
use = false,
) {
val signatureOrPath by stringOption(
name = "Signature or APK file path",
key = "signatureOrApkFilePath",
title = "Signature or APK file path",
validator = validator@{ signature ->
signature ?: return@validator false
@@ -31,7 +32,7 @@ val enableRomSignatureSpoofing = resourcePatch(
description = "The hex-encoded signature or path to an APK file with the desired signature.",
required = true,
)
apply {
execute {
document("AndroidManifest.xml").use { document ->
val permission = document.createElement("uses-permission").apply {
setAttribute("android:name", "android.permission.FAKE_PACKAGE_SIGNATURE")

View File

@@ -12,7 +12,7 @@ val setTargetSdkVersion34 = resourcePatch(
"For devices running Android 15+, this will disable edge-to-edge display.",
use = false,
) {
apply {
execute {
val targetSdkOverride = 34 // Android 14.
document("AndroidManifest.xml").use { document ->

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.all.misc.transformation
import app.revanced.patcher.extensions.replaceInstruction
import com.android.tools.smali.dexlib2.mutable.MutableMethod
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.instruction.Instruction

View File

@@ -1,8 +1,8 @@
package app.revanced.patches.all.misc.transformation
import com.android.tools.smali.dexlib2.mutable.MutableMethod
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.forEachInstructionAsSequence
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.findMutableMethodOf
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@@ -11,9 +11,39 @@ fun <T> transformInstructionsPatch(
filterMap: (ClassDef, Method, Instruction, Int) -> T?,
transform: (MutableMethod, T) -> Unit,
) = bytecodePatch {
apply {
forEachInstructionAsSequence { classDef, method, i, instruction ->
transform(method, filterMap(classDef, method, instruction, i) ?: return@forEachInstructionAsSequence)
// Returns the patch indices as a Sequence, which will execute lazily.
fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? =
method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
filterMap(classDef, method, instruction, index)
}
execute {
// Find all methods to patch
buildMap {
classes.forEach { classDef ->
val methods = buildList {
classDef.methods.forEach { method ->
// Since the Sequence executes lazily,
// using any() results in only calling
// filterMap until the first index has been found.
if (findPatchIndices(classDef, method)?.any() == true) add(method)
}
}
if (methods.isNotEmpty()) {
put(classDef, methods)
}
}
}.forEach { (classDef, methods) ->
// And finally transform the methods...
val mutableClass = proxy(classDef).mutableClass
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
?: return@methods
while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast())
}
}
}
}

View File

@@ -13,18 +13,19 @@ val changeVersionCodePatch = resourcePatch(
use = false,
) {
val versionCode by intOption(
key = "versionCode",
default = Int.MAX_VALUE,
values = mapOf(
"Lowest" to 1,
"Highest" to Int.MAX_VALUE,
),
name = "Version code",
title = "Version code",
description = "The version code to use. Using the highest value turns off app store " +
"updates and allows downgrading an existing app install to an older app version.",
required = true,
) { versionCode -> versionCode!! >= 1 }
apply {
execute {
document("AndroidManifest.xml").use { document ->
val manifestElement = document.getNode("manifest") as Element
manifestElement.setAttribute("android:versionCode", "$versionCode")

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.amazon
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused")
@@ -10,7 +10,7 @@ val deepLinkingPatch = bytecodePatch(
) {
compatibleWith("com.amazon.mShop.android.shopping")
apply {
execute {
deepLinkingFingerprint.method.addInstructions(
0,
"""

View File

@@ -10,7 +10,7 @@ val angulusPatch = bytecodePatch(name = "Hide ads") {
dependsOn(disableLicenseCheckPatch)
apply {
execute {
// Always return 0 as the daily measurement count.
getDailyMeasurementCountFingerprint.method.returnEarly(0)
}

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.backdrops.misc.pro
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint no longer resolves and will soon be deleted.")
internal val proUnlockFingerprint = fingerprint {
opcodes(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
)
custom { method, _ ->
method.name == "lambda\$existPurchase\$0" &&
method.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;"
}
}

View File

@@ -0,0 +1,24 @@
package app.revanced.patches.backdrops.misc.pro
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
@Deprecated("This patch no longer works and will soon be deleted.")
val proUnlockPatch = bytecodePatch{
compatibleWith("com.backdrops.wallpapers")
execute {
val registerIndex = proUnlockFingerprint.patternMatch!!.endIndex - 1
proUnlockFingerprint.method.apply {
val register = getInstruction<OneRegisterInstruction>(registerIndex).registerA
addInstruction(
proUnlockFingerprint.patternMatch!!.endIndex,
"const/4 v$register, 0x1",
)
}
}
}

View File

@@ -10,7 +10,7 @@ val removePlayLimitsPatch = bytecodePatch(
) {
compatibleWith("com.bandcamp.android")
apply {
execute {
handlePlaybackLimitsFingerprint.method.returnEarly()
}
}

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.cieid.restrictions.root
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused")
@@ -10,7 +10,7 @@ val bypassRootChecksPatch = bytecodePatch(
) {
compatibleWith("it.ipzs.cieid")
apply {
execute {
checkRootFingerprint.method.addInstruction(1, "return-void")
}
}

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.com.sbs.ondemand.tv
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch
import app.revanced.util.returnEarly
@@ -14,7 +14,7 @@ val removeAdsPatch = bytecodePatch(
dependsOn(disableLicenseCheckPatch)
apply {
execute {
shouldShowAdvertisingTVFingerprint.method.returnEarly(true)
shouldShowPauseAdFingerprint.method.returnEarly(false)

Some files were not shown because too many files have changed in this diff Show More