mirror of
https://github.com/revanced/revanced-integrations.git
synced 2024-08-31 11:35:24 +02:00
feat(YouTube - Hide Shorts components): Selectively hide Shorts for home / subscription / search (#592)
This commit is contained in:
parent
4ae7d5b178
commit
1ee99aa6f0
@ -112,6 +112,37 @@ final class KeywordContentFilter extends Filter {
|
|||||||
|
|
||||||
private volatile ByteTrieSearch bufferSearch;
|
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.
|
* Change first letter of the first word to use title case.
|
||||||
*/
|
*/
|
||||||
@ -224,15 +255,6 @@ final class KeywordContentFilter extends Filter {
|
|||||||
addPathCallbacks(startsWithFilter, containsFilter);
|
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
|
@Override
|
||||||
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||||
@ -240,34 +262,7 @@ final class KeywordContentFilter extends Filter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NavigationBar.isSearchBarActive()) {
|
if (!hideKeywordSettingIsActive()) return false;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field is intentionally compared using reference equality.
|
// Field is intentionally compared using reference equality.
|
||||||
if (Settings.HIDE_KEYWORD_CONTENT_PHRASES.get() != lastKeywordPhrasesParsed) {
|
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);
|
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,15 +1,19 @@
|
|||||||
package app.revanced.integrations.youtube.patches.components;
|
package app.revanced.integrations.youtube.patches.components;
|
||||||
|
|
||||||
|
import static app.revanced.integrations.shared.Utils.hideViewUnderCondition;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import app.revanced.integrations.youtube.settings.Settings;
|
|
||||||
import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
|
import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
|
||||||
|
|
||||||
import static app.revanced.integrations.shared.Utils.hideViewBy1dpUnderCondition;
|
import app.revanced.integrations.shared.Utils;
|
||||||
import static app.revanced.integrations.shared.Utils.hideViewUnderCondition;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
|
import app.revanced.integrations.youtube.shared.NavigationBar;
|
||||||
|
import app.revanced.integrations.youtube.shared.PlayerType;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
@ -35,8 +39,10 @@ public final class ShortsFilter extends Filter {
|
|||||||
private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList();
|
private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList();
|
||||||
|
|
||||||
public ShortsFilter() {
|
public ShortsFilter() {
|
||||||
|
// Identifier components.
|
||||||
|
|
||||||
var shorts = new StringFilterGroup(
|
var shorts = new StringFilterGroup(
|
||||||
Settings.HIDE_SHORTS,
|
null, // Setting is based on navigation state.
|
||||||
"shorts_shelf",
|
"shorts_shelf",
|
||||||
"inline_shorts",
|
"inline_shorts",
|
||||||
"shorts_grid",
|
"shorts_grid",
|
||||||
@ -46,7 +52,7 @@ public final class ShortsFilter extends Filter {
|
|||||||
// Feed Shorts shelf header.
|
// Feed Shorts shelf header.
|
||||||
// Use a different filter group for this pattern, as it requires an additional check after matching.
|
// Use a different filter group for this pattern, as it requires an additional check after matching.
|
||||||
shelfHeader = new StringFilterGroup(
|
shelfHeader = new StringFilterGroup(
|
||||||
Settings.HIDE_SHORTS,
|
null,
|
||||||
"shelf_header.eml"
|
"shelf_header.eml"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -58,14 +64,14 @@ public final class ShortsFilter extends Filter {
|
|||||||
|
|
||||||
addIdentifierCallbacks(shorts, shelfHeader, thanksButton);
|
addIdentifierCallbacks(shorts, shelfHeader, thanksButton);
|
||||||
|
|
||||||
|
// Path components.
|
||||||
|
|
||||||
// Shorts that appear in the feed/search when the device is using tablet layout.
|
// Shorts that appear in the feed/search when the device is using tablet layout.
|
||||||
shortsCompactFeedVideoPath = new StringFilterGroup(Settings.HIDE_SHORTS,
|
shortsCompactFeedVideoPath = new StringFilterGroup(null, "compact_video.eml");
|
||||||
"compact_video.eml");
|
|
||||||
// Filter out items that use the 'frame0' thumbnail.
|
// Filter out items that use the 'frame0' thumbnail.
|
||||||
// This is a valid thumbnail for both regular videos and Shorts,
|
// This is a valid thumbnail for both regular videos and Shorts,
|
||||||
// but it appears these thumbnails are used only for Shorts.
|
// but it appears these thumbnails are used only for Shorts.
|
||||||
shortsCompactFeedVideoBuffer = new ByteArrayFilterGroup(Settings.HIDE_SHORTS,
|
shortsCompactFeedVideoBuffer = new ByteArrayFilterGroup(null, "/frame0.jpg");
|
||||||
"/frame0.jpg");
|
|
||||||
|
|
||||||
// Shorts player components.
|
// Shorts player components.
|
||||||
joinButton = new StringFilterGroup(
|
joinButton = new StringFilterGroup(
|
||||||
@ -174,7 +180,8 @@ public final class ShortsFilter extends Filter {
|
|||||||
) return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
) return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||||
|
|
||||||
if (matchedGroup == shortsCompactFeedVideoPath) {
|
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 super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -195,22 +202,41 @@ public final class ShortsFilter extends Filter {
|
|||||||
) {
|
) {
|
||||||
if (path.startsWith(REEL_CHANNEL_BAR_PATH)) return super.isFiltered(
|
if (path.startsWith(REEL_CHANNEL_BAR_PATH)) return super.isFiltered(
|
||||||
identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex
|
identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex
|
||||||
);
|
); // else, return false.
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else if (matchedGroup == shelfHeader) {
|
} else {
|
||||||
// Because the header is used in watch history and possibly other places, check for the index,
|
// Feed/search path components.
|
||||||
// which is 0 when the shelf header is used for Shorts.
|
if (matchedGroup == shelfHeader) {
|
||||||
if (contentIndex != 0) return false;
|
// 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.
|
// Super class handles logging.
|
||||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
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) {
|
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.
|
// region Hide the buttons in older versions of YouTube. New versions use Litho.
|
||||||
|
@ -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_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_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_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_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_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", "",
|
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_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_MEDICAL_PANELS = new BooleanSetting("revanced_hide_medical_panels", TRUE);
|
||||||
public static final BooleanSetting HIDE_MIX_PLAYLISTS = new BooleanSetting("revanced_hide_mix_playlists", 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);
|
public static final BooleanSetting HIDE_TRANSCIPT_SECTION = new BooleanSetting("revanced_hide_transcript_section", TRUE);
|
||||||
|
|
||||||
// Shorts
|
// 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_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 = 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_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).
|
// Remove any previously saved announcement consumer (a random generated string).
|
||||||
Setting.preferences.saveString("revanced_announcement_consumer", null);
|
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
|
// endregion
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user