Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d2e853f
feat(YouTube Music): Add Settings patch
MarcaDian Sep 14, 2025
328a3f6
set appropriate theme style
MarcaDian Sep 14, 2025
c39fa6d
typo
MarcaDian Sep 14, 2025
889e7db
Merge remote-tracking branch 'ReVanced/dev' into music-settings
MarcaDian Sep 14, 2025
904e7af
refactor to abstract classes
MarcaDian Sep 14, 2025
951194e
remove unused summary
MarcaDian Sep 14, 2025
f52cfbf
creating a settings template
MarcaDian Sep 15, 2025
173b488
it works buggy, can come back to it later.
MarcaDian Sep 15, 2025
a32ea7a
remove horizontal divider from the settings preferences
MarcaDian Sep 15, 2025
b6a91fb
set correct style
MarcaDian Sep 15, 2025
e8c0362
apidump
MarcaDian Sep 15, 2025
2aa7527
Merge remote-tracking branch 'upstream/dev' into music-settings
LisoUseInAIKyrios Sep 15, 2025
ee6cae5
Fix Android compilation error
LisoUseInAIKyrios Sep 15, 2025
1ee7d72
Make spoof video streams setting work
LisoUseInAIKyrios Sep 15, 2025
2f1e38b
Remove settings that can be always on
LisoUseInAIKyrios Sep 15, 2025
5a804ff
Fix UI not showing correct settings values
LisoUseInAIKyrios Sep 15, 2025
738933d
hide category bar
LisoUseInAIKyrios Sep 15, 2025
541d87e
Remove setting for patch that could be always on
LisoUseInAIKyrios Sep 15, 2025
6dcd3d8
Add extension stub, turn out UI preference until someone updates this…
LisoUseInAIKyrios Sep 15, 2025
f491e11
Add all other settings
LisoUseInAIKyrios Sep 15, 2025
fd1fcc5
Turn off broken patch until someone who cares enough fixes it
LisoUseInAIKyrios Sep 15, 2025
79a8f03
Fix hide ads patch
LisoUseInAIKyrios Sep 15, 2025
161dc12
Fix patches
LisoUseInAIKyrios Sep 15, 2025
f479650
add permanent repeat
LisoUseInAIKyrios Sep 15, 2025
4e36340
fix item padding
MarcaDian Sep 15, 2025
e812a6c
Add debugging setting
LisoUseInAIKyrios Sep 15, 2025
40a5f84
Add other debug settings
LisoUseInAIKyrios Sep 15, 2025
6888b34
Add YT Music spoof stream client type
LisoUseInAIKyrios Sep 15, 2025
1ce20af
fix shared string
LisoUseInAIKyrios Sep 15, 2025
28d4969
fix default setting values
LisoUseInAIKyrios Sep 15, 2025
1df2209
fix typo
LisoUseInAIKyrios Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;

import app.revanced.extension.music.settings.Settings;

