Skip to content
This repository has been archived by the owner on Oct 26, 2024. It is now read-only.

Commit

Permalink
feat(YouTube): Support versions 19.25 and 19.34 (#689)
Browse files Browse the repository at this point in the history
Co-authored-by: LisoUseInAIKyrios <[email protected]>
Co-authored-by: kitadai31 <[email protected]>
  • Loading branch information
3 people authored Oct 19, 2024
1 parent 99d17bf commit 61569ba
Show file tree
Hide file tree
Showing 27 changed files with 989 additions and 521 deletions.
36 changes: 32 additions & 4 deletions app/src/main/java/app/revanced/integrations/shared/Utils.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package app.revanced.integrations.shared;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.*;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
Expand Down Expand Up @@ -268,6 +265,20 @@ public interface MatchFilter<T> {
boolean matches(T object);
}

/**
* Includes sub children.
*
* @noinspection unchecked
*/
public static <R extends View> R getChildViewByResourceName(@NonNull View view, @NonNull String str) {
var child = view.findViewById(Utils.getResourceIdentifier(str, "id"));
if (child != null) {
return (R) child;
}

throw new IllegalArgumentException("View with resource name '" + str + "' not found");
}

/**
* @param searchRecursively If children ViewGroups should also be
* recursively searched using depth first search.
Expand Down Expand Up @@ -710,4 +721,21 @@ public static void sortPreferenceGroups(@NonNull PreferenceGroup group) {
pref.setOrder(order);
}
}

/**
* If {@link Fragment} uses [Android library] rather than [AndroidX library],
* the Dialog theme corresponding to [Android library] should be used.
* <p>
* If not, the following issues will occur:
* <a href="https://github.com/ReVanced/revanced-patches/issues/3061">ReVanced/revanced-patches#3061</a>
* <p>
* To prevent these issues, apply the Dialog theme corresponding to [Android library].
*/
public static void setEditTextDialogTheme(AlertDialog.Builder builder) {
final int editTextDialogStyle = getResourceIdentifier(
"revanced_edit_text_dialog_style", "style");
if (editTextDialogStyle != 0) {
builder.getContext().setTheme(editTextDialogStyle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.Utils;
import app.revanced.integrations.shared.settings.BaseSettings;
import app.revanced.integrations.shared.settings.BooleanSetting;
import app.revanced.integrations.shared.settings.Setting;

Expand Down Expand Up @@ -141,8 +142,13 @@ private void updatePreferenceScreen(@NonNull PreferenceScreen screen,
} else if (pref.hasKey()) {
String key = pref.getKey();
Setting<?> setting = Setting.getSettingFromPath(key);

if (setting != null) {
updatePreference(pref, setting, syncSettingValue, applySettingToPreference);
} else if (BaseSettings.DEBUG.get() && (pref instanceof SwitchPreference
|| pref instanceof EditTextPreference || pref instanceof ListPreference)) {
// Probably a typo in the patches preference declaration.
Logger.printException(() -> "Preference key has no setting: " + key);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public boolean onPreferenceClick(Preference preference) {
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
try {
Utils.setEditTextDialogTheme(builder);

// Show the user the settings in JSON format.
builder.setNeutralButton(str("revanced_settings_import_copy"), (dialog, which) -> {
Utils.setClipboard(getEditText().getText().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.EditText;

import app.revanced.integrations.shared.Utils;
import app.revanced.integrations.shared.settings.Setting;
import app.revanced.integrations.shared.Logger;

Expand All @@ -33,6 +35,8 @@ public ResettableEditTextPreference(Context context) {
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
Utils.setEditTextDialogTheme(builder);

Setting<?> setting = Setting.getSettingFromPath(getKey());
if (setting != null) {
builder.setNeutralButton(str("revanced_settings_reset"), null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ public class BackgroundPlaybackPatch {
/**
* Injection point.
*/
public static boolean playbackIsNotShort() {
public static boolean allowBackgroundPlayback(boolean original) {
if (original) return true;

// Steps to verify most edge cases:
// 1. Open a regular video
// 2. Minimize app (PIP should appear)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,129 @@
package app.revanced.integrations.youtube.patches;

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

import android.content.Intent;
import android.net.Uri;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.settings.Settings;

@SuppressWarnings("unused")
public final class ChangeStartPagePatch {
public static void changeIntent(final Intent intent) {
final var startPage = Settings.START_PAGE.get();
if (startPage.isEmpty()) return;

Logger.printDebug(() -> "Changing start page to " + startPage);
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),
SUBSCRIPTIONS("FEsubscriptions", TRUE),
TRENDING("FEtrending", TRUE),

/**
* Channel id, this can be used as a browseId.
*/
GAMING("UCOpNcN46UbXVtpKMrmU4Abg", TRUE),
LIVE("UC4R8DWoMoI7CAwX8_LjQHig", TRUE),
MUSIC("UC-9-kyTW8ZkZNDHQJ6FgpwQ", 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 TRUE.equals(isBrowseId);
}

@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isIntentAction() {
return FALSE.equals(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();

/**
* 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 (appLaunched) {
Logger.printDebug(() -> "Ignore override browseId as the app already launched");
return original;
}
appLaunched = true;

Logger.printDebug(() -> "Changing browseId to " + START_PAGE.id);
return START_PAGE.id;
}

public static void overrideIntentAction(@NonNull Intent intent) {
if (!START_PAGE.isIntentAction()) {
return;
}

if (!ACTION_MAIN.equals(intent.getAction())) {
Logger.printDebug(() -> "Ignore override intent action" +
" as the current activity is not the entry point of the application");
return;
}

if (appLaunched) {
Logger.printDebug(() -> "Ignore override intent action as the app already launched");
return;
}
appLaunched = true;

if (startPage.startsWith("www"))
intent.setData(Uri.parse(startPage));
else
intent.setAction("com.google.android.youtube.action." + startPage);
final String intentAction = START_PAGE.id;
Logger.printDebug(() -> "Changing intent action to " + intentAction);
intent.setAction(intentAction);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
package app.revanced.integrations.youtube.patches;

import android.view.View;

import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.Utils;
import app.revanced.integrations.youtube.settings.Settings;

@SuppressWarnings("unused")
public final class HidePlayerButtonsPatch {

private static final boolean HIDE_PLAYER_BUTTONS_ENABLED = Settings.HIDE_PLAYER_BUTTONS.get();

private static final int PLAYER_CONTROL_PREVIOUS_BUTTON_TOUCH_AREA_ID =
Utils.getResourceIdentifier("player_control_previous_button_touch_area", "id");

private static final int PLAYER_CONTROL_NEXT_BUTTON_TOUCH_AREA_ID =
Utils.getResourceIdentifier("player_control_next_button_touch_area", "id");

/**
* Injection point.
*/
public static boolean previousOrNextButtonIsVisible(boolean previousOrNextButtonVisible) {
if (Settings.HIDE_PLAYER_BUTTONS.get()) {
return false;
public static void hidePreviousNextButtons(View parentView) {
if (!HIDE_PLAYER_BUTTONS_ENABLED) {
return;
}

// Must use a deferred call to main thread to hide the button.
// Otherwise the layout crashes if set to hidden now.
Utils.runOnMainThread(() -> {
hideView(parentView, PLAYER_CONTROL_PREVIOUS_BUTTON_TOUCH_AREA_ID);
hideView(parentView, PLAYER_CONTROL_NEXT_BUTTON_TOUCH_AREA_ID);
});
}

private static void hideView(View parentView, int resourceId) {
View nextPreviousButton = parentView.findViewById(resourceId);

if (nextPreviousButton == null) {
Logger.printException(() -> "Could not find player previous/next button");
return;
}
return previousOrNextButtonVisible;

Logger.printDebug(() -> "Hiding previous/next button");
Utils.hideViewByRemovingFromParentUnderCondition(true, nextPreviousButton);
}
}
Loading

0 comments on commit 61569ba

Please sign in to comment.