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

* Revert "fix(YouTube - Change start page): Use correct browseId for `Podcasts`…"

This reverts commit 66b7761e7760ac9444dbba431cdba3bd8186a0c6.

* feat(YouTube - Change start page): Update start pages

* Update strings.xml

* Fix

* feat: Fix typo, Switch to Kotlin, Add `Podcasts` and `Virtual Reality`

---------

Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com>
This commit is contained in:
Hoàng Gia Bảo 2025-01-27 17:02:38 +07:00 committed by GitHub
parent f7109f9815
commit 5255c7eca8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 163 additions and 145 deletions

View File

@ -1,141 +0,0 @@
package app.revanced.extension.youtube.patches.general;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
public final class ChangeStartPagePatch {
public enum StartPage {
/**
* Unmodified type, and same as un-patched.
*/
ORIGINAL("", null),
/**
* Browse id.
*/
BROWSE("FEguide_builder", TRUE),
EXPLORE("FEexplore", TRUE),
HISTORY("FEhistory", TRUE),
LIBRARY("FElibrary", TRUE),
MOVIE("FEstorefront", TRUE),
NOTIFICATIONS("FEactivity", TRUE),
SUBSCRIPTIONS("FEsubscriptions", TRUE),
TRENDING("FEtrending", TRUE),
YOUR_CLIPS("FEclips", TRUE),
/**
* Channel id, this can be used as a browseId.
*/
COURSES("UCtFRv9O2AHqOZjjynzrv-xg", TRUE),
FASHION("UCrpQ4p1Ql_hG8rKXIKM1MOQ", TRUE),
GAMING("UCOpNcN46UbXVtpKMrmU4Abg", TRUE),
LIVE("UC4R8DWoMoI7CAwX8_LjQHig", TRUE),
MUSIC("UC-9-kyTW8ZkZNDHQJ6FgpwQ", TRUE),
NEWS("UCYfdidRxbB8Qhf0Nx7ioOYw", TRUE),
PODCASTS("UCNVkxRPqsBNejO6B9thG9Xw", TRUE),
SHOPPING("UCkYQyvc_i9hXEo4xic9Hh2g", TRUE),
SPORTS("UCEgdi0XIXXZ-qJOFPf4JSKw", TRUE),
/**
* Playlist id, this can be used as a browseId.
*/
LIKED_VIDEO("VLLL", TRUE),
WATCH_LATER("VLWL", TRUE),
/**
* Intent action.
*/
SEARCH("com.google.android.youtube.action.open.search", FALSE),
SHORTS("com.google.android.youtube.action.open.shorts", FALSE);
@Nullable
final Boolean isBrowseId;
@NonNull
final String id;
StartPage(@NonNull String id, @Nullable Boolean isBrowseId) {
this.id = id;
this.isBrowseId = isBrowseId;
}
private boolean isBrowseId() {
return BooleanUtils.isTrue(isBrowseId);
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isIntentAction() {
return BooleanUtils.isFalse(isBrowseId);
}
}
/**
* Intent action when YouTube is cold started from the launcher.
* <p>
* If you don't check this, the hooking will also apply in the following cases:
* Case 1. The user clicked Shorts button on the YouTube shortcut.
* Case 2. The user clicked Shorts button on the YouTube widget.
* In this case, instead of opening Shorts, the start page specified by the user is opened.
*/
private static final String ACTION_MAIN = "android.intent.action.MAIN";
private static final StartPage START_PAGE = Settings.CHANGE_START_PAGE.get();
private static final boolean ALWAYS_CHANGE_START_PAGE = Settings.CHANGE_START_PAGE_TYPE.get();
/**
* There is an issue where the back button on the toolbar doesn't work properly.
* As a workaround for this issue, instead of overriding the browserId multiple times, just override it once.
*/
private static boolean appLaunched = false;
public static String overrideBrowseId(@NonNull String original) {
if (!START_PAGE.isBrowseId()) {
return original;
}
if (!ALWAYS_CHANGE_START_PAGE && appLaunched) {
Logger.printDebug(() -> "Ignore override browseId as the app already launched");
return original;
}
appLaunched = true;
final String browseId = START_PAGE.id;
Logger.printDebug(() -> "Changing browseId to " + browseId);
return browseId;
}
public static void overrideIntentAction(@NonNull Intent intent) {
if (!START_PAGE.isIntentAction()) {
return;
}
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 intentAction = START_PAGE.id;
Logger.printDebug(() -> "Changing intent action to " + intentAction);
intent.setAction(intentAction);
}
public static final class ChangeStartPageTypeAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return Settings.CHANGE_START_PAGE.get() != StartPage.ORIGINAL;
}
}
}

View File

