feat(YouTube - Shorts components): add Custom actions in toolbar setting (YouTube 18.38.44+) (#106)

* feat(YouTube - Shorts Player):  Hook `More` button

* fix(YouTube - Shorts Player): Incorrect videoId when playing a Short

* fix(YouTube - Shorts Player): `Open in normal player` didn't work when `Enable open links directly` was disabled

* fix: Use an existing class

---------

Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com>
This commit is contained in:
Francesco Marastoni
2024-12-15 07:54:33 +00:00
committed by GitHub
parent 7023e5b323
commit 73b95a5143
6 changed files with 191 additions and 16 deletions

View File

@ -4,16 +4,20 @@ import static app.revanced.extension.shared.utils.ResourceUtils.getString;
import static app.revanced.extension.youtube.patches.components.ShortsCustomActionsFilter.isShortsFlyoutMenuVisible;
import static app.revanced.extension.youtube.utils.ExtendedUtils.isSpoofingToLessThan;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import java.lang.ref.WeakReference;
import java.util.LinkedHashMap;
import java.util.Map;
@ -34,12 +38,83 @@ public final class CustomActionsPatch {
isSpoofingToLessThan("19.00.00");
private static final boolean SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU_ENABLED =
!IS_SPOOFING_TO_YOUTUBE_2023 && Settings.ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU.get();
private static final boolean SHORTS_CUSTOM_ACTIONS_TOOLBAR_ENABLED =
Settings.ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR.get();
private static final int arrSize = CustomAction.values().length;
private static final Map<CustomAction, Object> flyoutMenuMap = new LinkedHashMap<>(arrSize);
private static WeakReference<Context> contextRef = new WeakReference<>(null);
private static WeakReference<RecyclerView> recyclerViewRef = new WeakReference<>(null);
/**
* Injection point.
*/
public static void setToolbarMenu(String enumString, View toolbarView) {
if (!SHORTS_CUSTOM_ACTIONS_TOOLBAR_ENABLED) {
return;
}
if (ShortsPlayerState.getCurrent().isClosed()) {
return;
}
if (!isMoreButton(enumString)) {
return;
}
setToolbarMenuOnLongClickListener((ViewGroup) toolbarView);
}
private static void setToolbarMenuOnLongClickListener(ViewGroup parentView) {
ImageView imageView = Utils.getChildView(parentView, v -> v instanceof ImageView);
if (imageView == null) {
return;
}
Context context = imageView.getContext();
contextRef = new WeakReference<>(context);
// Overriding is possible only after OnClickListener is assigned to the more button.
Utils.runOnMainThreadDelayed(() -> imageView.setOnLongClickListener(button -> {
showMoreButtonDialog(context);
return true;
}), 0);
}
private static void showMoreButtonDialog(Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(getString("revanced_shorts_custom_actions_toolbar_dialog_title"));
Map<String, Runnable> toolbarMap = new LinkedHashMap<>(arrSize);
for (CustomAction customAction : CustomAction.values()) {
if (customAction.settings.get()) {
toolbarMap.putIfAbsent(customAction.getLabel(), customAction.getOnClickAction());
}
}
String[] titles = toolbarMap.keySet().toArray(new String[0]);
Runnable[] actions = toolbarMap.values().toArray(new Runnable[0]);
builder.setItems(titles, (dialog, which) -> {
String selectedOption = titles[which];
Runnable action = actions[which];
if (action != null) {
action.run();
} else {
Logger.printDebug(() -> "No action found for " + selectedOption);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private static boolean isMoreButton(String enumString) {
return StringUtils.equalsAny(
enumString,
"MORE_VERT",
"MORE_VERT_BOLD"
);
}
/**
* Injection point.
*/
@ -129,6 +204,24 @@ public final class CustomActionsPatch {
});
}
/**
* Injection point.
*/
public static void onLiveHeaderElementsContainerCreate(final View view) {
if (!SHORTS_CUSTOM_ACTIONS_TOOLBAR_ENABLED) {
return;
}
view.getViewTreeObserver().addOnDrawListener(() -> {
try {
if (view instanceof ViewGroup viewGroup) {
setToolbarMenuOnLongClickListener(viewGroup);
}
} catch (Exception ex) {
Logger.printException(() -> "onFlyoutMenuCreate failure", ex);
}
});
}
private static void hideFlyoutMenu() {
if (!SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU_ENABLED) {
return;

View File

@ -471,16 +471,17 @@ public class Settings extends BaseSettings {
// PreferenceScreen: Shorts - Shorts player components - Custom actions
public static final BooleanSetting ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU = new BooleanSetting("revanced_enable_shorts_custom_actions_flyout_menu", FALSE, true);
public static final BooleanSetting ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR = new BooleanSetting("revanced_enable_shorts_custom_actions_toolbar", FALSE, true);
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL = new BooleanSetting("revanced_shorts_custom_actions_copy_video_url", FALSE, true,
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU));
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU, ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR));
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_shorts_custom_actions_copy_video_url_timestamp", FALSE, true,
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU));
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU, ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR));
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_shorts_custom_actions_external_downloader", FALSE, true,
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU));
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU, ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR));
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO = new BooleanSetting("revanced_shorts_custom_actions_open_video", FALSE, true,
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU));
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU, ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR));
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_REPEAT_STATE = new BooleanSetting("revanced_shorts_custom_actions_repeat_state", FALSE, true,
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU));
parentsAny(ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU, ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR));
// Experimental Flags
public static final BooleanSetting ENABLE_TIME_STAMP = new BooleanSetting("revanced_enable_shorts_time_stamp", FALSE, true);