diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/KeywordContentFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/KeywordContentFilter.java index 6ea91beb..0cbc8f71 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/KeywordContentFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/KeywordContentFilter.java @@ -112,6 +112,37 @@ final class KeywordContentFilter extends Filter { private volatile ByteTrieSearch bufferSearch; + private static void logNavigationState(String state) { + // Enable locally to debug filtering. Default off to reduce log spam. + final boolean LOG_NAVIGATION_STATE = false; + // noinspection ConstantValue + if (LOG_NAVIGATION_STATE) { + Logger.printDebug(() -> "Navigation state: " + state); + } + } + + private static boolean hideKeywordSettingIsActive() { + if (NavigationBar.isSearchBarActive()) { + // Must check first. Search bar can be active with almost any tab. + logNavigationState("Search"); + return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get(); + } else if (PlayerType.getCurrent().isMaximizedOrFullscreen()) { + // For now, consider the under video results the same as the home feed. + logNavigationState("Player active"); + return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); + } else if (NavigationButton.HOME.isSelected()) { + logNavigationState("Home tab"); + return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); + } else if (NavigationButton.SUBSCRIPTIONS.isSelected()) { + logNavigationState("Subscription tab"); + return Settings.HIDE_SUBSCRIPTIONS_BUTTON.get(); + } else { + // User is in the Library or Notifications tab. + logNavigationState("Ignored tab"); + } + return false; + } + /** * Change first letter of the first word to use title case. */ @@ -224,15 +255,6 @@ final class KeywordContentFilter extends Filter { addPathCallbacks(startsWithFilter, containsFilter); } - private static void logNavigationState(String state) { - // Enable locally to debug filtering. Default off to reduce log spam. - final boolean LOG_NAVIGATION_STATE = false; - // noinspection ConstantValue - if (LOG_NAVIGATION_STATE) { - Logger.printDebug(() -> "Navigation state: " + state); - } - } - @Override public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { @@ -240,34 +262,7 @@ final class KeywordContentFilter extends Filter { return false; } - if (NavigationBar.isSearchBarActive()) { - // Search bar can be active with almost any tab active. - if (!Settings.HIDE_KEYWORD_CONTENT_SEARCH.get()) { - return false; - } - logNavigationState("Search"); - } else if (PlayerType.getCurrent().isMaximizedOrFullscreen()) { - // For now, consider the under video results the same as the home feed. - if (!Settings.HIDE_KEYWORD_CONTENT_HOME.get()) { - return false; - } - logNavigationState("Player active"); - } else if (NavigationButton.HOME.isSelected()) { - // Could use a Switch statement, but there is only 2 tabs of interest. - if (!Settings.HIDE_KEYWORD_CONTENT_HOME.get()) { - return false; - } - logNavigationState("Home tab"); - } else if (NavigationButton.SUBSCRIPTIONS.isSelected()) { - if (!Settings.HIDE_SUBSCRIPTIONS_BUTTON.get()) { - return false; - } - logNavigationState("Subscription tab"); - } else { - // User is in the Library or Notifications tab. - logNavigationState("Ignored tab"); - return false; - } + if (!hideKeywordSettingIsActive()) return false; // Field is intentionally compared using reference equality. if (Settings.HIDE_KEYWORD_CONTENT_PHRASES.get() != lastKeywordPhrasesParsed) { @@ -281,4 +276,5 @@ final class KeywordContentFilter extends Filter { return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } + } \ No newline at end of file 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 8bbcae7f..90a64f56 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 @@ -1,15 +1,19 @@ package app.revanced.integrations.youtube.patches.components; +import static app.revanced.integrations.shared.Utils.hideViewUnderCondition; + import android.os.Build; import android.view.View; + import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import app.revanced.integrations.youtube.settings.Settings; import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar; -import static app.revanced.integrations.shared.Utils.hideViewBy1dpUnderCondition; -import static app.revanced.integrations.shared.Utils.hideViewUnderCondition; +import app.revanced.integrations.shared.Utils; +import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.youtube.shared.NavigationBar; +import app.revanced.integrations.youtube.shared.PlayerType; @SuppressWarnings("unused") @RequiresApi(api = Build.VERSION_CODES.N) @@ -35,8 +39,10 @@ public final class ShortsFilter extends Filter { private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList(); public ShortsFilter() { + // Identifier components. + var shorts = new StringFilterGroup( - Settings.HIDE_SHORTS, + null, // Setting is based on navigation state. "shorts_shelf", "inline_shorts", "shorts_grid", @@ -46,7 +52,7 @@ public final class ShortsFilter extends Filter { // Feed Shorts shelf header. // Use a different filter group for this pattern, as it requires an additional check after matching. shelfHeader = new StringFilterGroup( - Settings.HIDE_SHORTS, + null, "shelf_header.eml" ); @@ -58,14 +64,14 @@ public final class ShortsFilter extends Filter { addIdentifierCallbacks(shorts, shelfHeader, thanksButton); + // Path components. + // Shorts that appear in the feed/search when the device is using tablet layout. - shortsCompactFeedVideoPath = new StringFilterGroup(Settings.HIDE_SHORTS, - "compact_video.eml"); + shortsCompactFeedVideoPath = new StringFilterGroup(null, "compact_video.eml"); // Filter out items that use the 'frame0' thumbnail. // This is a valid thumbnail for both regular videos and Shorts, // but it appears these thumbnails are used only for Shorts. - shortsCompactFeedVideoBuffer = new ByteArrayFilterGroup(Settings.HIDE_SHORTS, - "/frame0.jpg"); + shortsCompactFeedVideoBuffer = new ByteArrayFilterGroup(null, "/frame0.jpg"); // Shorts player components. joinButton = new StringFilterGroup( @@ -174,7 +180,8 @@ public final class ShortsFilter extends Filter { ) return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); if (matchedGroup == shortsCompactFeedVideoPath) { - if (contentIndex == 0 && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered()) { + if (shouldHideShortsFeedItems() && contentIndex == 0 + && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered()) { return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } return false; @@ -195,22 +202,41 @@ public final class ShortsFilter extends Filter { ) { if (path.startsWith(REEL_CHANNEL_BAR_PATH)) return super.isFiltered( identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex - ); + ); // else, return false. } return false; - } else 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. - if (contentIndex != 0) return false; + } else { + // Feed/search path 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. + if (contentIndex != 0) return false; + } + + if (!shouldHideShortsFeedItems()) return false; } // Super class handles logging. return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } + private static boolean shouldHideShortsFeedItems() { + if (NavigationBar.isSearchBarActive()) { // Must check search first. + return Settings.HIDE_SHORTS_SEARCH.get(); + } else if (PlayerType.getCurrent().isMaximizedOrFullscreen() + || NavigationBar.NavigationButton.HOME.isSelected()) { + return Settings.HIDE_SHORTS_HOME.get(); + } else if (NavigationBar.NavigationButton.SUBSCRIPTIONS.isSelected()) { + return Settings.HIDE_SHORTS_SUBSCRIPTIONS.get(); + } + return false; + } + public static void hideShortsShelf(final View shortsShelfView) { - hideViewBy1dpUnderCondition(Settings.HIDE_SHORTS, shortsShelfView); + if (shouldHideShortsFeedItems()) { + Utils.hideViewByLayoutParams(shortsShelfView); + } } // region Hide the buttons in older versions of YouTube. New versions use Litho. 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 8f2c43e4..1bb6ecaa 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 @@ -98,11 +98,11 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_IMAGE_SHELF = new BooleanSetting("revanced_hide_image_shelf", TRUE); public static final BooleanSetting HIDE_INFO_CARDS = new BooleanSetting("revanced_hide_info_cards", TRUE); public static final BooleanSetting HIDE_JOIN_MEMBERSHIP_BUTTON = new BooleanSetting("revanced_hide_join_membership_button", TRUE); - public static final BooleanSetting HIDE_KEYWORD_CONTENT_SEARCH = new BooleanSetting("revanced_hide_keyword_content_search", FALSE); public static final BooleanSetting HIDE_KEYWORD_CONTENT_HOME = new BooleanSetting("revanced_hide_keyword_content_home", FALSE); public static final BooleanSetting HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS = new BooleanSetting("revanced_hide_keyword_content_subscriptions", FALSE); + public static final BooleanSetting HIDE_KEYWORD_CONTENT_SEARCH = new BooleanSetting("revanced_hide_keyword_content_search", FALSE); public static final StringSetting HIDE_KEYWORD_CONTENT_PHRASES = new StringSetting("revanced_hide_keyword_content_phrases", "", - parentsAny(HIDE_KEYWORD_CONTENT_SEARCH, HIDE_KEYWORD_CONTENT_HOME, HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS)); + parentsAny(HIDE_KEYWORD_CONTENT_HOME, HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS, HIDE_KEYWORD_CONTENT_SEARCH)); public static final BooleanSetting HIDE_LOAD_MORE_BUTTON = new BooleanSetting("revanced_hide_load_more_button", TRUE, true); public static final BooleanSetting HIDE_MEDICAL_PANELS = new BooleanSetting("revanced_hide_medical_panels", TRUE); public static final BooleanSetting HIDE_MIX_PLAYLISTS = new BooleanSetting("revanced_hide_mix_playlists", TRUE); @@ -141,7 +141,10 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_TRANSCIPT_SECTION = new BooleanSetting("revanced_hide_transcript_section", TRUE); // Shorts - public static final BooleanSetting HIDE_SHORTS = new BooleanSetting("revanced_hide_shorts", FALSE, true); + @Deprecated public static final BooleanSetting DEPRECATED_HIDE_SHORTS = new BooleanSetting("revanced_hide_shorts", FALSE); + public static final BooleanSetting HIDE_SHORTS_HOME = new BooleanSetting("revanced_hide_shorts_home", FALSE); + public static final BooleanSetting HIDE_SHORTS_SUBSCRIPTIONS = new BooleanSetting("revanced_hide_shorts_subscriptions", FALSE); + 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); @@ -362,6 +365,14 @@ public class Settings extends BaseSettings { // Remove any previously saved announcement consumer (a random generated string). Setting.preferences.saveString("revanced_announcement_consumer", null); + // Shorts + if (DEPRECATED_HIDE_SHORTS.get()) { + Logger.printInfo(() -> "Migrating hide Shorts setting"); + DEPRECATED_HIDE_SHORTS.resetToDefault(); + HIDE_SHORTS_HOME.save(true); + HIDE_SHORTS_SUBSCRIPTIONS.save(true); + HIDE_SHORTS_SEARCH.save(true); + } // endregion }