@ -0,0 +1,150 @@
package app.revanced.extension.youtube.patches.general
import android.content.Intent
import android.net.Uri
import app.revanced.extension.shared.settings.Setting.Availability
import app.revanced.extension.shared.utils.Logger
import app.revanced.extension.youtube.settings.Settings
import org.apache.commons.lang3.StringUtils
import kotlin.Boolean
@Suppress("unused")
object ChangeStartPagePatch {
/**
* Intent action when YouTube is cold started from the launcher.
*
* If you don't check this, the hooking will also apply in the following cases:
* Case 1. The user clicked Shorts button on the YouTube shortcut.
* Case 2. The user clicked Shorts button on the YouTube widget.
* In this case, instead of opening Shorts, the start page specified by the user is opened.
*/
private const val ACTION_MAIN = "android.intent.action.MAIN"
private const val URL_ACTIVITY_CLASS_DESCRIPTOR =
"com.google.android.apps.youtube.app.application.Shell_UrlActivity"
private var START_PAGE = Settings.CHANGE_START_PAGE.get()
private val ALWAYS_CHANGE_START_PAGE = Settings.CHANGE_START_PAGE_TYPE.get()
/**
* There is an issue where the back button on the toolbar doesn't work properly.
* As a workaround for this issue, instead of overriding the browserId multiple times, just override it once.
*/
private var appLaunched = false
@JvmStatic
fun overrideBrowseId(original: String): String {
val browseId = START_PAGE.browseId
if (browseId == null) {
return original
}
if (!ALWAYS_CHANGE_START_PAGE && appLaunched) {
Logger.printDebug { "Ignore override browseId as the app already launched" }
return original
}
appLaunched = true
Logger.printDebug{ "Changing browseId to $browseId" }
return browseId
}
@JvmStatic
fun overrideIntent(intent: Intent) {
val action = START_PAGE.action
val url = START_PAGE.url
if (action == null && url == null) {
return
}
if (!StringUtils.equals(intent.action, ACTION_MAIN)) {
Logger.printDebug {
"Ignore override intent action" +
" as the current activity is not the entry point of the application"
}
return
}
if (!ALWAYS_CHANGE_START_PAGE && appLaunched) {
Logger.printDebug { "Ignore override intent as the app already launched" }
return
}
appLaunched = true
if (action != null) {
Logger.printDebug { "Changing intent action to $action" }
intent.setAction(action)
} else if (url != null) {
Logger.printDebug { "Changing url to $url" }
intent.setAction("android.intent.action.VIEW")
intent.setData(Uri.parse(url))
intent.putExtra("alias", URL_ACTIVITY_CLASS_DESCRIPTOR)
} else {
START_PAGE = Settings.CHANGE_START_PAGE.defaultValue
Settings.CHANGE_START_PAGE.resetToDefault()
Logger.printException { "Unknown start page: $START_PAGE" } // Should never happen
}
}
enum class StartPage(
val action: String? = null,
val browseId: String? = null,
val url: String? = null,
) {
/**
* Unmodified type, and same as un-patched.
*/
ORIGINAL,
/**
* Browse id.
*/
ALL_SUBSCRIPTIONS(browseId = "FEchannels"),
BROWSE(browseId = "FEguide_builder"),
EXPLORE(browseId = "FEexplore"),
HISTORY(browseId = "FEhistory"),
LIBRARY(browseId = "FElibrary"),
MOVIE(browseId = "FEstorefront"),
NOTIFICATIONS(browseId = "FEactivity"),
PLAYLISTS(browseId = "FEplaylist_aggregation"),
SUBSCRIPTIONS(browseId = "FEsubscriptions"),
TRENDING(browseId = "FEtrending"),
YOUR_CLIPS(browseId = "FEclips"),
/**
* Channel id, this can be used as a browseId.
*/
COURSES(browseId = "UCtFRv9O2AHqOZjjynzrv-xg"),
FASHION(browseId = "UCrpQ4p1Ql_hG8rKXIKM1MOQ"),
GAMING(browseId = "UCOpNcN46UbXVtpKMrmU4Abg"),
LIVE(browseId = "UC4R8DWoMoI7CAwX8_LjQHig"),
MUSIC(browseId = "UC-9-kyTW8ZkZNDHQJ6FgpwQ"),
NEWS(browseId = "UCYfdidRxbB8Qhf0Nx7ioOYw"),
SHOPPING(browseId = "UCkYQyvc_i9hXEo4xic9Hh2g"),
SPORTS(browseId = "UCEgdi0XIXXZ-qJOFPf4JSKw"),
VIRTUAL_REALITY(browseId = "UCzuqhhs6NWbgTzMuM09WKDQ"),
/**
* Playlist id, this can be used as a browseId.
*/
LIKED_VIDEO(browseId = "VLLL"),
WATCH_LATER(browseId = "VLWL"),
/**
* Intent action.
*/
SEARCH(action = "com.google.android.youtube.action.open.search"),
SHORTS(action = "com.google.android.youtube.action.open.shorts"),
/**
* URL.
*
* URL opens after the home feed is opened.
* Use this only if browseId cannot be used.
*/
PODCASTS(url = "www.youtube.com/podcasts");
}
class ChangeStartPageTypeAvailability : Availability {
override fun isAvailable(): Boolean {
return Settings.CHANGE_START_PAGE.get() != StartPage.ORIGINAL
}
}
}

