Skip to content

Commit 2e9d695

Browse files
authored
feat(YouTube - Debugging): Add setting to block experimental client flags (#6196)
1 parent 81f8369 commit 2e9d695

36 files changed

+1174
-281
lines changed

extensions/primevideo/src/main/java/app/revanced/extension/primevideo/videoplayer/PlaybackSpeedPatch.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import app.revanced.extension.shared.Logger;
1818
import app.revanced.extension.shared.Utils;
19+
import app.revanced.extension.shared.ui.Dim;
1920

2021
import com.amazon.video.sdk.player.Player;
2122

@@ -64,9 +65,8 @@ private static ImageView createSpeedButton(Context context) {
6465
SpeedIconDrawable speedIcon = new SpeedIconDrawable();
6566
speedButton.setImageDrawable(speedIcon);
6667

67-
int buttonSize = Utils.dipToPixels(48);
68-
speedButton.setMinimumWidth(buttonSize);
69-
speedButton.setMinimumHeight(buttonSize);
68+
speedButton.setMinimumWidth(Dim.dp48);
69+
speedButton.setMinimumHeight(Dim.dp48);
7070

7171
return speedButton;
7272
}
@@ -197,11 +197,11 @@ public int getOpacity() {
197197

198198
@Override
199199
public int getIntrinsicWidth() {
200-
return Utils.dipToPixels(32);
200+
return Dim.dp32;
201201
}
202202

203203
@Override
204204
public int getIntrinsicHeight() {
205-
return Utils.dipToPixels(32);
205+
return Dim.dp32;
206206
}
207207
}

extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
import android.preference.Preference;
2424
import android.preference.PreferenceGroup;
2525
import android.preference.PreferenceScreen;
26-
import android.util.DisplayMetrics;
2726
import android.util.Pair;
28-
import android.util.TypedValue;
2927
import android.view.Gravity;
3028
import android.view.View;
3129
import android.view.ViewGroup;
@@ -63,6 +61,7 @@
6361
import app.revanced.extension.shared.settings.BaseSettings;
6462
import app.revanced.extension.shared.settings.BooleanSetting;
6563
import app.revanced.extension.shared.settings.preference.ReVancedAboutPreference;
64+
import app.revanced.extension.shared.ui.Dim;
6665

6766
@SuppressWarnings("NewApi")
6867
public class Utils {
@@ -801,13 +800,10 @@ public static void hideViewByLayoutParams(View view) {
801800
public static void setDialogWindowParameters(Window window, int gravity, int yOffsetDip, int widthPercentage, boolean dimAmount) {
802801
WindowManager.LayoutParams params = window.getAttributes();
803802

804-
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
805-
int portraitWidth = Math.min(displayMetrics.widthPixels, displayMetrics.heightPixels);
806-
807-
params.width = (int) (portraitWidth * (widthPercentage / 100.0f)); // Set width based on parameters.
803+
params.width = Dim.pctPortraitWidth(widthPercentage);
808804
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
809805
params.gravity = gravity;
810-
params.y = yOffsetDip > 0 ? dipToPixels(yOffsetDip) : 0;
806+
params.y = yOffsetDip > 0 ? Dim.dp(yOffsetDip) : 0;
811807
if (dimAmount) {
812808
params.dimAmount = 0f;
813809
}
@@ -816,18 +812,6 @@ public static void setDialogWindowParameters(Window window, int gravity, int yOf
816812
window.setBackgroundDrawable(null); // Remove default dialog background
817813
}
818814

819-
/**
820-
* Creates an array of corner radii for a rounded rectangle shape.
821-
*
822-
* @param dp Radius in density-independent pixels (dip) to apply to all corners.
823-
* @return An array of eight float values representing the corner radii
824-
* (top-left, top-right, bottom-right, bottom-left).
825-
*/
826-
public static float[] createCornerRadii(float dp) {
827-
final float radius = dipToPixels(dp);
828-
return new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
829-
}
830-
831815
/**
832816
* Sets the theme light color used by the app.
833817
*/
@@ -1132,42 +1116,6 @@ public static int getColorFromString(String colorString) throws IllegalArgumentE
11321116
return getResourceColor(colorString);
11331117
}
11341118

1135-
/**
1136-
* Converts dip value to actual device pixels.
1137-
*
1138-
* @param dip The density-independent pixels value.
1139-
* @return The device pixel value.
1140-
*/
1141-
public static int dipToPixels(float dip) {
1142-
return (int) TypedValue.applyDimension(
1143-
TypedValue.COMPLEX_UNIT_DIP,
1144-
dip,
1145-
Resources.getSystem().getDisplayMetrics()
1146-
);
1147-
}
1148-
1149-
/**
1150-
* Converts a percentage of the screen height to actual device pixels.
1151-
*
1152-
* @param percentage The percentage of the screen height (e.g., 30 for 30%).
1153-
* @return The device pixel value corresponding to the percentage of screen height.
1154-
*/
1155-
public static int percentageHeightToPixels(int percentage) {
1156-
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
1157-
return (int) (metrics.heightPixels * (percentage / 100.0f));
1158-
}
1159-
1160-
/**
1161-
* Converts a percentage of the screen width to actual device pixels.
1162-
*
1163-
* @param percentage The percentage of the screen width (e.g., 30 for 30%).
1164-
* @return The device pixel value corresponding to the percentage of screen width.
1165-
*/
1166-
public static int percentageWidthToPixels(int percentage) {
1167-
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
1168-
return (int) (metrics.widthPixels * (percentage / 100.0f));
1169-
}
1170-
11711119
/**
11721120
* Uses {@link #adjustColorBrightness(int, float)} depending if light or dark mode is active.
11731121
*/

extensions/shared/library/src/main/java/app/revanced/extension/shared/patches/EnableDebuggingPatch.java

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package app.revanced.extension.shared.patches;
22

3+
import static java.lang.Boolean.TRUE;
4+
5+
import java.util.HashSet;
6+
import java.util.Set;
37
import java.util.concurrent.ConcurrentHashMap;
48
import java.util.concurrent.ConcurrentMap;
59

@@ -21,12 +25,28 @@ public final class EnableDebuggingPatch {
2125
? new ConcurrentHashMap<>(800, 0.5f, 1)
2226
: null;
2327

28+
private static final Set<Long> DISABLED_FEATURE_FLAGS = parseFlags(BaseSettings.DISABLED_FEATURE_FLAGS.get());
29+
30+
// Log all disabled flags on app startup.
31+
static {
32+
if (LOG_FEATURE_FLAGS && !DISABLED_FEATURE_FLAGS.isEmpty()) {
33+
StringBuilder sb = new StringBuilder("Disabled feature flags:\n");
34+
for (Long flag : DISABLED_FEATURE_FLAGS) {
35+
sb.append(" ").append(flag).append('\n');
36+
}
37+
Logger.printDebug(sb::toString);
38+
}
39+
}
40+
2441
/**
2542
* Injection point.
2643
*/
2744
public static boolean isBooleanFeatureFlagEnabled(boolean value, Long flag) {
2845
if (LOG_FEATURE_FLAGS && value) {
29-
if (featureFlags.putIfAbsent(flag, true) == null) {
46+
if (DISABLED_FEATURE_FLAGS.contains(flag)) {
47+
return false;
48+
}
49+
if (featureFlags.putIfAbsent(flag, TRUE) == null) {
3050
Logger.printDebug(() -> "boolean feature is enabled: " + flag);
3151
}
3252
}
@@ -70,10 +90,44 @@ public static String isStringFeatureFlagEnabled(String value, long flag, String
7090
if (LOG_FEATURE_FLAGS && !defaultValue.equals(value)) {
7191
if (featureFlags.putIfAbsent(flag, true) == null) {
7292
Logger.printDebug(() -> " string feature is enabled: " + flag
73-
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
93+
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
7494
}
7595
}
7696

7797
return value;
7898
}
99+
100+
/**
101+
* Get all logged feature flags.
102+
* @return Set of all known flags
103+
*/
104+
public static Set<Long> getAllLoggedFlags() {
105+
if (featureFlags != null) {
106+
return new HashSet<>(featureFlags.keySet());
107+
}
108+
109+
return new HashSet<>();
110+
}
111+
112+
/**
113+
* Public method for parsing flags.
114+
* @param flags String containing newline-separated flag IDs
115+
* @return Set of parsed flag IDs
116+
*/
117+
public static Set<Long> parseFlags(String flags) {
118+
Set<Long> parsedFlags = new HashSet<>();
119+
if (!flags.isBlank()) {
120+
for (String flag : flags.split("\n")) {
121+
String trimmedFlag = flag.trim();
122+
if (trimmedFlag.isEmpty()) continue; // Skip empty lines.
123+
try {
124+
parsedFlags.add(Long.parseLong(trimmedFlag));
125+
} catch (NumberFormatException e) {
126+
Logger.printException(() -> "Invalid flag ID: " + flag);
127+
}
128+
}
129+
}
130+
131+
return parsedFlags;
132+
}
79133
}

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseActivityHook.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import android.content.Context;
88
import android.graphics.drawable.Drawable;
99
import android.preference.PreferenceFragment;
10-
import android.util.TypedValue;
1110
import android.view.View;
1211
import android.view.ViewGroup;
1312
import android.widget.TextView;
@@ -16,6 +15,7 @@
1615
import app.revanced.extension.shared.Logger;
1716
import app.revanced.extension.shared.Utils;
1817
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
18+
import app.revanced.extension.shared.ui.Dim;
1919

2020
/**
2121
* Base class for hooking activities to inject a custom PreferenceFragment with a toolbar.
@@ -109,13 +109,12 @@ protected void createToolbar(Activity activity, PreferenceFragment fragment) {
109109
toolbar.setNavigationOnClickListener(getNavigationClickListener(activity));
110110
toolbar.setTitle(STRING_REVANCED_SETTINGS_TITLE);
111111

112-
final int margin = Utils.dipToPixels(16);
113-
toolbar.setTitleMarginStart(margin);
114-
toolbar.setTitleMarginEnd(margin);
112+
toolbar.setTitleMarginStart(Dim.dp16);
113+
toolbar.setTitleMarginEnd(Dim.dp16);
115114
TextView toolbarTextView = Utils.getChildView(toolbar, false, view -> view instanceof TextView);
116115
if (toolbarTextView != null) {
117116
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
118-
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
117+
toolbarTextView.setTextSize(20);
119118
}
120119
setToolbarLayoutParams(toolbar);
121120

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@ public class BaseSettings {
4242

4343
public static final EnumSetting<BrandingTheme> CUSTOM_BRANDING_ICON = new EnumSetting<>("revanced_custom_branding_icon", BrandingTheme.ORIGINAL, true);
4444
public static final IntegerSetting CUSTOM_BRANDING_NAME = new IntegerSetting("revanced_custom_branding_name", 1, true);
45+
46+
public static final StringSetting DISABLED_FEATURE_FLAGS = new StringSetting("revanced_disabled_feature_flags", "", true, parent(DEBUG));
4547
}

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerPreference.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package app.revanced.extension.shared.settings.preference;
22

33
import static app.revanced.extension.shared.StringRef.str;
4-
import static app.revanced.extension.shared.Utils.dipToPixels;
54
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
65

76
import android.app.Dialog;
@@ -37,6 +36,7 @@
3736
import app.revanced.extension.shared.settings.StringSetting;
3837
import app.revanced.extension.shared.ui.ColorDot;
3938
import app.revanced.extension.shared.ui.CustomDialog;
39+
import app.revanced.extension.shared.ui.Dim;
4040

4141
/**
4242
* A custom preference for selecting a color via a hexadecimal code or a color picker dialog.
@@ -310,11 +310,8 @@ protected void showDialog(Bundle state) {
310310
inputLayout.setGravity(Gravity.CENTER_VERTICAL);
311311

312312
dialogColorDot = new View(context);
313-
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(
314-
dipToPixels(20),
315-
dipToPixels(20)
316-
);
317-
previewParams.setMargins(dipToPixels(16), 0, dipToPixels(10), 0);
313+
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(Dim.dp20,Dim.dp20);
314+
previewParams.setMargins(Dim.dp16, 0, Dim.dp10, 0);
318315
dialogColorDot.setLayoutParams(previewParams);
319316
inputLayout.addView(dialogColorDot);
320317
updateDialogColorDot();

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerView.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package app.revanced.extension.shared.settings.preference;
22

3-
import static app.revanced.extension.shared.Utils.dipToPixels;
43
import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.getColorString;
54

65
import android.annotation.SuppressLint;
@@ -21,6 +20,7 @@
2120

2221
import app.revanced.extension.shared.Logger;
2322
import app.revanced.extension.shared.Utils;
23+
import app.revanced.extension.shared.ui.Dim;
2424

2525
/**
2626
* A custom color picker view that allows the user to select a color using a hue slider, a saturation-value selector
@@ -54,28 +54,28 @@ public interface OnColorChangedListener {
5454
}
5555

5656
/** Expanded touch area for the hue and opacity bars to increase the touch-sensitive area. */
57-
public static final float TOUCH_EXPANSION = dipToPixels(20f);
57+
public static final float TOUCH_EXPANSION = Dim.dp20;
5858

5959
/** Margin between different areas of the view (saturation-value selector, hue bar, and opacity slider). */
60-
private static final float MARGIN_BETWEEN_AREAS = dipToPixels(24);
60+
private static final float MARGIN_BETWEEN_AREAS = Dim.dp24;
6161

6262
/** Padding around the view. */
63-
private static final float VIEW_PADDING = dipToPixels(16);
63+
private static final float VIEW_PADDING = Dim.dp16;
6464

6565
/** Height of the hue bar. */
66-
private static final float HUE_BAR_HEIGHT = dipToPixels(12);
66+
private static final float HUE_BAR_HEIGHT = Dim.dp12;
6767

6868
/** Height of the opacity slider. */
69-
private static final float OPACITY_BAR_HEIGHT = dipToPixels(12);
69+
private static final float OPACITY_BAR_HEIGHT = Dim.dp12;
7070

7171
/** Corner radius for the hue bar. */
72-
private static final float HUE_CORNER_RADIUS = dipToPixels(6);
72+
private static final float HUE_CORNER_RADIUS = Dim.dp6;
7373

7474
/** Corner radius for the opacity slider. */
75-
private static final float OPACITY_CORNER_RADIUS = dipToPixels(6);
75+
private static final float OPACITY_CORNER_RADIUS = Dim.dp6;
7676

7777
/** Radius of the selector handles. */
78-
private static final float SELECTOR_RADIUS = dipToPixels(12);
78+
private static final float SELECTOR_RADIUS = Dim.dp12;
7979

8080
/** Stroke width for the selector handle outlines. */
8181
private static final float SELECTOR_STROKE_WIDTH = 8;
@@ -202,7 +202,7 @@ public void setOpacitySliderEnabled(boolean enabled) {
202202
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
203203
final float DESIRED_ASPECT_RATIO = 0.8f; // height = width * 0.8
204204

205-
final int minWidth = dipToPixels(250);
205+
final int minWidth = Dim.dp(250);
206206
final int minHeight = (int) (minWidth * DESIRED_ASPECT_RATIO) + (int) (HUE_BAR_HEIGHT + MARGIN_BETWEEN_AREAS)
207207
+ (opacitySliderEnabled ? (int) (OPACITY_BAR_HEIGHT + MARGIN_BETWEEN_AREAS) : 0);
208208

0 commit comments

Comments
 (0)