From 0586fb70e347c25742e03102441cfb37315b5937 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 14 Apr 2024 18:53:48 +0400 Subject: [PATCH] feat(YouTube - Hide Shorts components): Hide tagged products, hide search suggestions (#615) --- .../shared/settings/EnumSetting.java | 4 +- .../preference/SharedPrefCategory.java | 4 +- .../patches/components/ShortsFilter.java | 219 ++++++++---------- .../youtube/settings/Settings.java | 7 +- 4 files changed, 110 insertions(+), 124 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/EnumSetting.java b/app/src/main/java/app/revanced/integrations/shared/settings/EnumSetting.java index 20ef4821..a6301def 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/EnumSetting.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/EnumSetting.java @@ -17,7 +17,7 @@ import java.util.Objects; * All saved JSON text is converted to lowercase to keep the output less obnoxious. */ @SuppressWarnings("unused") -public class EnumSetting extends Setting { +public class EnumSetting> extends Setting { public EnumSetting(String key, T defaultValue) { super(key, defaultValue); } @@ -72,7 +72,7 @@ public class EnumSetting extends Setting { @NonNull private T getEnumFromString(String enumName) { //noinspection ConstantConditions - for (Enum value : defaultValue.getClass().getEnumConstants()) { + for (Enum value : defaultValue.getClass().getEnumConstants()) { if (value.name().equalsIgnoreCase(enumName)) { // noinspection unchecked return (T) value; diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/preference/SharedPrefCategory.java b/app/src/main/java/app/revanced/integrations/shared/settings/preference/SharedPrefCategory.java index 9c7fa45c..ddbc31cb 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/preference/SharedPrefCategory.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/preference/SharedPrefCategory.java @@ -53,7 +53,7 @@ public class SharedPrefCategory { /** * @param value a NULL parameter removes the value from the preferences */ - public void saveEnumAsString(@NonNull String key, @Nullable Enum value) { + public void saveEnumAsString(@NonNull String key, @Nullable Enum value) { saveObjectAsString(key, value); } @@ -98,7 +98,7 @@ public class SharedPrefCategory { } @NonNull - public T getEnum(@NonNull String key, @NonNull T _default) { + public > T getEnum(@NonNull String key, @NonNull T _default) { Objects.requireNonNull(_default); try { String enumName = preferences.getString(key, null); diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java index 05835b50..cbe254aa 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java @@ -22,19 +22,12 @@ public final class ShortsFilter extends Filter { private final StringFilterGroup shortsCompactFeedVideoPath; private final ByteArrayFilterGroup shortsCompactFeedVideoBuffer; - private final StringFilterGroup channelBar; - private final StringFilterGroup fullVideoLinkLabel; - private final StringFilterGroup videoTitle; - private final StringFilterGroup reelSoundMetadata; private final StringFilterGroup subscribeButton; - private final StringFilterGroup subscribeButtonPaused; - private final StringFilterGroup soundButton; - private final StringFilterGroup infoPanel; private final StringFilterGroup joinButton; private final StringFilterGroup shelfHeader; - private final StringFilterGroup suggestedActionPath; - private final ByteArrayFilterGroupList suggestedActions = new ByteArrayFilterGroupList(); + private final StringFilterGroup suggestedAction; + private final ByteArrayFilterGroupList suggestedActionsGroupList = new ByteArrayFilterGroupList(); private final StringFilterGroup actionBar; private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList(); @@ -44,7 +37,7 @@ public final class ShortsFilter extends Filter { // Identifier components. // - var shorts = new StringFilterGroup( + var shortsIdentifiers = new StringFilterGroup( null, // Setting is based on navigation state. "shorts_shelf", "inline_shorts", @@ -52,6 +45,7 @@ public final class ShortsFilter extends Filter { "shorts_video_cell", "shorts_pivot_item" ); + // Feed Shorts shelf header. // Use a different filter group for this pattern, as it requires an additional check after matching. shelfHeader = new StringFilterGroup( @@ -59,14 +53,7 @@ public final class ShortsFilter extends Filter { "shelf_header.eml" ); - // Home / subscription feed components. - - var thanksButton = new StringFilterGroup( // Edit: Does this item show up anymore? - Settings.HIDE_SHORTS_THANKS_BUTTON, - "suggested_action" - ); - - addIdentifierCallbacks(shorts, shelfHeader, thanksButton); + addIdentifierCallbacks(shortsIdentifiers, shelfHeader); // // Path components. @@ -80,6 +67,41 @@ public final class ShortsFilter extends Filter { shortsCompactFeedVideoBuffer = new ByteArrayFilterGroup(null, "/frame0.jpg"); // Shorts player components. + StringFilterGroup pausedOverlayButtons = new StringFilterGroup( + Settings.HIDE_SHORTS_PAUSED_OVERLAY_BUTTONS, + "shorts_paused_state" + ); + + StringFilterGroup channelBar = new StringFilterGroup( + Settings.HIDE_SHORTS_CHANNEL_BAR, + REEL_CHANNEL_BAR_PATH + ); + + StringFilterGroup fullVideoLinkLabel = new StringFilterGroup( + Settings.HIDE_SHORTS_FULL_VIDEO_LINK_LABEL, + "reel_multi_format_link" + ); + + StringFilterGroup videoTitle = new StringFilterGroup( + Settings.HIDE_SHORTS_VIDEO_TITLE, + "shorts_video_title_item" + ); + + StringFilterGroup reelSoundMetadata = new StringFilterGroup( + Settings.HIDE_SHORTS_SOUND_METADATA_LABEL, + "reel_sound_metadata" + ); + + StringFilterGroup soundButton = new StringFilterGroup( + Settings.HIDE_SHORTS_SOUND_BUTTON, + "reel_pivot_button" + ); + + StringFilterGroup infoPanel = new StringFilterGroup( + Settings.HIDE_SHORTS_INFO_PANEL, + "shorts_info_panel_overview" + ); + joinButton = new StringFilterGroup( Settings.HIDE_SHORTS_JOIN_BUTTON, "sponsor_button" @@ -90,109 +112,77 @@ public final class ShortsFilter extends Filter { "subscribe_button" ); - subscribeButtonPaused = new StringFilterGroup( - Settings.HIDE_SHORTS_SUBSCRIBE_BUTTON_PAUSED, - "shorts_paused_state" - ); - - channelBar = new StringFilterGroup( - Settings.HIDE_SHORTS_CHANNEL_BAR, - REEL_CHANNEL_BAR_PATH - ); - - fullVideoLinkLabel = new StringFilterGroup( - Settings.HIDE_SHORTS_FULL_VIDEO_LINK_LABEL, - "reel_multi_format_link" - ); - - videoTitle = new StringFilterGroup( - Settings.HIDE_SHORTS_VIDEO_TITLE, - "shorts_video_title_item" - ); - - reelSoundMetadata = new StringFilterGroup( - Settings.HIDE_SHORTS_SOUND_METADATA_LABEL, - "reel_sound_metadata" - ); - - soundButton = new StringFilterGroup( - Settings.HIDE_SHORTS_SOUND_BUTTON, - "reel_pivot_button" - ); - - infoPanel = new StringFilterGroup( - Settings.HIDE_SHORTS_INFO_PANEL, - "shorts_info_panel_overview" - ); - actionBar = new StringFilterGroup( null, "shorts_action_bar" ); - suggestedActionPath = new StringFilterGroup( + suggestedAction = new StringFilterGroup( null, "suggested_action.eml" ); addPathCallbacks( - shortsCompactFeedVideoPath, - joinButton, subscribeButton, subscribeButtonPaused, suggestedActionPath, - channelBar, fullVideoLinkLabel, videoTitle, reelSoundMetadata, - soundButton, infoPanel, actionBar + shortsCompactFeedVideoPath, suggestedAction, actionBar, joinButton, subscribeButton, + pausedOverlayButtons, channelBar, fullVideoLinkLabel, videoTitle, reelSoundMetadata, + soundButton, infoPanel ); // // Action buttons // - var shortsLikeButton = new ByteArrayFilterGroup( - Settings.HIDE_SHORTS_LIKE_BUTTON, - "shorts_like_button" - ); - - var shortsDislikeButton = new ByteArrayFilterGroup( - Settings.HIDE_SHORTS_DISLIKE_BUTTON, - "shorts_dislike_button" - ); - - var shortsCommentButton = new ByteArrayFilterGroup( - Settings.HIDE_SHORTS_COMMENTS_BUTTON, - "reel_comment_button" - ); - - var shortsShareButton = new ByteArrayFilterGroup( - Settings.HIDE_SHORTS_SHARE_BUTTON, - "reel_share_button" - ); - - var shortsRemixButton = new ByteArrayFilterGroup( - Settings.HIDE_SHORTS_REMIX_BUTTON, - "reel_remix_button" - ); - videoActionButtonGroupList.addAll( - shortsLikeButton, - shortsDislikeButton, - shortsCommentButton, - shortsShareButton, - shortsRemixButton + // This also appears as the path item 'shorts_like_button.eml' + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_LIKE_BUTTON, + "reel_like_button", + "reel_like_toggled_button" + ), + // This also appears as the path item 'shorts_dislike_button.eml' + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_DISLIKE_BUTTON, + "reel_dislike_button", + "reel_dislike_toggled_button" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_COMMENTS_BUTTON, + "reel_comment_button" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_SHARE_BUTTON, + "reel_share_button" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_REMIX_BUTTON, + "reel_remix_button" + ) ); // // Suggested actions. // - suggestedActions.addAll( + suggestedActionsGroupList.addAll( new ByteArrayFilterGroup( Settings.HIDE_SHORTS_SHOP_BUTTON, "yt_outline_bag_" ), new ByteArrayFilterGroup( - Settings.HIDE_SHORTS_LOCATION_BUTTON, + Settings.HIDE_SHORTS_TAGGED_PRODUCTS, + // Product buttons show pictures of the products, and does not have any unique icons to identify. + // Instead use a unique identifier found in the buffer. + "PAproduct_listZ" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_LOCATION_LABEL, "yt_outline_location_point_" ), new ByteArrayFilterGroup( Settings.HIDE_SHORTS_SAVE_SOUND_BUTTON, "yt_outline_list_add_" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_SEARCH_SUGGESTIONS, + "yt_outline_search_" ) ); } @@ -201,15 +191,15 @@ public final class ShortsFilter extends Filter { boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (contentType == FilterContentType.PATH) { - // Always filter if matched. - if (matchedGroup == soundButton || - matchedGroup == infoPanel || - matchedGroup == channelBar || - matchedGroup == fullVideoLinkLabel || - matchedGroup == videoTitle || - matchedGroup == reelSoundMetadata || - matchedGroup == subscribeButtonPaused - ) return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); + if (matchedGroup == subscribeButton || matchedGroup == joinButton) { + // Filter only when reelChannelBar is visible to avoid false positives. + if (path.startsWith(REEL_CHANNEL_BAR_PATH)) { + return super.isFiltered( + identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex + ); + } + return false; + } if (matchedGroup == shortsCompactFeedVideoPath) { if (shouldHideShortsFeedItems() && contentIndex == 0 @@ -219,32 +209,27 @@ public final class ShortsFilter extends Filter { return false; } - if (matchedGroup == subscribeButton || matchedGroup == joinButton) { - // Filter only when reelChannelBar is visible to avoid false positives. - if (path.startsWith(REEL_CHANNEL_BAR_PATH)) return super.isFiltered( - identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex - ); - return false; - } - // Video action buttons (like, dislike, comment, share, remix) have the same path. if (matchedGroup == actionBar) { - if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) return super.isFiltered( - identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex - ); + if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) { + return super.isFiltered( + identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex + ); + } return false; } - if (matchedGroup == suggestedActionPath) { - if (contentIndex == 0 && suggestedActions.check(protobufBufferArray).isFiltered()) return super.isFiltered( - identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex - ); - // else, return false; + if (matchedGroup == suggestedAction) { + if (contentIndex == 0 && suggestedActionsGroupList.check(protobufBufferArray).isFiltered()) { + return super.isFiltered( + identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex + ); + } + return false; } - return false; } else { - // Feed/search path components. + // Feed/search identifier components. if (matchedGroup == shelfHeader) { // Because the header is used in watch history and possibly other places, check for the index, // which is 0 when the shelf header is used for Shorts. diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java index d6617681..f7432af5 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java @@ -159,11 +159,12 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_SHORTS_SEARCH = new BooleanSetting("revanced_hide_shorts_search", FALSE); public static final BooleanSetting HIDE_SHORTS_JOIN_BUTTON = new BooleanSetting("revanced_hide_shorts_join_button", TRUE); public static final BooleanSetting HIDE_SHORTS_SUBSCRIBE_BUTTON = new BooleanSetting("revanced_hide_shorts_subscribe_button", TRUE); - public static final BooleanSetting HIDE_SHORTS_SUBSCRIBE_BUTTON_PAUSED = new BooleanSetting("revanced_hide_shorts_subscribe_button_paused", FALSE); - public static final BooleanSetting HIDE_SHORTS_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_thanks_button", TRUE); + public static final BooleanSetting HIDE_SHORTS_PAUSED_OVERLAY_BUTTONS = new BooleanSetting("revanced_hide_shorts_paused_overlay_buttons", FALSE); public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE); - public static final BooleanSetting HIDE_SHORTS_LOCATION_BUTTON = new BooleanSetting("revanced_hide_shorts_location_button", FALSE); + public static final BooleanSetting HIDE_SHORTS_TAGGED_PRODUCTS = new BooleanSetting("revanced_hide_shorts_tagged_products", TRUE); + public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE); public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", FALSE); + public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", FALSE); public static final BooleanSetting HIDE_SHORTS_LIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_like_button", FALSE); public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE); public static final BooleanSetting HIDE_SHORTS_COMMENTS_BUTTON = new BooleanSetting("revanced_hide_shorts_comments_button", FALSE);