feat(YouTube Music - Change start page): Add more start pages (#135)

* feat(YouTube Music - Change start page): Add more start pages

* Add more start pages

* feat: Switch to `EnumSetting`, Add `Default`, `Samples` and `Search`, Remove `Home`

---------

Co-authored-by: ILoveOpenSourceApplications <ILoveOpenSourceApplications@users.noreply.github.com>
Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com>
This commit is contained in:
ILoveOpenSourceApplications
2025-01-27 15:23:27 +05:30
committed by GitHub
parent eb24578186
commit f7109f9815
8 changed files with 175 additions and 30 deletions

View File

@ -0,0 +1,115 @@
package app.revanced.extension.music.patches.general;
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.NonNull;
import org.apache.commons.lang3.StringUtils;
import app.revanced.extension.music.settings.Settings;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.ResourceUtils;
@SuppressWarnings("unused")
public final class ChangeStartPagePatch {
public enum StartPage {
/**
* Unmodified type, and same as un-patched.
*/
ORIGINAL(""),
/**
* Browse id.
*/
CHARTS("FEmusic_charts"),
EXPLORE("FEmusic_explore"),
HISTORY("FEmusic_history"),
LIBRARY("FEmusic_library_landing"),
PODCASTS("FEmusic_non_music_audio"),
SAMPLES("FEmusic_immersive"),
SUBSCRIPTIONS("FEmusic_library_corpus_artists"),
/**
* Playlist id, this can be used as a browseId.
*/
EPISODES_FOR_LATER("VLSE"),
LIKED_MUSIC("VLLM"),
/**
* Intent extra.
*/
SEARCH("", 1, "Eh4IBRDTnQEYmgMiEwiZn+H0r5WLAxVV5OcDHcHRBmPqpd25AQA=");
@NonNull
final String browseId;
final int shortcutType;
/**
* Unique identifier for shortcut (Base64).
*/
@NonNull
final String shortcutId;
StartPage(@NonNull String browseId) {
this(browseId, 0, "");
}
StartPage(@NonNull String browseId, int shortcutType, @NonNull String shortcutId) {
this.browseId = browseId;
this.shortcutType = shortcutType;
this.shortcutId = shortcutId;
}
}
/**
* Intent action when YouTube is cold started from the launcher.
*/
private static final String ACTION_MAIN = "android.intent.action.MAIN";
private static final String SHORTCUT_ACTION = "com.google.android.youtube.music.action.shortcut";
private static final String SHORTCUT_CLASS_DESCRIPTOR = "com.google.android.apps.youtube.music.activities.InternalMusicActivity";
private static final String SHORTCUT_TYPE = "com.google.android.youtube.music.action.shortcut_type";
private static final StartPage START_PAGE = Settings.CHANGE_START_PAGE.get();
public static String overrideBrowseId(@NonNull String browseId) {
if (!browseId.equals("FEmusic_home")) {
return browseId;
}
final String overrideBrowseId = START_PAGE.browseId;
if (overrideBrowseId.isEmpty()) {
return browseId;
}
Logger.printDebug(() -> "Changing browseId to " + START_PAGE.name());
return overrideBrowseId;
}
public static void overrideIntent(@NonNull Intent intent) {
if (!StringUtils.equals(intent.getAction(), ACTION_MAIN)) {
Logger.printDebug(() -> "Ignore override intent action" +
" as the current activity is not the entry point of the application");
return;
}
final String overrideShortcutId = START_PAGE.shortcutId;
if (overrideShortcutId.isEmpty()) {
return;
}
Activity mActivity = ResourceUtils.getActivity();
if (mActivity == null) {
return;
}
Logger.printDebug(() -> "Changing intent action to " + START_PAGE.name());
intent.setAction(SHORTCUT_ACTION);
intent.setClassName(mActivity, SHORTCUT_CLASS_DESCRIPTOR);
intent.setPackage(mActivity.getPackageName());
intent.putExtra(SHORTCUT_TYPE, START_PAGE.shortcutType);
intent.putExtra(SHORTCUT_ACTION, overrideShortcutId);
}
}

View File

@ -32,17 +32,6 @@ public class GeneralPatch {
// endregion // endregion
// region [Change start page] patch
public static String changeStartPage(final String browseId) {
if (!browseId.equals("FEmusic_home"))
return browseId;
return Settings.CHANGE_START_PAGE.get();
}
// endregion
// region [Disable dislike redirection] patch // region [Disable dislike redirection] patch
public static boolean disableDislikeRedirection() { public static boolean disableDislikeRedirection() {

View File

@ -6,6 +6,7 @@ import static app.revanced.extension.music.sponsorblock.objects.CategoryBehaviou
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import app.revanced.extension.music.patches.general.ChangeStartPagePatch.StartPage;
import app.revanced.extension.music.patches.misc.AlbumMusicVideoPatch.RedirectType; import app.revanced.extension.music.patches.misc.AlbumMusicVideoPatch.RedirectType;
import app.revanced.extension.music.patches.misc.client.AppClient.ClientType; import app.revanced.extension.music.patches.misc.client.AppClient.ClientType;
import app.revanced.extension.music.patches.utils.PatchStatus; import app.revanced.extension.music.patches.utils.PatchStatus;
@ -91,7 +92,7 @@ public class Settings extends BaseSettings {
// PreferenceScreen: General // PreferenceScreen: General
public static final StringSetting CHANGE_START_PAGE = new StringSetting("revanced_change_start_page", "FEmusic_home", true); public static final EnumSetting<StartPage> CHANGE_START_PAGE = new EnumSetting<>("revanced_change_start_page", StartPage.ORIGINAL, true);
public static final BooleanSetting DISABLE_DISLIKE_REDIRECTION = new BooleanSetting("revanced_disable_dislike_redirection", FALSE); public static final BooleanSetting DISABLE_DISLIKE_REDIRECTION = new BooleanSetting("revanced_disable_dislike_redirection", FALSE);
public static final BooleanSetting ENABLE_LANDSCAPE_MODE = new BooleanSetting("revanced_enable_landscape_mode", FALSE, true); public static final BooleanSetting ENABLE_LANDSCAPE_MODE = new BooleanSetting("revanced_enable_landscape_mode", FALSE, true);
public static final BooleanSetting CUSTOM_FILTER = new BooleanSetting("revanced_custom_filter", FALSE); public static final BooleanSetting CUSTOM_FILTER = new BooleanSetting("revanced_custom_filter", FALSE);

View File

@ -136,9 +136,7 @@ public class ReVancedPreferenceFragment extends PreferenceFragment {
final Setting<?> settings = getSettingFromPath(dataString); final Setting<?> settings = getSettingFromPath(dataString);
if (settings instanceof StringSetting stringSetting) { if (settings instanceof StringSetting stringSetting) {
if (settings.equals(CHANGE_START_PAGE)) { if (settings.equals(BYPASS_IMAGE_REGION_RESTRICTIONS_DOMAIN)
ResettableListPreference.showDialog(mActivity, stringSetting, 2);
} else if (settings.equals(BYPASS_IMAGE_REGION_RESTRICTIONS_DOMAIN)
|| settings.equals(CUSTOM_FILTER_STRINGS) || settings.equals(CUSTOM_FILTER_STRINGS)
|| settings.equals(CUSTOM_PLAYBACK_SPEEDS) || settings.equals(CUSTOM_PLAYBACK_SPEEDS)
|| settings.equals(ENABLE_CUSTOM_NAVIGATION_BAR_COLOR_VALUE) || settings.equals(ENABLE_CUSTOM_NAVIGATION_BAR_COLOR_VALUE)
@ -163,7 +161,8 @@ public class ReVancedPreferenceFragment extends PreferenceFragment {
Logger.printDebug(() -> "Failed to find the right value: " + dataString); Logger.printDebug(() -> "Failed to find the right value: " + dataString);
} }
} else if (settings instanceof EnumSetting<?> enumSetting) { } else if (settings instanceof EnumSetting<?> enumSetting) {
if (settings.equals(DISABLE_MUSIC_VIDEO_IN_ALBUM_REDIRECT_TYPE) if (settings.equals(CHANGE_START_PAGE)
|| settings.equals(DISABLE_MUSIC_VIDEO_IN_ALBUM_REDIRECT_TYPE)
|| settings.equals(RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT) || settings.equals(RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT)
|| settings.equals(SPOOF_CLIENT_TYPE) || settings.equals(SPOOF_CLIENT_TYPE)
|| settings.equals(SPOOF_STREAMING_DATA_TYPE) || settings.equals(SPOOF_STREAMING_DATA_TYPE)

View File

@ -1,10 +1,11 @@
package app.revanced.patches.music.general.startpage package app.revanced.patches.music.general.startpage
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.extension.Constants.GENERAL_PATH
import app.revanced.patches.music.utils.patch.PatchList.CHANGE_START_PAGE import app.revanced.patches.music.utils.patch.PatchList.CHANGE_START_PAGE
import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
@ -18,6 +19,9 @@ import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"$GENERAL_PATH/ChangeStartPagePatch;"
@Suppress("unused") @Suppress("unused")
val changeStartPagePatch = bytecodePatch( val changeStartPagePatch = bytecodePatch(
CHANGE_START_PAGE.title, CHANGE_START_PAGE.title,
@ -29,6 +33,11 @@ val changeStartPagePatch = bytecodePatch(
execute { execute {
coldStartIntentFingerprint.methodOrThrow().addInstruction(
0,
"invoke-static {p1}, $EXTENSION_CLASS_DESCRIPTOR->overrideIntent(Landroid/content/Intent;)V"
)
coldStartUpFingerprint.methodOrThrow().apply { coldStartUpFingerprint.methodOrThrow().apply {
val defaultBrowseIdIndex = indexOfFirstStringInstructionOrThrow(DEFAULT_BROWSE_ID) val defaultBrowseIdIndex = indexOfFirstStringInstructionOrThrow(DEFAULT_BROWSE_ID)
val browseIdIndex = indexOfFirstInstructionReversedOrThrow(defaultBrowseIdIndex) { val browseIdIndex = indexOfFirstInstructionReversedOrThrow(defaultBrowseIdIndex) {
@ -39,7 +48,7 @@ val changeStartPagePatch = bytecodePatch(
addInstructions( addInstructions(
browseIdIndex + 1, """ browseIdIndex + 1, """
invoke-static {v$browseIdRegister}, $GENERAL_CLASS_DESCRIPTOR->changeStartPage(Ljava/lang/String;)Ljava/lang/String; invoke-static {v$browseIdRegister}, $EXTENSION_CLASS_DESCRIPTOR->overrideBrowseId(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$browseIdRegister move-result-object v$browseIdRegister
""" """
) )

View File

@ -7,6 +7,17 @@ import com.android.tools.smali.dexlib2.Opcode
const val DEFAULT_BROWSE_ID = "FEmusic_home" const val DEFAULT_BROWSE_ID = "FEmusic_home"
internal val coldStartIntentFingerprint = legacyFingerprint(
name = "coldStartIntentFingerprint",
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/content/Intent;"),
strings = listOf(
"android.intent.action.SEARCH",
"com.google.android.youtube.music.action.shortcut_type",
)
)
internal val coldStartUpFingerprint = legacyFingerprint( internal val coldStartUpFingerprint = legacyFingerprint(
name = "coldStartUpFingerprint", name = "coldStartUpFingerprint",
returnType = "Ljava/lang/String;", returnType = "Ljava/lang/String;",
@ -16,6 +27,9 @@ internal val coldStartUpFingerprint = legacyFingerprint(
Opcode.CONST_STRING, Opcode.CONST_STRING,
Opcode.RETURN_OBJECT Opcode.RETURN_OBJECT
), ),
strings = listOf("FEmusic_library_sideloaded_tracks", DEFAULT_BROWSE_ID) strings = listOf(
"FEmusic_library_sideloaded_tracks",
DEFAULT_BROWSE_ID
)
) )

View File

@ -1,18 +1,30 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string-array name="revanced_change_start_page_entries"> <string-array name="revanced_change_start_page_entries">
<item>@string/revanced_change_start_page_entry_chart</item> <item>@string/revanced_change_start_page_entry_default</item>
<item>@string/revanced_change_start_page_entry_charts</item>
<item>@string/revanced_change_start_page_entry_episodes_for_later</item>
<item>@string/revanced_change_start_page_entry_explore</item> <item>@string/revanced_change_start_page_entry_explore</item>
<item>@string/revanced_change_start_page_entry_home</item> <item>@string/revanced_change_start_page_entry_history</item>
<item>@string/revanced_change_start_page_entry_library</item> <item>@string/revanced_change_start_page_entry_library</item>
<item>@string/revanced_change_start_page_entry_subscription</item> <item>@string/revanced_change_start_page_entry_liked_music</item>
<item>@string/revanced_change_start_page_entry_podcasts</item>
<item>@string/revanced_change_start_page_entry_samples</item>
<item>@string/revanced_change_start_page_entry_search</item>
<item>@string/revanced_change_start_page_entry_subscriptions</item>
</string-array> </string-array>
<string-array name="revanced_change_start_page_entry_values"> <string-array name="revanced_change_start_page_entry_values">
<item>FEmusic_charts</item> <item>ORIGINAL</item>
<item>FEmusic_explore</item> <item>CHARTS</item>
<item>FEmusic_home</item> <item>EPISODES_FOR_LATER</item>
<item>FEmusic_library_landing</item> <item>EXPLORE</item>
<item>FEmusic_library_corpus_artists</item> <item>HISTORY</item>
<item>LIBRARY</item>
<item>LIKED_MUSIC</item>
<item>PODCASTS</item>
<item>SAMPLES</item>
<item>SEARCH</item>
<item>SUBSCRIPTIONS</item>
</string-array> </string-array>
<string-array name="revanced_disable_music_video_in_album_redirect_type_entries"> <string-array name="revanced_disable_music_video_in_album_redirect_type_entries">
<item>@string/revanced_disable_music_video_in_album_redirect_type_entry_redirect</item> <item>@string/revanced_disable_music_video_in_album_redirect_type_entry_redirect</item>

View File

@ -138,11 +138,17 @@ Limitations:
<string name="revanced_change_start_page_title">Change start page</string> <string name="revanced_change_start_page_title">Change start page</string>
<string name="revanced_change_start_page_summary">Select which page the app opens in.</string> <string name="revanced_change_start_page_summary">Select which page the app opens in.</string>
<string name="revanced_change_start_page_entry_chart">Charts</string> <string name="revanced_change_start_page_entry_default">Default</string>
<string name="revanced_change_start_page_entry_charts">Charts</string>
<string name="revanced_change_start_page_entry_episodes_for_later">Episodes for Later</string>
<string name="revanced_change_start_page_entry_explore">Explore</string> <string name="revanced_change_start_page_entry_explore">Explore</string>
<string name="revanced_change_start_page_entry_home">Home</string> <string name="revanced_change_start_page_entry_history">History</string>
<string name="revanced_change_start_page_entry_library">Library</string> <string name="revanced_change_start_page_entry_library">Library</string>
<string name="revanced_change_start_page_entry_subscription">Subscriptions</string> <string name="revanced_change_start_page_entry_liked_music">Liked Music</string>
<string name="revanced_change_start_page_entry_podcasts">Podcasts</string>
<string name="revanced_change_start_page_entry_samples">Samples</string>
<string name="revanced_change_start_page_entry_search">Search</string>
<string name="revanced_change_start_page_entry_subscriptions">Subscriptions</string>
<string name="revanced_disable_dislike_redirection_title">Disable dislike redirection</string> <string name="revanced_disable_dislike_redirection_title">Disable dislike redirection</string>
<string name="revanced_disable_dislike_redirection_summary">Disables redirection to the next track when clicking the Dislike button.</string> <string name="revanced_disable_dislike_redirection_summary">Disables redirection to the next track when clicking the Dislike button.</string>
<string name="revanced_disable_auto_captions_title">Disable forced auto captions</string> <string name="revanced_disable_auto_captions_title">Disable forced auto captions</string>