From 3a3ceec4b596354dcccbf3516ef1634bd8819b90 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 23 Jun 2024 15:46:42 +0300 Subject: [PATCH 1/9] fix(YouTube - Hide layout components): Detect if a keyword filter hides all videos (#657) --- .../revanced/integrations/shared/Utils.java | 1 + .../integrations/youtube/ThemeHelper.java | 2 + .../integrations/youtube/TrieSearch.java | 4 +- .../DisableSuggestedVideoEndScreenPatch.java | 5 - .../patches/PlayerOverlaysHookPatch.java | 2 - .../youtube/patches/VideoInformation.java | 1 + .../components/KeywordContentFilter.java | 176 ++++++++++++++---- .../patches/components/LithoFilterPatch.java | 1 + .../ReVancedPreferenceFragment.java | 2 - 9 files changed, 142 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/shared/Utils.java b/app/src/main/java/app/revanced/integrations/shared/Utils.java index cc53abf5d3..f0c17e8c26 100644 --- a/app/src/main/java/app/revanced/integrations/shared/Utils.java +++ b/app/src/main/java/app/revanced/integrations/shared/Utils.java @@ -54,6 +54,7 @@ private Utils() { * * @return The manifest 'Version' entry of the patches.jar used during patching. */ + @SuppressWarnings("SameReturnValue") public static String getPatchesReleaseVersion() { return ""; // Value is replaced during patching. } diff --git a/app/src/main/java/app/revanced/integrations/youtube/ThemeHelper.java b/app/src/main/java/app/revanced/integrations/youtube/ThemeHelper.java index c9f7536b52..65d29b97ea 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/ThemeHelper.java +++ b/app/src/main/java/app/revanced/integrations/youtube/ThemeHelper.java @@ -39,6 +39,7 @@ public static void setActivityTheme(Activity activity) { /** * Injection point. */ + @SuppressWarnings("SameReturnValue") private static String darkThemeResourceName() { // Value is changed by Theme patch, if included. return "@color/yt_black3"; @@ -58,6 +59,7 @@ public static int getDarkThemeColor() { /** * Injection point. */ + @SuppressWarnings("SameReturnValue") private static String lightThemeResourceName() { // Value is changed by Theme patch, if included. return "@color/yt_white1"; diff --git a/app/src/main/java/app/revanced/integrations/youtube/TrieSearch.java b/app/src/main/java/app/revanced/integrations/youtube/TrieSearch.java index 1c927cd2d5..12b385a7fc 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/TrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/TrieSearch.java @@ -380,7 +380,7 @@ private boolean matches(@NonNull T textToSearch, int textToSearchLength, int sta throw new IllegalArgumentException("endIndex: " + endIndex + " is greater than texToSearchLength: " + textToSearchLength); } - if (patterns.size() == 0) { + if (patterns.isEmpty()) { return false; // No patterns were added. } for (int i = startIndex; i < endIndex; i++) { @@ -393,7 +393,7 @@ private boolean matches(@NonNull T textToSearch, int textToSearchLength, int sta * @return Estimated memory size (in kilobytes) of this instance. */ public int getEstimatedMemorySize() { - if (patterns.size() == 0) { + if (patterns.isEmpty()) { return 0; } // Assume the device has less than 32GB of ram (and can use pointer compression), diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java index 0b7897bac0..27c0a07d52 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java @@ -1,13 +1,8 @@ package app.revanced.integrations.youtube.patches; import android.annotation.SuppressLint; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.widget.ImageView; -import androidx.annotation.NonNull; -import app.revanced.integrations.shared.Logger; import app.revanced.integrations.youtube.settings.Settings; /** @noinspection unused*/ diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java index 32732cdcc3..c51055e261 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java @@ -2,8 +2,6 @@ import android.view.ViewGroup; -import androidx.annotation.Nullable; - import app.revanced.integrations.youtube.shared.PlayerOverlays; @SuppressWarnings("unused") diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java b/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java index 8cf525f3c7..695af32693 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java @@ -278,6 +278,7 @@ public static long getVideoTime() { * * @see VideoState */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public static boolean isAtEndOfVideo() { return videoTime >= videoLength && videoLength > 0; } 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 98f1ceebc8..c3813178d9 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 @@ -1,7 +1,6 @@ package app.revanced.integrations.youtube.patches.components; import static app.revanced.integrations.shared.StringRef.str; -import static app.revanced.integrations.youtube.ByteTrieSearch.convertStringsToBytes; import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton; import android.os.Build; @@ -10,13 +9,16 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.Utils; import app.revanced.integrations.youtube.ByteTrieSearch; +import app.revanced.integrations.youtube.TrieSearch; import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.youtube.shared.NavigationBar; import app.revanced.integrations.youtube.shared.PlayerType; @@ -65,13 +67,18 @@ final class KeywordContentFilter extends Filter { // Video decoders. "OMX.ffmpeg.vp9.decoder", "OMX.Intel.sw_vd.vp9", - "OMX.sprd.av1.decoder", "OMX.MTK.VIDEO.DECODER.SW.VP9", + "OMX.google.vp9.decoder", + "OMX.google.av1.decoder", + "OMX.sprd.av1.decoder", "c2.android.av1.decoder", + "c2.android.av1-dav1d.decoder", + "c2.android.vp9.decoder", "c2.mtk.sw.vp9.decoder", // User analytics. "https://ad.doubleclick.net/ddm/activity/", "DEVICE_ADVERTISER_ID_FOR_CONVERSION_TRACKING", + "tag_for_child_directed_treatment", // Found in overflow menu such as 'Watch later'. // Litho components frequently found in the buffer that belong to the path filter items. "metadata.eml", "thumbnail.eml", @@ -97,6 +104,7 @@ final class KeywordContentFilter extends Filter { /** * Substrings that are never at the start of the path. */ + @SuppressWarnings("FieldCanBeLocal") private final StringFilterGroup containsFilter = new StringFilterGroup( null, "modern_type_shelf_header_content.eml", @@ -104,6 +112,38 @@ final class KeywordContentFilter extends Filter { "video_card.eml" // Shorts that appear in a horizontal shelf. ); + /** + * Threshold for {@link #filteredVideosPercentage} + * that indicates all or nearly all videos have been filtered. + * This should be close to 100% to reduce false positives. + */ + private static final float ALL_VIDEOS_FILTERED_THRESHOLD = 0.95f; + + private static final float ALL_VIDEOS_FILTERED_SAMPLE_SIZE = 50; + + private static final long ALL_VIDEOS_FILTERED_TIMEOUT_MILLISECONDS = 60 * 1000; // 60 seconds + + /** + * Rolling average of how many videos were filtered by a keyword. + * Used to detect if a keyword passes the initial check against {@link #STRINGS_IN_EVERY_BUFFER} + * but a keyword is still hiding all videos. + * + * This check can still fail if some extra UI elements pass the keywords, + * such as the video chapter preview or any other elements. + * + * To test this, add a filter that appears in all videos (such as 'ovd='), + * and open the subscription feed. In practice this does not always identify problems + * in the home feed and search, because the home feed has a finite amount of content and + * search results have a lot of extra video junk that is not hidden and interferes with the detection. + */ + private volatile float filteredVideosPercentage; + + /** + * If filtering is temporarily turned off, the time to resume filtering. + * Field is zero if no timeout is in effect. + */ + private volatile long timeToResumeFiltering; + /** * The last value of {@link Settings#HIDE_KEYWORD_CONTENT_PHRASES} * parsed and loaded into {@link #bufferSearch}. @@ -113,39 +153,6 @@ final class KeywordContentFilter extends Filter { private volatile ByteTrieSearch bufferSearch; - private static boolean hideKeywordSettingIsActive() { - // Must check player type first, as search bar can be active behind the player. - if (PlayerType.getCurrent().isMaximizedOrFullscreen()) { - // For now, consider the under video results the same as the home feed. - return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); - } - - // Must check second, as search can be from any tab. - if (NavigationBar.isSearchBarActive()) { - return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get(); - } - - // Avoid checking navigation button status if all other settings are off. - final boolean hideHome = Settings.HIDE_KEYWORD_CONTENT_HOME.get(); - final boolean hideSubscriptions = Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS.get(); - if (!hideHome && !hideSubscriptions) { - return false; - } - - NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton(); - if (selectedNavButton == null) { - return hideHome; // Unknown tab, treat the same as home. - } - if (selectedNavButton == NavigationButton.HOME) { - return hideHome; - } - if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) { - return hideSubscriptions; - } - // User is in the Library or Notifications tab. - return false; - } - /** * Change first letter of the first word to use title case. */ @@ -247,11 +254,26 @@ private synchronized void parseKeywords() { // Must be synchronized since Litho keywords.addAll(Arrays.asList(phraseVariations)); } - search.addPatterns(convertStringsToBytes(keywords.toArray(new String[0]))); + for (String keyword : keywords) { + // Use a callback to get the keyword that matched. + // TrieSearch could have this built in, but that's slightly more complicated since + // the strings are stored as a byte array and embedded in the search tree. + TrieSearch.TriePatternMatchedCallback callback = + (textSearched, matchedStartIndex, matchedLength, callbackParameter) -> { + // noinspection unchecked + ((MutableReference) callbackParameter).value = keyword; + return true; + }; + byte[] stringBytes = keyword.getBytes(StandardCharsets.UTF_8); + search.addPattern(stringBytes, callback); + } + Logger.printDebug(() -> "Search using: (" + search.getEstimatedMemorySize() + " KB) keywords: " + keywords); } bufferSearch = search; + timeToResumeFiltering = 0; + filteredVideosPercentage = 0; lastKeywordPhrasesParsed = rawKeywords; // Must set last. } @@ -260,6 +282,69 @@ public KeywordContentFilter() { addPathCallbacks(startsWithFilter, containsFilter); } + private boolean hideKeywordSettingIsActive() { + if (timeToResumeFiltering != 0) { + if (System.currentTimeMillis() < timeToResumeFiltering) { + return false; + } + + timeToResumeFiltering = 0; + filteredVideosPercentage = 0; + Logger.printDebug(() -> "Resuming keyword filtering"); + } + + // Must check player type first, as search bar can be active behind the player. + if (PlayerType.getCurrent().isMaximizedOrFullscreen()) { + // For now, consider the under video results the same as the home feed. + return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); + } + + // Must check second, as search can be from any tab. + if (NavigationBar.isSearchBarActive()) { + return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get(); + } + + // Avoid checking navigation button status if all other settings are off. + final boolean hideHome = Settings.HIDE_KEYWORD_CONTENT_HOME.get(); + final boolean hideSubscriptions = Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS.get(); + if (!hideHome && !hideSubscriptions) { + return false; + } + + NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton(); + if (selectedNavButton == null) { + return hideHome; // Unknown tab, treat the same as home. + } + if (selectedNavButton == NavigationButton.HOME) { + return hideHome; + } + if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) { + return hideSubscriptions; + } + // User is in the Library or Notifications tab. + return false; + } + + private void updateStats(boolean videoWasHidden, @Nullable String keyword) { + float updatedAverage = filteredVideosPercentage + * ((ALL_VIDEOS_FILTERED_SAMPLE_SIZE - 1) / ALL_VIDEOS_FILTERED_SAMPLE_SIZE); + if (videoWasHidden) { + updatedAverage += 1 / ALL_VIDEOS_FILTERED_SAMPLE_SIZE; + } + + if (updatedAverage <= ALL_VIDEOS_FILTERED_THRESHOLD) { + filteredVideosPercentage = updatedAverage; + return; + } + + // A keyword is hiding everything. + // Inform the user, and temporarily turn off filtering. + timeToResumeFiltering = System.currentTimeMillis() + ALL_VIDEOS_FILTERED_TIMEOUT_MILLISECONDS; + + Logger.printDebug(() -> "Temporarily turning off filtering due to excessively broad filter: " + keyword); + Utils.showToastLong(str("revanced_hide_keyword_toast_invalid_broad", keyword)); + } + @Override boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { @@ -267,8 +352,6 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff return false; } - if (!hideKeywordSettingIsActive()) return false; - // Field is intentionally compared using reference equality. //noinspection StringEquality if (Settings.HIDE_KEYWORD_CONTENT_PHRASES.get() != lastKeywordPhrasesParsed) { @@ -276,11 +359,22 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff parseKeywords(); } - if (!bufferSearch.matches(protobufBufferArray)) { - return false; + if (!hideKeywordSettingIsActive()) return false; + + MutableReference matchRef = new MutableReference<>(); + if (bufferSearch.matches(protobufBufferArray, matchRef)) { + updateStats(true, matchRef.value); + return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } - return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); + updateStats(false, null); + return false; } +} +/** + * Simple non-atomic wrapper since {@link AtomicReference#setPlain(Object)} is not available with Android 8.0. + */ +final class MutableReference { + T value; } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LithoFilterPatch.java index e1bb9d6780..a7c9972004 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LithoFilterPatch.java @@ -96,6 +96,7 @@ public boolean isEnabled() { * @return If {@link FilterGroupList} should include this group when searching. * By default, all filters are included except non enabled settings that require reboot. */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean includeInSearch() { return isEnabled() || !setting.rebootApp; } diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java index 1f3bd6c012..58fd974633 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java @@ -3,13 +3,11 @@ import android.os.Build; import android.preference.ListPreference; import android.preference.Preference; -import android.preference.PreferenceGroup; import androidx.annotation.RequiresApi; import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment; -import app.revanced.integrations.youtube.patches.DownloadsPatch; import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.integrations.youtube.settings.Settings; From 3dda3de28044d5c9b1b76cb56bfc4c90fc542302 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 23 Jun 2024 12:50:16 +0000 Subject: [PATCH 2/9] chore(release): 1.11.1-dev.1 [skip ci] ## [1.11.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.0...v1.11.1-dev.1) (2024-06-23) ### Bug Fixes * **YouTube - Hide layout components:** Detect if a keyword filter hides all videos ([#657](https://github.com/ReVanced/revanced-integrations/issues/657)) ([3a3ceec](https://github.com/ReVanced/revanced-integrations/commit/3a3ceec4b596354dcccbf3516ef1634bd8819b90)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46da0a24a7..59e896ea40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.11.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.0...v1.11.1-dev.1) (2024-06-23) + + +### Bug Fixes + +* **YouTube - Hide layout components:** Detect if a keyword filter hides all videos ([#657](https://github.com/ReVanced/revanced-integrations/issues/657)) ([3a3ceec](https://github.com/ReVanced/revanced-integrations/commit/3a3ceec4b596354dcccbf3516ef1634bd8819b90)) + # [1.11.0](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0...v1.11.0) (2024-06-23) diff --git a/gradle.properties b/gradle.properties index d06a595f03..1489fb3a53 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.11.0 +version = 1.11.1-dev.1 From c237e3c02c971fb1801663cb662096d319c04928 Mon Sep 17 00:00:00 2001 From: Bceez <153008658+Bceez@users.noreply.github.com> Date: Sun, 30 Jun 2024 20:42:52 +0200 Subject: [PATCH 3/9] fix(YouTube - Hide layout components): Hide new kind of community post (#659) fix(YouTube - Hide layout components) Community posts not hiding --- .../youtube/patches/components/LayoutComponentsFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java index 522658c524..69908576f8 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java @@ -80,7 +80,8 @@ public LayoutComponentsFilter() { final var communityPosts = new StringFilterGroup( Settings.HIDE_COMMUNITY_POSTS, "post_base_wrapper", - "image_post_root.eml" + "image_post_root.eml", + "text_post_root.eml" ); final var communityGuidelines = new StringFilterGroup( From d9f76790207712ed021c5ec48eb0cfb88f2d950f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 30 Jun 2024 18:45:48 +0000 Subject: [PATCH 4/9] chore(release): 1.11.1-dev.2 [skip ci] ## [1.11.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.1...v1.11.1-dev.2) (2024-06-30) ### Bug Fixes * **YouTube - Hide layout components:** Hide new kind of community post ([#659](https://github.com/ReVanced/revanced-integrations/issues/659)) ([c237e3c](https://github.com/ReVanced/revanced-integrations/commit/c237e3c02c971fb1801663cb662096d319c04928)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59e896ea40..1382d2001b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.11.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.1...v1.11.1-dev.2) (2024-06-30) + + +### Bug Fixes + +* **YouTube - Hide layout components:** Hide new kind of community post ([#659](https://github.com/ReVanced/revanced-integrations/issues/659)) ([c237e3c](https://github.com/ReVanced/revanced-integrations/commit/c237e3c02c971fb1801663cb662096d319c04928)) + ## [1.11.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.0...v1.11.1-dev.1) (2024-06-23) diff --git a/gradle.properties b/gradle.properties index 1489fb3a53..74a56b1ecf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.11.1-dev.1 +version = 1.11.1-dev.2 From 77533cf3d68b9c748e1d4f3a85cd0544afc7ce48 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 5 Jul 2024 21:38:33 +0400 Subject: [PATCH 5/9] fix(YouTube - Settings): Move some settings to different menus, adjust default setting values (#661) --- .../patches/components/LayoutComponentsFilter.java | 6 ------ .../components/PlayerFlyoutMenuItemsFilter.java | 13 +++++++++++-- .../integrations/youtube/settings/Settings.java | 13 +++++++------ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java index 69908576f8..b9d581a945 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java @@ -164,11 +164,6 @@ public LayoutComponentsFilter() { "inline_expander" ); - final var videoQualityMenuFooter = new StringFilterGroup( - Settings.HIDE_VIDEO_QUALITY_MENU_FOOTER, - "quality_sheet_footer" - ); - final var channelBar = new StringFilterGroup( Settings.HIDE_CHANNEL_BAR, "channel_bar" @@ -276,7 +271,6 @@ public LayoutComponentsFilter() { compactBanner, compactChannelBarInner, medicalPanel, - videoQualityMenuFooter, infoPanel, emergencyBox, subscribersCommunityGuidelines, diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java index 1a3d350a0d..cdc692c327 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java @@ -14,6 +14,7 @@ public class PlayerFlyoutMenuItemsFilter extends Filter { private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList(); private final ByteArrayFilterGroup exception; + private final StringFilterGroup videoQualityMenuFooter; @RequiresApi(api = Build.VERSION_CODES.N) public PlayerFlyoutMenuItemsFilter() { @@ -23,8 +24,13 @@ public PlayerFlyoutMenuItemsFilter() { "quality_sheet" ); - // Using pathFilterGroupList due to new flyout panel(A/B) + videoQualityMenuFooter = new StringFilterGroup( + Settings.HIDE_VIDEO_QUALITY_MENU_FOOTER, + "quality_sheet_footer" + ); + addPathCallbacks( + videoQualityMenuFooter, new StringFilterGroup(null, "overflow_menu_item.eml|") ); @@ -75,7 +81,10 @@ public PlayerFlyoutMenuItemsFilter() { @Override boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { - // Only 1 path callback was added, so the matched group must be the overflow menu. + if (matchedGroup == videoQualityMenuFooter) { + return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); + } + if (contentIndex != 0) { return false; // Overflow menu is always the start of the path. } 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 ce88954fea..ddf5532897 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 @@ -26,11 +26,10 @@ public class Settings extends BaseSettings { // Video public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE); - public static final BooleanSetting HIDE_VIDEO_QUALITY_MENU_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", TRUE); - public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", TRUE); + public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE); public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2); public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2); - public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", TRUE); + public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE); public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", 1.0f); public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds", "0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true); @@ -55,6 +54,7 @@ public class Settings extends BaseSettings { // Feed public static final BooleanSetting HIDE_ALBUM_CARDS = new BooleanSetting("revanced_hide_album_cards", FALSE, true); public static final BooleanSetting HIDE_ARTIST_CARDS = new BooleanSetting("revanced_hide_artist_cards", FALSE); + public static final BooleanSetting HIDE_EXPANDABLE_CHIP = new BooleanSetting("revanced_hide_expandable_chip", TRUE); // Alternative thumbnails public static final EnumSetting ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL); @@ -89,8 +89,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true); @Deprecated public static final BooleanSetting HIDE_EMAIL_ADDRESS = new BooleanSetting("revanced_hide_email_address", FALSE); public static final BooleanSetting HIDE_EMERGENCY_BOX = new BooleanSetting("revanced_hide_emergency_box", TRUE); - public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", TRUE); - public static final BooleanSetting HIDE_EXPANDABLE_CHIP = new BooleanSetting("revanced_hide_expandable_chip", TRUE); + public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", FALSE); public static final BooleanSetting HIDE_FEED_SURVEY = new BooleanSetting("revanced_hide_feed_survey", TRUE); public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true); public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS = new BooleanSetting("revanced_hide_filter_bar_feed_in_related_videos", FALSE, true); @@ -101,7 +100,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_HIDE_CHANNEL_GUIDELINES = new BooleanSetting("revanced_hide_channel_guidelines", TRUE); public static final BooleanSetting HIDE_HIDE_INFO_PANELS = new BooleanSetting("revanced_hide_info_panels", 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", FALSE); public static final BooleanSetting HIDE_JOIN_MEMBERSHIP_BUTTON = new BooleanSetting("revanced_hide_join_membership_button", TRUE); @Deprecated public static final BooleanSetting HIDE_LOAD_MORE_BUTTON = new BooleanSetting("revanced_hide_load_more_button", TRUE); public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true); @@ -182,6 +181,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_LOCK_SCREEN_MENU = new BooleanSetting("revanced_hide_player_flyout_lock_screen", FALSE); public static final BooleanSetting HIDE_AUDIO_TRACK_MENU = new BooleanSetting("revanced_hide_player_flyout_audio_track", FALSE); public static final BooleanSetting HIDE_WATCH_IN_VR_MENU = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE); + public static final BooleanSetting HIDE_VIDEO_QUALITY_MENU_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE); // General layout public static final StringSetting START_PAGE = new StringSetting("revanced_start_page", ""); @@ -215,6 +215,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE); 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); + // Save sound to playlist and Search suggestions may have been A/B tests that were abandoned by YT, and it's not clear if these are still used. 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_SUPER_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_super_thanks_button", TRUE); From ff2637cb4c9c396f626cd7ee912953b22525baef Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 5 Jul 2024 21:40:52 +0400 Subject: [PATCH 6/9] fix(YouTube - Hide ads): Hide new types of home feed button ads (#662) --- .../integrations/youtube/patches/components/AdsFilter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java index e7559b6565..d3f63a2ff5 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java @@ -56,10 +56,11 @@ public AdsFilter() { final var buttonedAd = new StringFilterGroup( Settings.HIDE_BUTTONED_ADS, + "_ad_with", "_buttoned_layout", + // text_image_button_group_layout, landscape_image_button_group_layout, full_width_square_image_button_group_layout + "image_button_group_layout", "full_width_square_image_layout", - "_ad_with", - "text_image_button_group_layout", "video_display_button_group_layout", "landscape_image_wide_button_layout", "video_display_carousel_button_group_layout" From 7aec04647a28261e323d6f13fcad7aebd14af66d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 5 Jul 2024 17:44:15 +0000 Subject: [PATCH 7/9] chore(release): 1.11.1-dev.3 [skip ci] ## [1.11.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.2...v1.11.1-dev.3) (2024-07-05) ### Bug Fixes * **YouTube - Hide ads:** Hide new types of home feed button ads ([#662](https://github.com/ReVanced/revanced-integrations/issues/662)) ([ff2637c](https://github.com/ReVanced/revanced-integrations/commit/ff2637cb4c9c396f626cd7ee912953b22525baef)) * **YouTube - Settings:** Move some settings to different menus, adjust default setting values ([#661](https://github.com/ReVanced/revanced-integrations/issues/661)) ([77533cf](https://github.com/ReVanced/revanced-integrations/commit/77533cf3d68b9c748e1d4f3a85cd0544afc7ce48)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1382d2001b..36ad5bfbe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.11.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.2...v1.11.1-dev.3) (2024-07-05) + + +### Bug Fixes + +* **YouTube - Hide ads:** Hide new types of home feed button ads ([#662](https://github.com/ReVanced/revanced-integrations/issues/662)) ([ff2637c](https://github.com/ReVanced/revanced-integrations/commit/ff2637cb4c9c396f626cd7ee912953b22525baef)) +* **YouTube - Settings:** Move some settings to different menus, adjust default setting values ([#661](https://github.com/ReVanced/revanced-integrations/issues/661)) ([77533cf](https://github.com/ReVanced/revanced-integrations/commit/77533cf3d68b9c748e1d4f3a85cd0544afc7ce48)) + ## [1.11.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.1...v1.11.1-dev.2) (2024-06-30) diff --git a/gradle.properties b/gradle.properties index 74a56b1ecf..f116c25eb4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.11.1-dev.2 +version = 1.11.1-dev.3 From 5ce16eedc6e27560b97ab982408ac697146105e9 Mon Sep 17 00:00:00 2001 From: Sami Alaoui <4ndroidgeek@gmail.com> Date: Wed, 10 Jul 2024 23:11:55 +0100 Subject: [PATCH 8/9] fix(YouTube - SponsorBlock): Skip segments when casting (#655) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: oSumAtrIX Co-authored-by: Hoàng Gia Bảo <70064328+YT-Advanced@users.noreply.github.com> Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> fix(YouTube - SponsorBlock): Skip segments when casting #655 --- .../youtube/patches/VideoInformation.java | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java b/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java index 695af32693..21aafa6672 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/VideoInformation.java @@ -23,7 +23,9 @@ public final class VideoInformation { private static final String SHORTS_PLAYER_PARAMETERS = "8AEB"; private static WeakReference playerControllerRef; + private static WeakReference mdxPlayerDirectorRef; private static Method seekMethod; + private static Method mdxSeekMethod; @NonNull private static String videoId = ""; @@ -59,6 +61,22 @@ public static void initialize(@NonNull Object playerController) { } } + /** + * Injection point. + * + * @param mdxPlayerDirector MDX player director object (casting mode). + */ + public static void initializeMdx(@NonNull Object mdxPlayerDirector) { + try { + mdxPlayerDirectorRef = new WeakReference<>(Objects.requireNonNull(mdxPlayerDirector)); + + mdxSeekMethod = mdxPlayerDirector.getClass().getMethod(SEEK_METHOD_NAME, Long.TYPE); + mdxSeekMethod.setAccessible(true); + } catch (Exception ex) { + Logger.printException(() -> "Failed to initialize MDX", ex); + } + } + /** * Injection point. * @@ -178,8 +196,32 @@ public static boolean seekTo(final long seekTime) { } Logger.printDebug(() -> "Seeking to " + adjustedSeekTime); - //noinspection DataFlowIssue - return (Boolean) seekMethod.invoke(playerControllerRef.get(), adjustedSeekTime); + + try { + //noinspection DataFlowIssue + if ((Boolean) seekMethod.invoke(playerControllerRef.get(), adjustedSeekTime)) { + return true; + } // Else the video is loading or changing videos, or video is casting to a different device. + } catch (Exception ex) { + Logger.printInfo(() -> "seekTo method call failed", ex); + } + + // Try calling the seekTo method of the MDX player director (called when casting). + // The difference has to be a different second mark in order to avoid infinite skip loops + // as the Lounge API only supports seconds. + if ((adjustedSeekTime / 1000) == (videoTime / 1000)) { + Logger.printDebug(() -> "Skipping seekTo for MDX because seek time is too small (" + + (adjustedSeekTime - videoTime) + "ms)"); + return false; + } + try { + //noinspection DataFlowIssue + return (Boolean) mdxSeekMethod.invoke(mdxPlayerDirectorRef.get(), adjustedSeekTime); + } catch (Exception ex) { + Logger.printInfo(() -> "seekTo (MDX) method call failed", ex); + return false; + } + } catch (Exception ex) { Logger.printException(() -> "Failed to seek", ex); return false; From 6fef1b28a4284e318fd542dc0a09c822122ac7c0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Jul 2024 22:14:58 +0000 Subject: [PATCH 9/9] chore(release): 1.11.1-dev.4 [skip ci] ## [1.11.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.3...v1.11.1-dev.4) (2024-07-10) ### Bug Fixes * **YouTube - SponsorBlock:** Skip segments when casting ([#655](https://github.com/ReVanced/revanced-integrations/issues/655)) ([5ce16ee](https://github.com/ReVanced/revanced-integrations/commit/5ce16eedc6e27560b97ab982408ac697146105e9)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36ad5bfbe1..92ea265838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.11.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.3...v1.11.1-dev.4) (2024-07-10) + + +### Bug Fixes + +* **YouTube - SponsorBlock:** Skip segments when casting ([#655](https://github.com/ReVanced/revanced-integrations/issues/655)) ([5ce16ee](https://github.com/ReVanced/revanced-integrations/commit/5ce16eedc6e27560b97ab982408ac697146105e9)) + ## [1.11.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.2...v1.11.1-dev.3) (2024-07-05) diff --git a/gradle.properties b/gradle.properties index f116c25eb4..4c19a73852 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.11.1-dev.3 +version = 1.11.1-dev.4