playerHeaders,
boolean showErrorToasts) {
Objects.requireNonNull(clientType);
@@ -128,21 +129,24 @@ public class StreamingDataRequest {
Objects.requireNonNull(playerHeaders);
final long startTime = System.currentTimeMillis();
- Logger.printDebug(() -> "Fetching video streams for: " + videoId + " using client: " + clientType);
try {
HttpURLConnection connection = PlayerRoutes.getPlayerResponseConnectionFromRoute(GET_STREAMING_DATA, clientType);
connection.setConnectTimeout(HTTP_TIMEOUT_MILLISECONDS);
connection.setReadTimeout(HTTP_TIMEOUT_MILLISECONDS);
+ boolean authHeadersIncludes = false;
+
for (String key : REQUEST_HEADER_KEYS) {
String value = playerHeaders.get(key);
+
if (value != null) {
if (key.equals(AUTHORIZATION_HEADER)) {
- if (!clientType.canLogin) {
+ if (!clientType.useAuth) {
Logger.printDebug(() -> "Not including request header: " + key);
continue;
}
+ authHeadersIncludes = true;
}
Logger.printDebug(() -> "Including request header: " + key);
@@ -150,7 +154,15 @@ public class StreamingDataRequest {
}
}
- String innerTubeBody = String.format(PlayerRoutes.createInnertubeBody(clientType), videoId);
+ if (!authHeadersIncludes && clientType.requiresAuth) {
+ Logger.printDebug(() -> "Skipping client since user is not logged in: " + clientType
+ + " videoId: " + videoId);
+ return null;
+ }
+
+ Logger.printDebug(() -> "Fetching video streams for: " + videoId + " using client: " + clientType);
+
+ String innerTubeBody = PlayerRoutes.createInnertubeBody(clientType, videoId);
byte[] requestBody = innerTubeBody.getBytes(StandardCharsets.UTF_8);
connection.setFixedLengthStreamingMode(requestBody.length);
connection.getOutputStream().write(requestBody);
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java
index 9606587dd..c4887b8e3 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java
@@ -90,4 +90,12 @@ public class ThemeHelper {
public static int getForegroundColor() {
return isDarkTheme() ? getLightThemeColor() : getDarkThemeColor();
}
+
+ public static int getToolbarBackgroundColor() {
+ final String colorName = isDarkTheme()
+ ? "yt_black3"
+ : "yt_white1";
+
+ return getColorInt(colorName);
+ }
}
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java
index cd1039128..9c4683bcc 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java
@@ -106,7 +106,8 @@ public final class LayoutComponentsFilter extends Filter {
inFeedSurvey = new StringFilterGroup(
Settings.HIDE_FEED_SURVEY,
"in_feed_survey",
- "slimline_survey"
+ "slimline_survey",
+ "feed_nudge"
);
final var medicalPanel = new StringFilterGroup(
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java
index 22d8df37e..ae2a09f92 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java
@@ -32,6 +32,11 @@ public class CustomPlaybackSpeedPatch {
*/
public static final float PLAYBACK_SPEED_MAXIMUM = 8;
+ /**
+ * Tap and hold speed.
+ */
+ private static final float TAP_AND_HOLD_SPEED;
+
/**
* Custom playback speeds.
*/
@@ -48,12 +53,27 @@ public class CustomPlaybackSpeedPatch {
private static String[] preferenceListEntries, preferenceListEntryValues;
static {
+ final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get();
+ if (holdSpeed > 0 && holdSpeed <= PLAYBACK_SPEED_MAXIMUM) {
+ TAP_AND_HOLD_SPEED = holdSpeed;
+ } else {
+ showInvalidCustomSpeedToast();
+ Settings.SPEED_TAP_AND_HOLD.resetToDefault();
+ TAP_AND_HOLD_SPEED = Settings.SPEED_TAP_AND_HOLD.get();
+ }
+
loadCustomSpeeds();
}
- private static void resetCustomSpeeds(@NonNull String toastMessage) {
- Utils.showToastLong(toastMessage);
- Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
+ /**
+ * Injection point.
+ */
+ public static float tapAndHoldSpeed() {
+ return TAP_AND_HOLD_SPEED;
+ }
+
+ private static void showInvalidCustomSpeedToast() {
+ Utils.showToastLong(str("revanced_custom_playback_speeds_invalid", PLAYBACK_SPEED_MAXIMUM));
}
private static void loadCustomSpeeds() {
@@ -74,17 +94,18 @@ public class CustomPlaybackSpeedPatch {
}
if (speedFloat >= PLAYBACK_SPEED_MAXIMUM) {
- resetCustomSpeeds(str("revanced_custom_playback_speeds_invalid", PLAYBACK_SPEED_MAXIMUM));
+ showInvalidCustomSpeedToast();
+ Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
loadCustomSpeeds();
return;
}
- customPlaybackSpeeds[i] = speedFloat;
- i++;
+ customPlaybackSpeeds[i++] = speedFloat;
}
} catch (Exception ex) {
Logger.printInfo(() -> "parse error", ex);
- resetCustomSpeeds(str("revanced_custom_playback_speeds_parse_exception"));
+ Utils.showToastLong(str("revanced_custom_playback_speeds_parse_exception"));
+ Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
loadCustomSpeeds();
}
}
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java
index 1812ca5c5..8ce9172b8 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java
@@ -1,26 +1,31 @@
package app.revanced.extension.youtube.settings;
+import static app.revanced.extension.shared.Utils.getResourceIdentifier;
+
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
+import android.os.Build;
import android.preference.PreferenceFragment;
+import android.util.TypedValue;
import android.view.ViewGroup;
-import android.widget.ImageButton;
import android.widget.TextView;
+import android.widget.Toolbar;
+
+import androidx.annotation.RequiresApi;
+
+import java.util.Objects;
+
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.ThemeHelper;
+import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFragment;
import app.revanced.extension.youtube.settings.preference.ReturnYouTubeDislikePreferenceFragment;
import app.revanced.extension.youtube.settings.preference.SponsorBlockPreferenceFragment;
-import java.util.Objects;
-
-import static app.revanced.extension.shared.Utils.getChildView;
-import static app.revanced.extension.shared.Utils.getResourceIdentifier;
-
/**
* Hooks LicenseActivity.
*
@@ -29,6 +34,14 @@ import static app.revanced.extension.shared.Utils.getResourceIdentifier;
@SuppressWarnings("unused")
public class LicenseActivityHook {
+ private static ViewGroup.LayoutParams toolbarLayoutParams;
+
+ public static void setToolbarLayoutParams(Toolbar toolbar) {
+ if (toolbarLayoutParams != null) {
+ toolbar.setLayoutParams(toolbarLayoutParams);
+ }
+ }
+
/**
* Injection point.
* Overrides the ReVanced settings language.
@@ -42,17 +55,36 @@ public class LicenseActivityHook {
return Utils.getContext();
}
+ /**
+ * Injection point.
+ */
+ public static boolean useCairoSettingsFragment(boolean original) {
+ // Early targets have layout issues and it's better to always force off.
+ if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
+ return false;
+ }
+ if (Settings.RESTORE_OLD_SETTINGS_MENUS.get()) {
+ return false;
+ }
+
+ // On the first launch of a clean install, forcing the cairo menu can give a
+ // half broken appearance because all the preference icons may not be available yet.
+ // 19.34+ cairo settings are always on, so it doesn't need to be forced anyway.
+ // Cairo setting will show on the next launch of the app.
+ return original;
+ }
+
/**
* Injection point.
*
* Hooks LicenseActivity#onCreate in order to inject our own fragment.
*/
+ @RequiresApi(api = Build.VERSION_CODES.N)
public static void initialize(Activity licenseActivity) {
try {
ThemeHelper.setActivityTheme(licenseActivity);
- licenseActivity.setContentView(
- getResourceIdentifier("revanced_settings_with_toolbar", "layout"));
- setBackButton(licenseActivity);
+ licenseActivity.setContentView(getResourceIdentifier(
+ "revanced_settings_with_toolbar", "layout"));
PreferenceFragment fragment;
String toolbarTitleResourceName;
@@ -75,7 +107,7 @@ public class LicenseActivityHook {
return;
}
- setToolbarTitle(licenseActivity, toolbarTitleResourceName);
+ createToolbar(licenseActivity, toolbarTitleResourceName);
//noinspection deprecation
licenseActivity.getFragmentManager()
@@ -87,28 +119,36 @@ public class LicenseActivityHook {
}
}
- private static void setToolbarTitle(Activity activity, String toolbarTitleResourceName) {
- ViewGroup toolbar = activity.findViewById(getToolbarResourceId());
- TextView toolbarTextView = Objects.requireNonNull(getChildView(toolbar, false,
- view -> view instanceof TextView));
- toolbarTextView.setText(getResourceIdentifier(toolbarTitleResourceName, "string"));
- }
-
+ @RequiresApi(api = Build.VERSION_CODES.N)
@SuppressLint("UseCompatLoadingForDrawables")
- private static void setBackButton(Activity activity) {
- ViewGroup toolbar = activity.findViewById(getToolbarResourceId());
- ImageButton imageButton = Objects.requireNonNull(getChildView(toolbar, false,
- view -> view instanceof ImageButton));
- imageButton.setImageDrawable(ReVancedPreferenceFragment.getBackButtonDrawable());
- imageButton.setOnClickListener(view -> activity.onBackPressed());
- }
+ private static void createToolbar(Activity activity, String toolbarTitleResourceName) {
+ // Replace dummy placeholder toolbar.
+ // This is required to fix submenu title alignment issue with Android ASOP 15+
+ ViewGroup toolBarParent = activity.findViewById(
+ getResourceIdentifier("revanced_toolbar_parent", "id"));
+ ViewGroup dummyToolbar = toolBarParent.findViewById(getResourceIdentifier(
+ "revanced_toolbar", "id"));
+ toolbarLayoutParams = dummyToolbar.getLayoutParams();
+ toolBarParent.removeView(dummyToolbar);
- private static int getToolbarResourceId() {
- final int toolbarResourceId = getResourceIdentifier("revanced_toolbar", "id");
- if (toolbarResourceId == 0) {
- throw new IllegalStateException("Could not find back button resource");
+ Toolbar toolbar = new Toolbar(toolBarParent.getContext());
+ toolbar.setBackgroundColor(ThemeHelper.getToolbarBackgroundColor());
+ toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable());
+ toolbar.setNavigationOnClickListener(view -> activity.onBackPressed());
+ toolbar.setTitle(getResourceIdentifier(toolbarTitleResourceName, "string"));
+
+ final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
+ Utils.getContext().getResources().getDisplayMetrics());
+ toolbar.setTitleMarginStart(margin);
+ toolbar.setTitleMarginEnd(margin);
+ TextView toolbarTextView = Utils.getChildView(toolbar, false,
+ view -> view instanceof TextView);
+ if (toolbarTextView != null) {
+ toolbarTextView.setTextColor(ThemeHelper.getForegroundColor());
}
- return toolbarResourceId;
+ setToolbarLayoutParams(toolbar);
+
+ toolBarParent.addView(toolbar, 0);
}
}
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java
index 93515648a..5817e5aca 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java
@@ -50,6 +50,7 @@ public class Settings extends BaseSettings {
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
// Speed
+ public static final FloatSetting SPEED_TAP_AND_HOLD = new FloatSetting("revanced_speed_tap_and_hold", 2.0f, true);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE);
public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE);
public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f);
@@ -203,6 +204,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_PLAYER_FLYOUT_WATCH_IN_VR = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
// General layout
+ public static final BooleanSetting RESTORE_OLD_SETTINGS_MENUS = new BooleanSetting("revanced_restore_old_settings_menus", FALSE, true);
public static final EnumSetting CHANGE_FORM_FACTOR = new EnumSetting<>("revanced_change_form_factor", FormFactor.DEFAULT, true, "revanced_change_form_factor_user_dialog_message");
public static final BooleanSetting BYPASS_IMAGE_REGION_RESTRICTIONS = new BooleanSetting("revanced_bypass_image_region_restrictions", FALSE, true);
public static final BooleanSetting GRADIENT_LOADING_SCREEN = new BooleanSetting("revanced_gradient_loading_screen", FALSE, true);
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java
index 02804c8c9..00cf12a35 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java
@@ -30,6 +30,7 @@ import app.revanced.extension.shared.settings.EnumSetting;
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
import app.revanced.extension.youtube.ThemeHelper;
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
+import app.revanced.extension.youtube.settings.LicenseActivityHook;
import app.revanced.extension.youtube.settings.Settings;
/**
@@ -140,9 +141,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
.getParent();
// Fix required for Android 15 and YT 19.45+
- // FIXME:
- // On Android 15 the text layout is not aligned the same as the parent
- // screen and it looks a little off. Otherwise this works.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
@@ -169,6 +167,8 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
toolbarTextView.setTextColor(ThemeHelper.getForegroundColor());
}
+ LicenseActivityHook.setToolbarLayoutParams(toolbar);
+
rootView.addView(toolbar, 0);
return false;
}
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java
index 0fc4283e2..5d43cb81f 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java
@@ -87,11 +87,6 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
// Android VR supports AV1 but all other clients do not.
if (clientType != ClientType.ANDROID_VR && clientType != ClientType.ANDROID_VR_NO_AUTH) {
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
-
- // Android Creator does not support HDR.
- if (clientType == ClientType.ANDROID_CREATOR) {
- summary += '\n' + str("revanced_spoof_video_streams_about_no_hdr");
- }
}
setTitle(title);
diff --git a/gradle.properties b/gradle.properties
index 8ef87aa3a..3fd9489ea 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
-version = 5.8.1
+version = 5.9.0-dev.4
diff --git a/patches/api/patches.api b/patches/api/patches.api
index 92ca7f946..a4075b866 100644
--- a/patches/api/patches.api
+++ b/patches/api/patches.api
@@ -603,16 +603,19 @@ public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatch
}
public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt {
+ 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 (Lkotlin/Pair;Ljava/util/Set;ILjava/lang/Object;)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 (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ public synthetic fun (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 equals (Ljava/lang/Object;)Z
+ public final fun getIcon ()Ljava/lang/String;
public final fun getKey ()Ljava/lang/String;
+ public final fun getLayout ()Ljava/lang/String;
public final fun getSummaryKey ()Ljava/lang/String;
public final fun getTag ()Ljava/lang/String;
public final fun getTitleKey ()Ljava/lang/String;
@@ -635,17 +638,19 @@ 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 ()V
- public fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
- public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
+ public synthetic fun (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 getKey ()Ljava/lang/String;
+ public final fun getLayout ()Ljava/lang/String;
public final fun getPreferences ()Ljava/util/Set;
public final fun getTitleKey ()Ljava/lang/String;
public abstract fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
}
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
- public fun (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;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 (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;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 (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 (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;
@@ -653,8 +658,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 (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
- public synthetic fun (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (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 (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;
@@ -662,6 +667,7 @@ public class app/revanced/patches/shared/misc/settings/preference/BasePreference
public final class app/revanced/patches/shared/misc/settings/preference/InputType : java/lang/Enum {
public static final field NUMBER Lapp/revanced/patches/shared/misc/settings/preference/InputType;
+ public static final field NUMBER_DECIMAL Lapp/revanced/patches/shared/misc/settings/preference/InputType;
public static final field TEXT Lapp/revanced/patches/shared/misc/settings/preference/InputType;
public static final field TEXT_CAP_CHARACTERS Lapp/revanced/patches/shared/misc/settings/preference/InputType;
public static final field TEXT_MULTI_LINE Lapp/revanced/patches/shared/misc/settings/preference/InputType;
@@ -672,8 +678,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 (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 (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 (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 (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
@@ -693,8 +699,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/ListPref
public fun ()V
public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/util/resource/ArrayResource;Lapp/revanced/util/resource/ArrayResource;)V
public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/util/resource/ArrayResource;Lapp/revanced/util/resource/ArrayResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
- public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- public synthetic fun (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 (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 (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 final fun getEntries ()Lapp/revanced/util/resource/ArrayResource;
public final fun getEntriesKey ()Ljava/lang/String;
public final fun getEntryValues ()Lapp/revanced/util/resource/ArrayResource;
@@ -703,22 +709,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 (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
- public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
+ public synthetic fun (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 (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
- public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (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 (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 (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 (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 (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 (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;
}
@@ -727,6 +733,7 @@ public final class app/revanced/patches/shared/misc/settings/preference/Preferen
public static final field BY_KEY Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
public static final field BY_TITLE Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
public static final field UNSORTED Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
+ public final fun appendSortType (Ljava/lang/String;)Ljava/lang/String;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getKeySuffix ()Ljava/lang/String;
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
@@ -745,8 +752,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 ()V
- public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (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 (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;
@@ -754,8 +761,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 ()V
- public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
- public synthetic fun (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 (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 (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;
}
@@ -1447,10 +1454,6 @@ public final class app/revanced/patches/youtube/video/speed/button/PlaybackSpeed
public static final fun getPlaybackSpeedButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
-public final class app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatchKt {
- public static final fun getSpeedUnavailableId ()J
-}
-
public final class app/revanced/patches/youtube/video/videoid/VideoIdPatchKt {
public static final fun getVideoIdPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun hookBackgroundPlayVideoId (Ljava/lang/String;)V
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt
index 7c343961c..d6d9df94c 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.shared.misc.settings
+import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResource
import app.revanced.patches.all.misc.resources.addResources
@@ -12,15 +13,22 @@ import app.revanced.util.getNode
import app.revanced.util.insertFirst
import org.w3c.dom.Node
+// TODO: Delete this on next major version bump.
+@Deprecated("Use non deprecated settings patch function")
+fun settingsPatch (
+ rootPreference: Pair,
+ preferences: Set,
+) = settingsPatch(listOf(rootPreference), preferences)
+
/**
* A resource patch that adds settings to a settings fragment.
*
- * @param rootPreference A pair of an intent preference and the name of the fragment file to add it to.
- * If null, no preference will be added.
+ * @param rootPreferences List of intent preferences and the name of the fragment file to add it to.
+ * File names that do not exist are ignored and not processed.
* @param preferences A set of preferences to add to the ReVanced fragment.
*/
-fun settingsPatch(
- rootPreference: Pair? = null,
+fun settingsPatch (
+ rootPreferences: List>? = null,
preferences: Set,
) = resourcePatch {
dependsOn(addResourcesPatch)
@@ -46,10 +54,20 @@ fun settingsPatch(
}
// Add the root preference to an existing fragment if needed.
- rootPreference?.let { (intentPreference, fragment) ->
- document("res/xml/$fragment.xml").use { document ->
- document.getNode("PreferenceScreen").addPreference(intentPreference, true)
+ rootPreferences?.let {
+ var modified = false
+
+ it.forEach { (intent, fileName) ->
+ val preferenceFileName = "res/xml/$fileName.xml"
+ if (get(preferenceFileName).exists()) {
+ document(preferenceFileName).use { document ->
+ document.getNode("PreferenceScreen").addPreference(intent, true)
+ }
+ modified = true
+ }
}
+
+ if (!modified) throw PatchException("No declared preference files exists: $rootPreferences")
}
// Add all preferences to the ReVanced fragment.
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreference.kt
index 509d0eea3..7c5cbf2cd 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreference.kt
@@ -9,6 +9,8 @@ import org.w3c.dom.Element
*
* @param key The key of the preference. If null, other parameters must be specified.
* @param titleKey The key of the preference title.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param summaryKey The key of the preference summary.
* @param tag The tag or full class name of the preference.
*/
@@ -17,6 +19,8 @@ abstract class BasePreference(
val key: String? = null,
val titleKey: String = "${key}_title",
val summaryKey: String? = "${key}_summary",
+ val icon: String? = null,
+ val layout: String? = null,
val tag: String
) {
/**
@@ -33,6 +37,11 @@ abstract class BasePreference(
key?.let { setAttribute("android:key", it) }
setAttribute("android:title", "@string/${titleKey}")
summaryKey?.let { addSummary(it) }
+ icon?.let {
+ setAttribute("android:icon", it)
+ setAttribute("app:iconSpaceReserved", "true")
+ }
+ layout?.let { setAttribute("android:layout", layout) }
}
override fun hashCode(): Int {
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen.kt
index 648f5eefd..8590e9965 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen.kt
@@ -24,16 +24,20 @@ abstract class BasePreferenceScreen(
key: String? = null,
titleKey: String = "${key}_title",
private val summaryKey: String? = "${key}_summary",
+ icon: String? = null,
+ layout: String? = null,
preferences: MutableSet = mutableSetOf(),
val categories: MutableSet = mutableSetOf(),
private val sorting: Sorting = Sorting.BY_TITLE,
- ) : BasePreferenceCollection(key, titleKey, preferences) {
+ ) : BasePreferenceCollection(key, titleKey, icon, layout, preferences) {
override fun transform(): PreferenceScreenPreference {
return PreferenceScreenPreference(
key,
titleKey,
summaryKey,
+ icon,
+ layout,
sorting,
// Screens and preferences are sorted at runtime by extension code,
// so title sorting uses the localized language in use.
@@ -56,12 +60,17 @@ abstract class BasePreferenceScreen(
open inner class Category(
key: String? = null,
titleKey: String = "${key}_title",
+ icon: String? = null,
+ layout: String? = null,
preferences: MutableSet = mutableSetOf(),
- ) : BasePreferenceCollection(key, titleKey, preferences) {
+ ) : BasePreferenceCollection(key, titleKey, icon, layout, preferences) {
override fun transform(): PreferenceCategory {
return PreferenceCategory(
key,
titleKey,
+ icon,
+ layout,
+ sorting,
preferences = preferences,
)
}
@@ -82,6 +91,8 @@ abstract class BasePreferenceScreen(
abstract class BasePreferenceCollection(
val key: String? = null,
val titleKey: String = "${key}_title",
+ val icon: String? = null,
+ val layout: String? = null,
val preferences: MutableSet = mutableSetOf(),
) {
abstract fun transform(): BasePreference
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/InputType.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/InputType.kt
index e5142d92e..88857cd7f 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/InputType.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/InputType.kt
@@ -5,4 +5,5 @@ enum class InputType(val type: String) {
TEXT_CAP_CHARACTERS("textCapCharacters"),
TEXT_MULTI_LINE("textMultiLine"),
NUMBER("number"),
+ NUMBER_DECIMAL("numberDecimal"),
}
\ No newline at end of file
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/IntentPreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/IntentPreference.kt
index dbc109ae8..2aef02dc8 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/IntentPreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/IntentPreference.kt
@@ -9,6 +9,8 @@ import org.w3c.dom.Document
* @param key Optional preference key.
* @param titleKey The preference title key.
* @param summaryKey The preference summary key.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param tag The preference tag.
* @param intent The intent to open.
*/
@@ -16,9 +18,11 @@ class IntentPreference(
key: String? = null,
titleKey: String = "${key}_title",
summaryKey: String? = "${key}_summary",
+ icon: String? = null,
+ layout: String? = null,
tag: String = "Preference",
val intent: Intent,
-) : BasePreference(key, titleKey, summaryKey, tag) {
+) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt
index e0338d29c..e6d9b440b 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt
@@ -10,6 +10,8 @@ import org.w3c.dom.Document
* @param key The preference key. If null, other parameters must be specified.
* @param titleKey The preference title key.
* @param summaryKey The preference summary key.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param tag The preference tag.
* @param entriesKey The entries array key.
* @param entryValuesKey The entry values array key.
@@ -19,10 +21,12 @@ class ListPreference(
key: String? = null,
titleKey: String = "${key}_title",
summaryKey: String? = "${key}_summary",
+ icon: String? = null,
+ layout: String? = null,
tag: String = "ListPreference",
val entriesKey: String? = "${key}_entries",
val entryValuesKey: String? = "${key}_entry_values"
-) : BasePreference(key, titleKey, summaryKey, tag) {
+) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
var entries: ArrayResource? = null
private set
var entryValues: ArrayResource? = null
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference.kt
index d4ecaae7e..b5ce55489 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference.kt
@@ -10,6 +10,8 @@ import org.w3c.dom.Document
*
* @param key The preference key.
* @param summaryKey The preference summary key.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param tag The tag or full class name of the preference.
* @param selectable If the preference is selectable and responds to tap events.
*/
@@ -18,9 +20,11 @@ class NonInteractivePreference(
key: String,
titleKey: String = "${key}_title",
summaryKey: String? = "${key}_summary",
+ icon: String? = null,
+ layout: String? = null,
tag: String = "Preference",
val selectable: Boolean = false,
-) : BasePreference(key, titleKey, summaryKey, tag) {
+) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
setAttribute("android:selectable", selectable.toString())
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceCategory.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceCategory.kt
index 67e82208f..8b2deb96e 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceCategory.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceCategory.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.shared.misc.settings.preference
+import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.util.resource.BaseResource
import org.w3c.dom.Document
@@ -8,6 +9,8 @@ import org.w3c.dom.Document
*
* @param key The key of the preference. If null, other parameters must be specified.
* @param titleKey The key of the preference title.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param tag The tag or full class name of the preference.
* @param preferences The preferences in this category.
*/
@@ -15,9 +18,12 @@ import org.w3c.dom.Document
open class PreferenceCategory(
key: String? = null,
titleKey: String = "${key}_title",
+ icon: String? = null,
+ layout: String? = null,
+ sorting: Sorting = Sorting.BY_TITLE,
tag: String = "PreferenceCategory",
val preferences: Set
-) : BasePreference(key, titleKey, null, tag) {
+) : BasePreference(sorting.appendSortType(key), titleKey, null, icon, layout, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference.kt
index 2b21a8413..a37e92947 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference.kt
@@ -9,6 +9,8 @@ import org.w3c.dom.Document
* @param key The key of the preference. If null, other parameters must be specified.
* @param titleKey The key of the preference title.
* @param summaryKey The key of the preference summary.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param sorting Sorting to use. If the sorting is not [Sorting.UNSORTED],
* then the key parameter will be modified to include the sort type.
* @param tag The tag or full class name of the preference.
@@ -19,6 +21,8 @@ open class PreferenceScreenPreference(
key: String? = null,
titleKey: String = "${key}_title",
summaryKey: String? = "${key}_summary",
+ icon: String? = null,
+ layout: String? = null,
sorting: Sorting = Sorting.BY_TITLE,
tag: String = "PreferenceScreen",
val preferences: Set,
@@ -28,7 +32,7 @@ open class PreferenceScreenPreference(
// or adding new attributes to the attrs.xml file.
// Since the key value is not currently used by the extensions,
// for now it's much simpler to modify the key to include the sort parameter.
-) : BasePreference(if (sorting == Sorting.UNSORTED) key else (key + sorting.keySuffix), titleKey, summaryKey, tag) {
+) : BasePreference(sorting.appendSortType(key), titleKey, summaryKey, icon, layout, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
preferences.forEach {
@@ -53,6 +57,16 @@ open class PreferenceScreenPreference(
/**
* Unspecified sorting.
*/
- UNSORTED("_sort_by_unsorted"),
+ UNSORTED("_sort_by_unsorted");
+
+ /**
+ * @return The key with this sort type appended to to the end,
+ * or if key is null then null is returned.
+ */
+ fun appendSortType(key: String?): String? {
+ if (key == null) return null
+ if (this == UNSORTED) return key
+ return key + keySuffix
+ }
}
}
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/SwitchPreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/SwitchPreference.kt
index e09d813a3..df9accd4b 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/SwitchPreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/SwitchPreference.kt
@@ -8,6 +8,8 @@ import org.w3c.dom.Document
*
* @param key The preference key. If null, other parameters must be specified.
* @param titleKey The preference title key.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param tag The preference tag.
* @param summaryOnKey The preference summary-on key.
* @param summaryOffKey The preference summary-off key.
@@ -17,9 +19,11 @@ class SwitchPreference(
key: String? = null,
titleKey: String = "${key}_title",
tag: String = "SwitchPreference",
+ icon: String? = null,
+ layout: String? = null,
val summaryOnKey: String = "${key}_summary_on",
val summaryOffKey: String = "${key}_summary_off"
-) : BasePreference(key, titleKey, null, tag) {
+) : BasePreference(key, titleKey, null, icon, layout, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
addSummary(summaryOnKey, SummaryType.ON)
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/TextPreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/TextPreference.kt
index 81de61569..397d4bd43 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/TextPreference.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/TextPreference.kt
@@ -9,6 +9,8 @@ import org.w3c.dom.Document
* @param key The preference key. If null, other parameters must be specified.
* @param titleKey The preference title key.
* @param summaryKey The preference summary key.
+ * @param icon The preference icon resource name.
+ * @param layout Layout declaration.
* @param tag The preference tag.
* @param inputType The preference input type.
*/
@@ -17,9 +19,11 @@ class TextPreference(
key: String? = null,
titleKey: String = "${key}_title",
summaryKey: String? = "${key}_summary",
+ icon: String? = null,
+ layout: String? = null,
tag: String = "app.revanced.extension.shared.settings.preference.ResettableEditTextPreference",
val inputType: InputType = InputType.TEXT
-) : BasePreference(key, titleKey, summaryKey, tag) {
+) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt
index 1a0dc6665..0f7647b4c 100644
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt
@@ -65,9 +65,12 @@ val navigationButtonsPatch = bytecodePatch(
)
if (is_19_25_or_greater) {
- preferences += SwitchPreference("revanced_disable_translucent_status_bar")
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_light")
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_dark")
+
+ PreferenceScreen.GENERAL_LAYOUT.addPreferences(
+ SwitchPreference("revanced_disable_translucent_status_bar")
+ )
}
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/DisableCairoSettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/DisableCairoSettingsPatch.kt
deleted file mode 100644
index cd058ca59..000000000
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/DisableCairoSettingsPatch.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.cairo
-
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.patch.bytecodePatch
-import app.revanced.patches.youtube.misc.backgroundplayback.backgroundPlaybackPatch
-import app.revanced.patches.youtube.misc.playservice.is_19_04_or_greater
-import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
-import app.revanced.util.indexOfFirstInstructionOrThrow
-import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
-import com.android.tools.smali.dexlib2.Opcode
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-
-internal val disableCairoSettingsPatch = bytecodePatch(
- description = "Disables Cairo Fragment from being used.",
-) {
- dependsOn(versionCheckPatch)
-
- execute {
- if (!is_19_04_or_greater) {
- return@execute
- }
-
- /**
- *
- * Cairo Fragment was added since YouTube v19.04.38.
- *
- * Disable this for the following reasons:
- * 1. [backgroundPlaybackPatch] does not activate the Minimized playback setting of Cairo Fragment.
- * 2. Some patches do not yet support Cairo Fragments (ie: custom Seekbar color).
- * 3. Settings preferences added by ReVanced are missing.
- *
- * Screenshots of the Cairo Fragment:
- * uYouPlus#1468.
- */
- cairoFragmentConfigFingerprint.method.apply {
- val literalIndex = indexOfFirstLiteralInstructionOrThrow(CAIRO_CONFIG_LITERAL_VALUE)
- val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
- val register = getInstruction(resultIndex).registerA
-
- addInstruction(
- resultIndex + 1,
- "const/16 v$register, 0x0",
- )
- }
- }
-}
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/Fingerprints.kt
deleted file mode 100644
index 5272adc07..000000000
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/Fingerprints.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.cairo
-
-import app.revanced.patcher.fingerprint
-import app.revanced.util.literal
-import com.android.tools.smali.dexlib2.AccessFlags
-
-/**
- * Added in YouTube v19.04.38.
- *
- * When this value is true, Cairo Fragment is used.
- * In this case, some of the patches may be broken, so set this value to FALSE.
- */
-internal const val CAIRO_CONFIG_LITERAL_VALUE = 45532100L
-
-internal val cairoFragmentConfigFingerprint = fingerprint {
- accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
- returns("Z")
- literal { CAIRO_CONFIG_LITERAL_VALUE }
-}
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt
index 42298d82f..c86620384 100644
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt
@@ -21,3 +21,14 @@ internal val setThemeFingerprint = fingerprint {
opcodes(Opcode.RETURN_OBJECT)
literal { appearanceStringId }
}
+
+/**
+ * Added in YouTube v19.04.38.
+ */
+internal const val CAIRO_CONFIG_LITERAL_VALUE = 45532100L
+
+internal val cairoFragmentConfigFingerprint = fingerprint {
+ accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
+ returns("Z")
+ literal { CAIRO_CONFIG_LITERAL_VALUE }
+}
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt
index 68c058b7b..8bf7cfc06 100644
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt
@@ -18,8 +18,10 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPref
import app.revanced.patches.shared.misc.settings.settingsPatch
import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
-import app.revanced.patches.youtube.misc.fix.cairo.disableCairoSettingsPatch
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
+import app.revanced.patches.youtube.misc.playservice.is_19_04_or_greater
+import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
+import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -43,13 +45,28 @@ private val settingsResourcePatch = resourcePatch {
dependsOn(
resourceMappingPatch,
settingsPatch(
- rootPreference = IntentPreference(
- titleKey = "revanced_settings_title",
- summaryKey = null,
- intent = newIntent("revanced_settings_intent"),
- ) to "settings_fragment",
- preferences,
- ),
+ listOf(
+ IntentPreference(
+ titleKey = "revanced_settings_title",
+ summaryKey = null,
+ intent = newIntent("revanced_settings_intent"),
+ ) to "settings_fragment",
+ PreferenceCategory(
+ titleKey = "revanced_settings_title",
+ layout = "@layout/preference_group_title",
+ preferences = setOf(
+ IntentPreference(
+ titleKey = "revanced_settings_submenu_title",
+ summaryKey = null,
+ icon = "@drawable/revanced_settings_icon",
+ layout = "@layout/preference_with_icon",
+ intent = newIntent("revanced_settings_intent"),
+ )
+ )
+ ) to "settings_fragment_cairo",
+ ),
+ preferences
+ )
)
execute {
@@ -57,6 +74,7 @@ private val settingsResourcePatch = resourcePatch {
appearanceStringId = resourceMappings["string", "app_theme_appearance_dark"]
arrayOf(
+ ResourceGroup("drawable", "revanced_settings_icon.xml"),
ResourceGroup("layout", "revanced_settings_with_toolbar.xml"),
).forEach { resourceGroup ->
copyResources("settings", resourceGroup)
@@ -79,7 +97,6 @@ private val settingsResourcePatch = resourcePatch {
// Remove horizontal divider from the settings Preferences
// To better match the appearance of the stock YouTube settings.
document("res/values/styles.xml").use { document ->
-
arrayOf(
"Theme.YouTube.Settings",
"Theme.YouTube.Settings.Dark",
@@ -99,7 +116,6 @@ private val settingsResourcePatch = resourcePatch {
// Some devices freak out if undeclared data is passed to an intent,
// and this change appears to fix the issue.
document("AndroidManifest.xml").use { document ->
-
val licenseElement = document.childNodes.findElementByAttributeValueOrThrow(
"android:name",
"com.google.android.libraries.social.licenses.LicenseActivity",
@@ -123,7 +139,7 @@ val settingsPatch = bytecodePatch(
sharedExtensionPatch,
settingsResourcePatch,
addResourcesPatch,
- disableCairoSettingsPatch,
+ versionCheckPatch,
fixPlaybackSpeedWhilePlayingPatch,
// Currently there is no easy way to make a mandatory patch,
// so for now this is a dependent of this patch.
@@ -147,6 +163,12 @@ val settingsPatch = bytecodePatch(
selectable = true,
)
+ if (is_19_34_or_greater) {
+ PreferenceScreen.GENERAL_LAYOUT.addPreferences(
+ SwitchPreference("revanced_restore_old_settings_menus")
+ )
+ }
+
PreferenceScreen.MISC.addPreferences(
TextPreference(
key = null,
@@ -224,6 +246,14 @@ val settingsPatch = bytecodePatch(
methods.add(attachBaseContext)
}
+ // Add setting to force cairo settings fragment on/off.
+ if (is_19_04_or_greater) {
+ cairoFragmentConfigFingerprint.method.insertFeatureFlagBooleanOverride(
+ CAIRO_CONFIG_LITERAL_VALUE,
+ "$activityHookClassDescriptor->useCairoSettingsFragment(Z)Z"
+ )
+ }
+
}
finalize {
@@ -259,17 +289,15 @@ object PreferenceScreen : BasePreferenceScreen() {
key = "revanced_settings_screen_03_feed",
summaryKey = null,
)
- val PLAYER = Screen(
- key = "revanced_settings_screen_04_player",
+ val GENERAL_LAYOUT = Screen(
+ key = "revanced_settings_screen_04_general",
summaryKey = null,
)
- val GENERAL_LAYOUT = Screen(
- key = "revanced_settings_screen_05_general",
+ val PLAYER = Screen(
+ key = "revanced_settings_screen_05_player",
summaryKey = null,
)
- // Don't sort, as related preferences are scattered apart.
- // Can use title sorting after PreferenceCategory support is added.
val SHORTS = Screen(
key = "revanced_settings_screen_06_shorts",
summaryKey = null,
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt
index bd6668993..695642c5a 100644
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt
@@ -17,22 +17,26 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.patches.shared.misc.settings.preference.InputType
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.shared.misc.settings.preference.TextPreference
+import app.revanced.patches.youtube.interaction.seekbar.disableFastForwardNoticeFingerprint
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
+import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
+import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTreeHook
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField
-var speedUnavailableId = -1L
- internal set
+internal var speedUnavailableId = -1L
+ private set
private val customPlaybackSpeedResourcePatch = resourcePatch {
dependsOn(resourceMappingPatch)
@@ -61,6 +65,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
recyclerViewTreeHookPatch,
customPlaybackSpeedResourcePatch,
addResourcesPatch,
+ versionCheckPatch
)
execute {
@@ -71,6 +76,12 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
TextPreference("revanced_custom_playback_speeds", inputType = InputType.TEXT_MULTI_LINE),
)
+ if (is_19_25_or_greater) {
+ PreferenceScreen.VIDEO.addPreferences(
+ TextPreference("revanced_speed_tap_and_hold", inputType = InputType.NUMBER_DECIMAL),
+ )
+ }
+
// Replace the speeds float array with custom speeds.
speedArrayGeneratorFingerprint.method.apply {
val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "size" }
@@ -166,5 +177,27 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
// endregion
+
+
+ // region Custom tap and hold 2x speed.
+
+ if (is_19_25_or_greater) {
+ disableFastForwardNoticeFingerprint.method.apply {
+ val index = indexOfFirstInstructionOrThrow {
+ (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits()
+ }
+ val register = getInstruction(index).registerA
+
+ addInstructions(
+ index + 1,
+ """
+ invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->tapAndHoldSpeed()F
+ move-result v$register
+ """
+ )
+ }
+ }
+
+ // endregion
}
}
diff --git a/patches/src/main/kotlin/app/revanced/util/resource/StringResource.kt b/patches/src/main/kotlin/app/revanced/util/resource/StringResource.kt
index 915536b77..cb9c0b213 100644
--- a/patches/src/main/kotlin/app/revanced/util/resource/StringResource.kt
+++ b/patches/src/main/kotlin/app/revanced/util/resource/StringResource.kt
@@ -24,31 +24,31 @@ class StringResource(
if (value.startsWith('"') && value.endsWith('"')) {
// Raw strings allow unescaped single quote but not double quote.
if (!value.substring(1, value.length - 1).contains(Regex("(?
الإعلانات
مُصغَّرات فيديو بديلة
الموجز
- المشغل
- التصميم العام
+ عام
+ مشغل
شريط تقدم الفيديو
التحكم عن طريق إيماءة التمرير
- إعدادات متنوعة
+ متنوع
الفيديو
+ إعادة قوائم إعدادات قديمة
تعطيل تشغيل فيديوهات Shorts في الخلفية
@@ -1341,6 +1342,8 @@ Second \"item\" text"