View File

@ -48,9 +48,9 @@ val changeStartPagePatch = bytecodePatch(
// There is no browseId assigned to Shorts and Search.
// Just hook the Intent action.
intentActionFingerprint.methodOrThrow().addInstruction(
intentFingerprint.methodOrThrow().addInstruction(
0,
"invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->overrideIntentAction(Landroid/content/Intent;)V"
"invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->overrideIntent(Landroid/content/Intent;)V"
)
// region add settings

View File

@ -15,8 +15,8 @@ internal val browseIdFingerprint = legacyFingerprint(
strings = listOf("FEwhat_to_watch"),
)
internal val intentActionFingerprint = legacyFingerprint(
name = "intentActionFingerprint",
internal val intentFingerprint = legacyFingerprint(
name = "intentFingerprint",
parameters = listOf("Landroid/content/Intent;"),
strings = listOf("has_handled_intent"),
)

View File

@ -38,6 +38,7 @@
</string-array>
<string-array name="revanced_change_start_page_entries">
<item>@string/revanced_change_start_page_entry_default</item>
<item>@string/revanced_change_start_page_entry_all_subscriptions</item>
<item>@string/revanced_change_start_page_entry_browse</item>
<item>@string/revanced_change_start_page_entry_courses</item>
<item>@string/revanced_change_start_page_entry_explore</item>
@ -51,6 +52,7 @@
<item>@string/revanced_change_start_page_entry_music</item>
<item>@string/revanced_change_start_page_entry_news</item>
<item>@string/revanced_change_start_page_entry_notifications</item>
<item>@string/revanced_change_start_page_entry_playlists</item>
<item>@string/revanced_change_start_page_entry_podcasts</item>
<item>@string/revanced_change_start_page_entry_search</item>
<item>@string/revanced_change_start_page_entry_shopping</item>
@ -58,11 +60,13 @@
<item>@string/revanced_change_start_page_entry_sports</item>
<item>@string/revanced_change_start_page_entry_subscriptions</item>
<item>@string/revanced_change_start_page_entry_trending</item>
<item>@string/revanced_change_start_page_entry_virtual_reality</item>
<item>@string/revanced_change_start_page_entry_watch_later</item>
<item>@string/revanced_change_start_page_entry_your_clips</item>
</string-array>
<string-array name="revanced_change_start_page_entry_values">
<item>ORIGINAL</item>
<item>ALL_SUBSCRIPTIONS</item>
<item>BROWSE</item>
<item>COURSES</item>
<item>EXPLORE</item>
@ -76,6 +80,7 @@
<item>MUSIC</item>
<item>NEWS</item>
<item>NOTIFICATIONS</item>
<item>PLAYLISTS</item>
<item>PODCASTS</item>
<item>SEARCH</item>
<item>SHOPPING</item>
@ -83,6 +88,7 @@
<item>SPORTS</item>
<item>SUBSCRIPTIONS</item>
<item>TRENDING</item>
<item>VIRTUAL_REALITY</item>
<item>WATCH_LATER</item>
<item>YOUR_CLIPS</item>
</string-array>

View File

@ -376,6 +376,7 @@ If the layout of the player screen changes due to server-side changes, unintende
<string name="revanced_change_start_page_title">Change start page</string>
<string name="revanced_change_start_page_entry_default">Default</string>
<string name="revanced_change_start_page_entry_all_subscriptions">All subscriptions</string>
<string name="revanced_change_start_page_entry_browse">Browse channels</string>
<string name="revanced_change_start_page_entry_courses">Courses / Learning</string>
<string name="revanced_change_start_page_entry_explore">Explore</string>
@ -389,6 +390,7 @@ If the layout of the player screen changes due to server-side changes, unintende
<string name="revanced_change_start_page_entry_music">Music</string>
<string name="revanced_change_start_page_entry_news">News</string>
<string name="revanced_change_start_page_entry_notifications">Notifications</string>
<string name="revanced_change_start_page_entry_playlists">Playlists</string>
<string name="revanced_change_start_page_entry_podcasts">Podcasts</string>
<string name="revanced_change_start_page_entry_search">Search</string>
<string name="revanced_change_start_page_entry_shopping">Shopping</string>
@ -396,6 +398,7 @@ If the layout of the player screen changes due to server-side changes, unintende
<string name="revanced_change_start_page_entry_sports">Sports</string>
<string name="revanced_change_start_page_entry_subscriptions">Subscriptions</string>
<string name="revanced_change_start_page_entry_trending">Trending</string>
<string name="revanced_change_start_page_entry_virtual_reality">Virtual Reality</string>
<string name="revanced_change_start_page_entry_watch_later">Watch later</string>
<string name="revanced_change_start_page_entry_your_clips">Your clips</string>
<string name="revanced_change_start_page_type_title">Change start page type</string>