@SuppressWarnings("unused")
public class HideCategoryBarPatch {

/**
* Injection point
*/
public static boolean hideCategoryBar() {
return Settings.HIDE_CATEGORY_BAR.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;

import app.revanced.extension.music.settings.Settings;

@SuppressWarnings("unused")
public class HideGetPremiumPatch {

/**
* Injection point
*/
public static boolean hideGetPremiumLabel() {
return Settings.HIDE_GET_PREMIUM_LABEL.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;

import app.revanced.extension.music.settings.Settings;

@SuppressWarnings("unused")
public class HideUpgradeButtonPatch {

/**
* Injection point
*/
public static boolean hideUpgradeButton() {
return Settings.HIDE_UPGRADE_BUTTON.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app.revanced.extension.music.patches;

import app.revanced.extension.music.settings.Settings;

@SuppressWarnings("unused")
public class HideVideoAdsPatch {

/**
* Injection point
*/
public static boolean showVideoAds(boolean original) {
if (Settings.HIDE_VIDEO_ADS.get()) {
return false;
}
return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;

import app.revanced.extension.music.settings.Settings;

@SuppressWarnings("unused")
public class PermanentRepeatPatch {

/**
* Injection point
*/
public static boolean permanentRepeat() {
return Settings.PERMANENT_REPEAT.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package app.revanced.extension.music.settings;

import android.app.Activity;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceFragment;
import android.view.View;

import app.revanced.extension.music.settings.preference.ReVancedPreferenceFragment;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;

/**
* Hooks GoogleApiActivity to inject a custom ReVancedPreferenceFragment with a toolbar.
*/
public class GoogleApiActivityHook extends BaseActivityHook {
/**
* Injection point
* <p>
* Creates an instance of GoogleApiActivityHook for use in static initialization.
*/
@SuppressWarnings("unused")
public static GoogleApiActivityHook createInstance() {
// Must touch the Music settings to ensure the class is loaded and
// the values can be found when setting the UI preferences.
// Logging anything under non debug ensures this is set.
Logger.printInfo(() -> "Permanent repeat enabled: " + Settings.PERMANENT_REPEAT.get());

return new GoogleApiActivityHook();
}

/**
* Sets the fixed theme for the activity.
*/
@Override
protected void customizeActivityTheme(Activity activity) {
// 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.getResourceIdentifier("Theme.ReVanced.YouTubeMusic.Settings", "style"));
}

/**
* Returns the resource ID for the YouTube Music settings layout.
*/
@Override
protected int getContentViewResourceId() {
return Utils.getResourceIdentifier("revanced_music_settings_with_toolbar", "layout");
}

/**
* Returns the fixed background color for the toolbar.
*/
@Override
protected int getToolbarBackgroundColor() {
return Utils.getResourceColor("ytm_color_black");
}

/**
* Returns the navigation icon with a color filter applied.
*/
@Override
protected Drawable getNavigationIcon() {
Drawable navigationIcon = ReVancedPreferenceFragment.getBackButtonDrawable();
navigationIcon.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
return navigationIcon;
}

/**
* Returns the click listener that finishes the activity when the navigation icon is clicked.
*/
@Override
protected View.OnClickListener getNavigationClickListener(Activity activity) {
return view -> activity.finish();
}

/**
* Creates a new ReVancedPreferenceFragment for the activity.
*/
@Override
protected PreferenceFragment createPreferenceFragment() {
return new ReVancedPreferenceFragment();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package app.revanced.extension.music.settings;

import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;

import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.BooleanSetting;

public class Settings extends BaseSettings {

// Ads
public static final BooleanSetting HIDE_VIDEO_ADS = new BooleanSetting("revanced_music_hide_video_ads", TRUE, true);
public static final BooleanSetting HIDE_GET_PREMIUM_LABEL = new BooleanSetting("revanced_music_hide_get_premium_label", TRUE, true);
public static final BooleanSetting HIDE_UPGRADE_BUTTON = new BooleanSetting("revanced_music_hide_upgrade_button", TRUE, true);

// General
public static final BooleanSetting HIDE_CATEGORY_BAR = new BooleanSetting("revanced_music_hide_category_bar", FALSE, true);

// Player
public static final BooleanSetting PERMANENT_REPEAT = new BooleanSetting("revanced_music_play_permanent_repeat", FALSE, true);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package app.revanced.extension.music.settings.preference;

import android.widget.Toolbar;

import app.revanced.extension.music.settings.GoogleApiActivityHook;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;

/**
* Preference fragment for ReVanced settings.
*/
@SuppressWarnings({"deprecation", "NewApi"})
public class ReVancedPreferenceFragment extends ToolbarPreferenceFragment {

/**
* Initializes the preference fragment.
*/
@Override
protected void initialize() {
super.initialize();

try {
Utils.sortPreferenceGroups(getPreferenceScreen());
setPreferenceScreenToolbar(getPreferenceScreen());
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
}

/**
* Sets toolbar for all nested preference screens.
*/
@Override
protected void customizeToolbar(Toolbar toolbar) {
GoogleApiActivityHook.setToolbarLayoutParams(toolbar);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package app.revanced.extension.shared.settings;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceFragment;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toolbar;

import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;

/**
* Base class for hooking activities to inject a custom PreferenceFragment with a toolbar.
* Provides common logic for initializing the activity and setting up the toolbar.
*/
@SuppressWarnings({"deprecation", "NewApi"})
public abstract class BaseActivityHook extends Activity {

/**
* Layout parameters for the toolbar, extracted from the dummy toolbar.
*/
protected static ViewGroup.LayoutParams toolbarLayoutParams;

/**
* Sets the layout parameters for the toolbar.
*/
public static void setToolbarLayoutParams(Toolbar toolbar) {
if (toolbarLayoutParams != null) {
toolbar.setLayoutParams(toolbarLayoutParams);
}
}

/**
* Initializes the activity by setting the theme, content view and injecting a PreferenceFragment.
*/
public static void initialize(BaseActivityHook hook, Activity activity) {
try {
hook.customizeActivityTheme(activity);
activity.setContentView(hook.getContentViewResourceId());

// Sanity check.
String dataString = activity.getIntent().getDataString();
if (!"revanced_settings_intent".equals(dataString)) {
Logger.printException(() -> "Unknown intent: " + dataString);
return;
}

PreferenceFragment fragment = hook.createPreferenceFragment();
hook.createToolbar(activity, fragment);

activity.getFragmentManager()
.beginTransaction()
.replace(Utils.getResourceIdentifier("revanced_settings_fragments", "id"), fragment)
.commit();
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
}

/**
* Creates and configures a toolbar for the activity, replacing a dummy placeholder.
*/
@SuppressLint("UseCompatLoadingForDrawables")
protected void createToolbar(Activity activity, PreferenceFragment fragment) {
// Replace dummy placeholder toolbar.
// This is required to fix submenu title alignment issue with Android ASOP 15+
ViewGroup toolBarParent = activity.findViewById(
Utils.getResourceIdentifier("revanced_toolbar_parent", "id"));
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent, "revanced_toolbar");
toolbarLayoutParams = dummyToolbar.getLayoutParams();
toolBarParent.removeView(dummyToolbar);

// Sets appropriate system navigation bar color for the activity.
ToolbarPreferenceFragment.setNavigationBarColor(activity.getWindow());

Toolbar toolbar = new Toolbar(toolBarParent.getContext());
toolbar.setBackgroundColor(getToolbarBackgroundColor());
toolbar.setNavigationIcon(getNavigationIcon());
toolbar.setNavigationOnClickListener(getNavigationClickListener(activity));
toolbar.setTitle(Utils.getResourceIdentifier("revanced_settings_title", "string"));

final int margin = Utils.dipToPixels(16);
toolbar.setTitleMarginStart(margin);
toolbar.setTitleMarginEnd(margin);
TextView toolbarTextView = Utils.getChildView(toolbar, false, view -> view instanceof TextView);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
setToolbarLayoutParams(toolbar);

onPostToolbarSetup(activity, toolbar, fragment);

toolBarParent.addView(toolbar, 0);
}

/**
* 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.
*/
protected abstract int getToolbarBackgroundColor();

/**
* Returns the navigation icon drawable for the toolbar.
*/
protected abstract Drawable getNavigationIcon();

/**
* Returns the click listener for the toolbar's navigation icon.
*/
protected abstract View.OnClickListener getNavigationClickListener(Activity activity);

/**
* Creates the PreferenceFragment to be injected into the activity.
*/
protected PreferenceFragment createPreferenceFragment() {
return new ToolbarPreferenceFragment();
}

/**
* Performs additional setup after the toolbar is configured.
*
* @param activity The activity hosting the toolbar.
* @param toolbar The configured toolbar.
* @param fragment The PreferenceFragment associated with the activity.
*/
protected void onPostToolbarSetup(Activity activity, Toolbar toolbar, PreferenceFragment fragment) {}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package app.revanced.extension.youtube.settings.preference;
package app.revanced.extension.shared.settings.preference;

import android.content.Context;
import android.util.AttributeSet;
import android.preference.Preference;
import app.revanced.extension.shared.settings.preference.LogBufferManager;

/**
* A custom preference that clears the ReVanced debug log buffer when clicked.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package app.revanced.extension.youtube.settings.preference;
package app.revanced.extension.shared.settings.preference;

import android.content.Context;
import android.util.AttributeSet;
import android.preference.Preference;
import app.revanced.extension.shared.settings.preference.LogBufferManager;

/**
* A custom preference that triggers exporting ReVanced debug logs to the clipboard when clicked.
Expand Down
Loading
Loading