feat(YouTube - Hide Shorts components): Selectively hide Shorts for home / subscription / search (#592)

This commit is contained in:
LisoUseInAIKyrios 2024-03-27 17:44:01 +04:00 committed by GitHub
parent 4ae7d5b178
commit 1ee99aa6f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 89 additions and 56 deletions

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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
}