From 38ae5aac845745824218a08053db519a3325d7a9 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:11:07 +0400 Subject: [PATCH 01/51] fix(YouTube - Disable suggested video end screen): Require app restart --- .../app/revanced/integrations/youtube/settings/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6d2b7224..1297d965 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 @@ -71,7 +71,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting DISABLE_FULLSCREEN_AMBIENT_MODE = new BooleanSetting("revanced_disable_fullscreen_ambient_mode", TRUE, true); public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE); public static final BooleanSetting DISABLE_ROLLING_NUMBER_ANIMATIONS = new BooleanSetting("revanced_disable_rolling_number_animations", FALSE); - public static final BooleanSetting DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE); + public static final BooleanSetting DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE, true); public static final BooleanSetting GRADIENT_LOADING_SCREEN = new BooleanSetting("revanced_gradient_loading_screen", FALSE); 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); From eaa2e1139c3765ffddc34f99ccc172359a5902fb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 1 Apr 2024 13:14:01 +0000 Subject: [PATCH 02/51] chore(release): 1.7.1-dev.1 [skip ci] ## [1.7.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.7.0...v1.7.1-dev.1) (2024-04-01) ### Bug Fixes * **YouTube - Disable suggested video end screen:** Require app restart ([38ae5aa](https://github.com/ReVanced/revanced-integrations/commit/38ae5aac845745824218a08053db519a3325d7a9)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d975944..aaa23f4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.7.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.7.0...v1.7.1-dev.1) (2024-04-01) + + +### Bug Fixes + +* **YouTube - Disable suggested video end screen:** Require app restart ([38ae5aa](https://github.com/ReVanced/revanced-integrations/commit/38ae5aac845745824218a08053db519a3325d7a9)) + # [1.7.0](https://github.com/ReVanced/revanced-integrations/compare/v1.6.0...v1.7.0) (2024-03-30) diff --git a/gradle.properties b/gradle.properties index ba78657a..bebd6a9b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.7.0 +version = 1.7.1-dev.1 From cbccb46e639003adbed941f9b88c41b4c9998729 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:21:51 +0400 Subject: [PATCH 03/51] fix(YouTube - Navigation bar hook): Handle if search is active but hidden behind a maximized player --- .../patches/AlternativeThumbnailsPatch.java | 8 +++--- .../components/KeywordContentFilter.java | 25 +++++++++++-------- .../patches/components/ShortsFilter.java | 17 +++++++++---- .../youtube/shared/NavigationBar.java | 7 +++--- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java index 1e0d2e1e..888649f6 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java @@ -163,12 +163,14 @@ public final class AlternativeThumbnailsPatch { } private static EnumSetting optionSettingForCurrentNavigation() { - if (NavigationBar.isSearchBarActive()) { // Must check search first. - return ALT_THUMBNAIL_SEARCH; - } + // Must check player type first, as search bar can be active behind the player. if (PlayerType.getCurrent().isMaximizedOrFullscreen()) { return ALT_THUMBNAIL_PLAYER; } + // Must check second, as search can be from any tab. + if (NavigationBar.isSearchBarActive()) { + return ALT_THUMBNAIL_SEARCH; + } if (NavigationButton.HOME.isSelected()) { return ALT_THUMBNAIL_HOME; } 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 7858bb74..ed6e63f0 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 @@ -122,24 +122,27 @@ final class KeywordContentFilter extends Filter { } 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()) { + // 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. logNavigationState("Player active"); return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); - } else if (NavigationButton.HOME.isSelected()) { + } + // Must check second, as search can be from any tab. + if (NavigationBar.isSearchBarActive()) { + logNavigationState("Search"); + return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get(); + } + if (NavigationButton.HOME.isSelected()) { logNavigationState("Home tab"); return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); - } else if (NavigationButton.SUBSCRIPTIONS.isSelected()) { + } + 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"); } + // User is in the Library or Notifications tab. + logNavigationState("Ignored tab"); return false; } @@ -195,6 +198,7 @@ final class KeywordContentFilter extends Filter { private synchronized void parseKeywords() { // Must be synchronized since Litho is multi-threaded. String rawKeywords = Settings.HIDE_KEYWORD_CONTENT_PHRASES.get(); + //noinspection StringEquality if (rawKeywords == lastKeywordPhrasesParsed) { Logger.printDebug(() -> "Using previously initialized search"); return; // Another thread won the race, and search is already initialized. @@ -265,6 +269,7 @@ final class KeywordContentFilter extends Filter { if (!hideKeywordSettingIsActive()) return false; // Field is intentionally compared using reference equality. + //noinspection StringEquality if (Settings.HIDE_KEYWORD_CONTENT_PHRASES.get() != lastKeywordPhrasesParsed) { // User changed the keywords. parseKeywords(); 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 8c3dbf26..5b32d7a1 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 @@ -219,12 +219,19 @@ public final class ShortsFilter extends Filter { } 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()) { + // 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_SHORTS_HOME.get(); - } else if (NavigationBar.NavigationButton.SUBSCRIPTIONS.isSelected()) { + } + // Must check second, as search can be from any tab. + if (NavigationBar.isSearchBarActive()) { + return Settings.HIDE_SHORTS_SEARCH.get(); + } + if (NavigationBar.NavigationButton.HOME.isSelected()) { + return Settings.HIDE_SHORTS_HOME.get(); + } + if (NavigationBar.NavigationButton.SUBSCRIPTIONS.isSelected()) { return Settings.HIDE_SHORTS_SUBSCRIPTIONS.get(); } return false; diff --git a/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java b/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java index 4cec2680..2655a60d 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java +++ b/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java @@ -27,14 +27,15 @@ public final class NavigationBar { } /** - * @return If the search bar is on screen. + * @return If the search bar is on screen. This includes if the player + * is on screen and the search results are behind the player (and not visible). + * Detecting the search is covered by the player can be done by checking {@link PlayerType#isMaximizedOrFullscreen()}. */ public static boolean isSearchBarActive() { View searchbarResults = searchBarResultsRef.get(); return searchbarResults != null && searchbarResults.getParent() != null; } - /** * Last YT navigation enum loaded. Not necessarily the active navigation tab. */ @@ -44,7 +45,7 @@ public final class NavigationBar { /** * Injection point. */ - public static void setLastAppNavigationEnum(@Nullable Enum ytNavigationEnumName) { + public static void setLastAppNavigationEnum(@Nullable Enum ytNavigationEnumName) { if (ytNavigationEnumName != null) { lastYTNavigationEnumName = ytNavigationEnumName.name(); } From 20162f977b4933cd0c0c072d77169b904fd22474 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 3 Apr 2024 20:25:32 +0000 Subject: [PATCH 04/51] chore(release): 1.7.1-dev.2 [skip ci] ## [1.7.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.1...v1.7.1-dev.2) (2024-04-03) ### Bug Fixes * **YouTube - Navigation bar hook:** Handle if search is active but hidden behind a maximized player ([cbccb46](https://github.com/ReVanced/revanced-integrations/commit/cbccb46e639003adbed941f9b88c41b4c9998729)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaa23f4f..ad63b701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.7.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.1...v1.7.1-dev.2) (2024-04-03) + + +### Bug Fixes + +* **YouTube - Navigation bar hook:** Handle if search is active but hidden behind a maximized player ([cbccb46](https://github.com/ReVanced/revanced-integrations/commit/cbccb46e639003adbed941f9b88c41b4c9998729)) + ## [1.7.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.7.0...v1.7.1-dev.1) (2024-04-01) diff --git a/gradle.properties b/gradle.properties index bebd6a9b..8a401f01 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.7.1-dev.1 +version = 1.7.1-dev.2 From b2fe105199d4a5958676cbc8f9c701541e8ff24a Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 4 Apr 2024 10:46:54 +0400 Subject: [PATCH 05/51] fix(YouTube - Player flyout menu): Add hide Lock screen menu (#609) --- .../PlayerFlyoutMenuItemsFilter.java | 20 ++++++++++++++----- .../youtube/settings/Settings.java | 3 ++- 2 files changed, 17 insertions(+), 6 deletions(-) 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 19ccfac5..7099bf2f 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 @@ -57,6 +57,10 @@ public class PlayerFlyoutMenuItemsFilter extends Filter { Settings.HIDE_MORE_INFO_MENU, "yt_outline_info_circle" ), + new ByteArrayFilterGroup( + Settings.HIDE_LOCK_SCREEN_MENU, + "yt_outline_lock" + ), new ByteArrayFilterGroup( Settings.HIDE_SPEED_MENU, "yt_outline_play_arrow_half_circle" @@ -75,15 +79,21 @@ public class PlayerFlyoutMenuItemsFilter extends Filter { @Override boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { - // Shorts also use this player flyout panel - if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(protobufBufferArray).isFiltered()) - return false; - // Only 1 path callback was added, so the matched group must be the overflow menu. - if (contentIndex == 0 && flyoutFilterGroupList.check(protobufBufferArray).isFiltered()) { + if (contentIndex != 0) { + return false; // Overflow menu is always the start of the path. + } + + // Shorts also use this player flyout panel + if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(protobufBufferArray).isFiltered()) { + return false; + } + + if (flyoutFilterGroupList.check(protobufBufferArray).isFiltered()) { // Super class handles logging. return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } + return false; } } 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 1297d965..75b03d51 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 @@ -198,6 +198,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_HELP_MENU = new BooleanSetting("revanced_hide_player_flyout_help", TRUE); public static final BooleanSetting HIDE_SPEED_MENU = new BooleanSetting("revanced_hide_player_flyout_speed", FALSE); public static final BooleanSetting HIDE_MORE_INFO_MENU = new BooleanSetting("revanced_hide_player_flyout_more_info", TRUE); + 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); @@ -218,7 +219,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true); public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE); public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE); - @Deprecated + @Deprecated public static final StringSetting DEPRECATED_ANNOUNCEMENT_LAST_HASH = new StringSetting("revanced_announcement_last_hash", ""); public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1); public static final BooleanSetting REMOVE_TRACKING_QUERY_PARAMETER = new BooleanSetting("revanced_remove_tracking_query_parameter", TRUE); From 33da670984a7cde7e71818b1e8177f59d886cab2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 4 Apr 2024 06:49:49 +0000 Subject: [PATCH 06/51] chore(release): 1.7.1-dev.3 [skip ci] ## [1.7.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.2...v1.7.1-dev.3) (2024-04-04) ### Bug Fixes * **YouTube - Player flyout menu:** Add hide Lock screen menu ([#609](https://github.com/ReVanced/revanced-integrations/issues/609)) ([b2fe105](https://github.com/ReVanced/revanced-integrations/commit/b2fe105199d4a5958676cbc8f9c701541e8ff24a)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad63b701..f3e55392 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.7.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.2...v1.7.1-dev.3) (2024-04-04) + + +### Bug Fixes + +* **YouTube - Player flyout menu:** Add hide Lock screen menu ([#609](https://github.com/ReVanced/revanced-integrations/issues/609)) ([b2fe105](https://github.com/ReVanced/revanced-integrations/commit/b2fe105199d4a5958676cbc8f9c701541e8ff24a)) + ## [1.7.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.1...v1.7.1-dev.2) (2024-04-03) diff --git a/gradle.properties b/gradle.properties index 8a401f01..8d4a708c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.7.1-dev.2 +version = 1.7.1-dev.3 From c420891e3ef134f30af79cf2f30da3fa2fe5a455 Mon Sep 17 00:00:00 2001 From: nullptr <107796137+johnconner122@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:09:42 +0300 Subject: [PATCH 07/51] fix(YouTube - Hide load more button): Include patch with `Hide layout components`, and hide button only in search feed (#600) --- .../patches/HideLoadMoreButtonPatch.java | 14 ------------- .../components/LayoutComponentsFilter.java | 21 +++++++++++++++++++ .../youtube/settings/Settings.java | 5 ++++- 3 files changed, 25 insertions(+), 15 deletions(-) delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch.java diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch.java deleted file mode 100644 index fa3a0e70..00000000 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch.java +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.integrations.youtube.patches; - -import android.view.View; - -import app.revanced.integrations.youtube.settings.Settings; -import app.revanced.integrations.shared.Utils; - -@SuppressWarnings("unused") -public class HideLoadMoreButtonPatch { - public static void hideLoadMoreButton(View view){ - if(!Settings.HIDE_LOAD_MORE_BUTTON.get()) return; - Utils.hideViewByLayoutParams(view); - } -} 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 f32ad545..8c52c2d8 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 @@ -1,13 +1,17 @@ package app.revanced.integrations.youtube.patches.components; import android.os.Build; +import android.view.View; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import app.revanced.integrations.shared.Utils; import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.shared.Logger; import app.revanced.integrations.youtube.StringTrieSearch; +import app.revanced.integrations.youtube.shared.NavigationBar; +import app.revanced.integrations.youtube.shared.PlayerType; @SuppressWarnings("unused") public final class LayoutComponentsFilter extends Filter { @@ -322,7 +326,24 @@ public final class LayoutComponentsFilter extends Filter { return true; } + /** + * Injection point. + */ public static boolean showWatermark() { return !Settings.HIDE_VIDEO_CHANNEL_WATERMARK.get(); } + + private static final boolean HIDE_SHOW_MORE_BUTTON_ENABLED = Settings.HIDE_SHOW_MORE_BUTTON.get(); + + /** + * Injection point. + */ + public static void hideShowMoreButton(View view) { + if (HIDE_SHOW_MORE_BUTTON_ENABLED + && NavigationBar.isSearchBarActive() + // Search bar can be active but behind the player. + && !PlayerType.getCurrent().isMaximizedOrFullscreen()) { + Utils.hideViewByLayoutParams(view); + } + } } 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 75b03d51..714306f4 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 @@ -108,7 +108,8 @@ public class Settings extends BaseSettings { 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_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); + @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); 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_MOVIES_SECTION = new BooleanSetting("revanced_hide_movies_section", TRUE); @@ -384,6 +385,8 @@ public class Settings extends BaseSettings { HIDE_SHORTS_SEARCH.save(true); } + migrateOldSettingToNew(HIDE_LOAD_MORE_BUTTON, HIDE_SHOW_MORE_BUTTON); + // endregion } } From bddcc97392428cccd9569e4e5db07d7be00857c9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 4 Apr 2024 21:12:44 +0000 Subject: [PATCH 08/51] chore(release): 1.7.1-dev.4 [skip ci] ## [1.7.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.3...v1.7.1-dev.4) (2024-04-04) ### Bug Fixes * **YouTube - Hide load more button:** Include patch with `Hide layout components`, and hide button only in search feed ([#600](https://github.com/ReVanced/revanced-integrations/issues/600)) ([c420891](https://github.com/ReVanced/revanced-integrations/commit/c420891e3ef134f30af79cf2f30da3fa2fe5a455)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3e55392..7f096479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.7.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.3...v1.7.1-dev.4) (2024-04-04) + + +### Bug Fixes + +* **YouTube - Hide load more button:** Include patch with `Hide layout components`, and hide button only in search feed ([#600](https://github.com/ReVanced/revanced-integrations/issues/600)) ([c420891](https://github.com/ReVanced/revanced-integrations/commit/c420891e3ef134f30af79cf2f30da3fa2fe5a455)) + ## [1.7.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.2...v1.7.1-dev.3) (2024-04-04) diff --git a/gradle.properties b/gradle.properties index 8d4a708c..1c3ea08a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.7.1-dev.3 +version = 1.7.1-dev.4 From fedace02fd5c443ef37dcf77253438b041f4c3f9 Mon Sep 17 00:00:00 2001 From: nullptr <107796137+johnconner122@users.noreply.github.com> Date: Sat, 6 Apr 2024 21:41:50 +0300 Subject: [PATCH 09/51] feat(YouTube - Hide layout components): Add option to hide horizontal shelves (#598) Co-authored-by: oSumAtrIX Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> --- .../patches/HideBreakingNewsPatch.java | 29 ------------------- .../components/LayoutComponentsFilter.java | 28 ++++++++++++++++-- .../youtube/settings/Settings.java | 3 +- 3 files changed, 28 insertions(+), 32 deletions(-) delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java deleted file mode 100644 index bd6d89fa..00000000 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.integrations.youtube.patches; - -import android.view.View; - -import app.revanced.integrations.youtube.patches.spoof.SpoofAppVersionPatch; -import app.revanced.integrations.youtube.settings.Settings; -import app.revanced.integrations.shared.Utils; - -@SuppressWarnings("unused") -public class HideBreakingNewsPatch { - - /** - * When spoofing to app versions 17.31.00 and older, the watch history preview bar uses - * the same layout components as the breaking news shelf. - * - * Breaking news does not appear to be present in these older versions anyways. - */ - private static final boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory = - SpoofAppVersionPatch.isSpoofingToLessThan("18.01.00"); - - /** - * Injection point. - */ - public static void hideBreakingNews(View view) { - if (!Settings.HIDE_BREAKING_NEWS.get() - || isSpoofingOldVersionWithHorizontalCardListWatchHistory) return; - Utils.hideViewByLayoutParams(view); - } -} 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 8c52c2d8..a22ff004 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 @@ -35,6 +35,7 @@ public final class LayoutComponentsFilter extends Filter { private final StringFilterGroup compactChannelBarInner; private final StringFilterGroup compactChannelBarInnerButton; private final ByteArrayFilterGroup joinMembershipButton; + private final StringFilterGroup horizontalShelves; static { mixPlaylistsExceptions.addPatterns( @@ -43,7 +44,6 @@ public final class LayoutComponentsFilter extends Filter { ); } - @RequiresApi(api = Build.VERSION_CODES.N) public LayoutComponentsFilter() { exceptions.addPatterns( @@ -237,6 +237,12 @@ public final class LayoutComponentsFilter extends Filter { "endorsement_header_footer" ); + horizontalShelves = new StringFilterGroup( + Settings.HIDE_HORIZONTAL_SHELVES, + "horizontal_video_shelf.eml", + "horizontal_shelf.eml" + ); + addPathCallbacks( expandableMetadata, inFeedSurvey, @@ -263,7 +269,8 @@ public final class LayoutComponentsFilter extends Filter { timedReactions, imageShelf, channelMemberShelf, - forYouShelf + forYouShelf, + horizontalShelves ); } @@ -279,7 +286,9 @@ public final class LayoutComponentsFilter extends Filter { // The groups are excluded from the filter due to the exceptions list below. // Filter them separately here. if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata) + { return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); + } if (exceptions.matches(path)) return false; // Exceptions are not filtered. @@ -298,6 +307,10 @@ public final class LayoutComponentsFilter extends Filter { // TODO: This also hides the feed Shorts shelf header if (matchedGroup == searchResultShelfHeader && contentIndex != 0) return false; + if (contentIndex == 0 && matchedGroup == horizontalShelves && hideShelves()) { + return super.isFiltered(path, identifier, protobufBufferArray, matchedGroup, contentType, contentIndex); + } + return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } @@ -346,4 +359,15 @@ public final class LayoutComponentsFilter extends Filter { Utils.hideViewByLayoutParams(view); } } + + private static boolean hideShelves() { + // Only filter if the library tab is not selected. + // This check is important as the shelf layout is used for the library tab playlists. + return !NavigationBar.NavigationButton.libraryOrYouTabIsSelected() + // But if the player is opened while library is selected, + // then still filter any recommendations below the player. + || PlayerType.getCurrent().isMaximizedOrFullscreen() + // Or if the search is active while library is selected, then also filter. + || NavigationBar.isSearchBarActive(); + } } 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 714306f4..e8261ff3 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 @@ -55,6 +55,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_SELF_SPONSOR = new BooleanSetting("revanced_hide_self_sponsor_ads", TRUE); public static final BooleanSetting HIDE_VIDEO_ADS = new BooleanSetting("revanced_hide_video_ads", TRUE, true); public static final BooleanSetting HIDE_WEB_SEARCH_RESULTS = new BooleanSetting("revanced_hide_web_search_results", TRUE); + // Layout public static final EnumSetting ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL); public static final EnumSetting ALT_THUMBNAIL_SUBSCRIPTIONS = new EnumSetting<>("revanced_alt_thumbnail_subscription", ThumbnailOption.ORIGINAL); @@ -76,7 +77,7 @@ public class Settings extends BaseSettings { 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_AUTOPLAY_BUTTON = new BooleanSetting("revanced_hide_autoplay_button", TRUE, true); - public static final BooleanSetting HIDE_BREAKING_NEWS = new BooleanSetting("revanced_hide_breaking_news", TRUE, true); + public static final BooleanSetting HIDE_HORIZONTAL_SHELVES = new BooleanSetting("revanced_hide_horizontal_shelves", TRUE); public static final BooleanSetting HIDE_CAPTIONS_BUTTON = new BooleanSetting("revanced_hide_captions_button", FALSE); public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_hide_cast_button", TRUE, true); public static final BooleanSetting HIDE_CHANNEL_BAR = new BooleanSetting("revanced_hide_channel_bar", FALSE); From c5c9de500d8f1268799e55c31c446bfe8336f79a Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 6 Apr 2024 22:46:07 +0400 Subject: [PATCH 10/51] fix(YouTube - GmsCore support): Prompt to disable battery optimizations, if not done already (#601) Co-authored-by: oSumAtrIX --- .../integrations/shared/GmsCoreSupport.java | 81 +++++++++++-------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java b/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java index bab1a994..e6874205 100644 --- a/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java +++ b/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java @@ -1,21 +1,25 @@ package app.revanced.integrations.shared; +import static app.revanced.integrations.shared.StringRef.str; + +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.SearchManager; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.PowerManager; +import android.provider.Settings; + import androidx.annotation.RequiresApi; import java.net.MalformedURLException; import java.net.URL; -import static app.revanced.integrations.shared.StringRef.str; - /** * @noinspection unused */ @@ -45,27 +49,19 @@ public class GmsCoreSupport { System.exit(0); } - private static void showToastOrDialog(Context context, String toastMessageKey, String dialogMessageKey, String link) { - if (!(context instanceof Activity)) { - // Context is for the application and cannot show a dialog using it. - Utils.showToastLong(str(toastMessageKey)); - open(link); - return; - } - + private static void showBatteryOptimizationDialog(Activity context, + String dialogMessageRef, + String positiveButtonStringRef, + DialogInterface.OnClickListener onPositiveClickListener) { // Use a delay to allow the activity to finish initializing. // Otherwise, if device is in dark mode the dialog is shown with wrong color scheme. Utils.runOnMainThreadDelayed(() -> { new AlertDialog.Builder(context) .setIconAttribute(android.R.attr.alertDialogIcon) .setTitle(str("gms_core_dialog_title")) - .setMessage(str(dialogMessageKey)) - .setPositiveButton(str("gms_core_dialog_ok_button_text"), (dialog, id) -> { - open(link); - }) - // Manually allow using the back button to dismiss the dialog with the back button, - // if troubleshooting and somehow the GmsCore verification checks always fail. - .setCancelable(true) + .setMessage(str(dialogMessageRef)) + .setPositiveButton(str(positiveButtonStringRef), onPositiveClickListener) + .setCancelable(false) .show(); }, 100); } @@ -74,47 +70,62 @@ public class GmsCoreSupport { * Injection point. */ @RequiresApi(api = Build.VERSION_CODES.N) - public static void checkGmsCore(Context context) { + public static void checkGmsCore(Activity context) { try { // Verify GmsCore is installed. try { PackageManager manager = context.getPackageManager(); manager.getPackageInfo(GMS_CORE_PACKAGE_NAME, PackageManager.GET_ACTIVITIES); } catch (PackageManager.NameNotFoundException exception) { - Logger.printDebug(() -> "GmsCore was not found"); + Logger.printInfo(() -> "GmsCore was not found"); // Cannot show a dialog and must show a toast, - // because on some installations the app crashes before the dialog can display. + // because on some installations the app crashes before a dialog can be displayed. Utils.showToastLong(str("gms_core_toast_not_installed_message")); open(getGmsCoreDownload()); return; } - // Check if GmsCore is whitelisted from battery optimizations. - var powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - if (!powerManager.isIgnoringBatteryOptimizations(GMS_CORE_PACKAGE_NAME)) { - Logger.printDebug(() -> "GmsCore is not whitelisted from battery optimizations"); - showToastOrDialog(context, - "gms_core_toast_not_whitelisted_message", - "gms_core_dialog_not_whitelisted_using_battery_optimizations_message", - DONT_KILL_MY_APP_LINK); - return; - } - // Check if GmsCore is running in the background. try (var client = context.getContentResolver().acquireContentProviderClient(GMS_CORE_PROVIDER)) { if (client == null) { - Logger.printDebug(() -> "GmsCore is not running in the background"); - showToastOrDialog(context, - "gms_core_toast_not_whitelisted_message", + Logger.printInfo(() -> "GmsCore is not running in the background"); + + showBatteryOptimizationDialog(context, "gms_core_dialog_not_whitelisted_not_allowed_in_background_message", - DONT_KILL_MY_APP_LINK); + "gms_core_dialog_open_website_text", + (dialog, id) -> open(DONT_KILL_MY_APP_LINK)); + return; } } + + // Check if GmsCore is whitelisted from battery optimizations. + if (batteryOptimizationsEnabled(context)) { + Logger.printInfo(() -> "GmsCore is not whitelisted from battery optimizations"); + showBatteryOptimizationDialog(context, + "gms_core_dialog_not_whitelisted_using_battery_optimizations_message", + "gms_core_dialog_continue_text", + (dialog, id) -> openGmsCoreDisableBatteryOptimizationsIntent(context)); + } } catch (Exception ex) { Logger.printException(() -> "checkGmsCore failure", ex); } } + @SuppressLint("BatteryLife") // Permission is part of GmsCore + private static void openGmsCoreDisableBatteryOptimizationsIntent(Activity activity) { + Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.fromParts("package", GMS_CORE_PACKAGE_NAME, null)); + activity.startActivityForResult(intent, 0); + } + + /** + * @return If GmsCore is not whitelisted from battery optimizations. + */ + private static boolean batteryOptimizationsEnabled(Context context) { + var powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + return !powerManager.isIgnoringBatteryOptimizations(GMS_CORE_PACKAGE_NAME); + } + private static String getGmsCoreDownload() { final var vendorGroupId = getGmsCoreVendorGroupId(); //noinspection SwitchStatementWithTooFewBranches From 628c25e808542b127a95aff83e834777e8989345 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 6 Apr 2024 18:48:59 +0000 Subject: [PATCH 11/51] chore(release): 1.8.0-dev.1 [skip ci] # [1.8.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.4...v1.8.0-dev.1) (2024-04-06) ### Bug Fixes * **YouTube - GmsCore support:** Prompt to disable battery optimizations, if not done already ([#601](https://github.com/ReVanced/revanced-integrations/issues/601)) ([c5c9de5](https://github.com/ReVanced/revanced-integrations/commit/c5c9de500d8f1268799e55c31c446bfe8336f79a)) ### Features * **YouTube - Hide layout components:** Add option to hide horizontal shelves ([#598](https://github.com/ReVanced/revanced-integrations/issues/598)) ([fedace0](https://github.com/ReVanced/revanced-integrations/commit/fedace02fd5c443ef37dcf77253438b041f4c3f9)) --- CHANGELOG.md | 12 ++++++++++++ gradle.properties | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f096479..5b70a5bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [1.8.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.4...v1.8.0-dev.1) (2024-04-06) + + +### Bug Fixes + +* **YouTube - GmsCore support:** Prompt to disable battery optimizations, if not done already ([#601](https://github.com/ReVanced/revanced-integrations/issues/601)) ([c5c9de5](https://github.com/ReVanced/revanced-integrations/commit/c5c9de500d8f1268799e55c31c446bfe8336f79a)) + + +### Features + +* **YouTube - Hide layout components:** Add option to hide horizontal shelves ([#598](https://github.com/ReVanced/revanced-integrations/issues/598)) ([fedace0](https://github.com/ReVanced/revanced-integrations/commit/fedace02fd5c443ef37dcf77253438b041f4c3f9)) + ## [1.7.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.3...v1.7.1-dev.4) (2024-04-04) diff --git a/gradle.properties b/gradle.properties index 1c3ea08a..a36b92b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.7.1-dev.4 +version = 1.8.0-dev.1 From f6de32884e2debe588f959fd6d7c06e0ecf686bc Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 6 Apr 2024 22:49:49 +0400 Subject: [PATCH 12/51] chore: Add check in missing from merge --- .../java/app/revanced/integrations/shared/GmsCoreSupport.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java b/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java index e6874205..16f0ed0c 100644 --- a/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java +++ b/app/src/main/java/app/revanced/integrations/shared/GmsCoreSupport.java @@ -61,7 +61,8 @@ public class GmsCoreSupport { .setTitle(str("gms_core_dialog_title")) .setMessage(str(dialogMessageRef)) .setPositiveButton(str(positiveButtonStringRef), onPositiveClickListener) - .setCancelable(false) + // Allow using back button to skip the action, just in case the check can never be satisfied. + .setCancelable(true) .show(); }, 100); } From c5d38a7e0791ebb8fe59397fff959cc94e0a7aed Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 7 Apr 2024 20:14:29 +0400 Subject: [PATCH 13/51] fix(YouTube - Hide layout components): Do not hide playlist shelf in library --- .../patches/components/LayoutComponentsFilter.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 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 a22ff004..ea1369a0 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 @@ -281,6 +281,7 @@ public final class LayoutComponentsFilter extends Filter { if (searchResultRecommendations.check(protobufBufferArray).isFiltered()) { return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); } + return false; } // The groups are excluded from the filter due to the exceptions list below. @@ -307,8 +308,12 @@ public final class LayoutComponentsFilter extends Filter { // TODO: This also hides the feed Shorts shelf header if (matchedGroup == searchResultShelfHeader && contentIndex != 0) return false; - if (contentIndex == 0 && matchedGroup == horizontalShelves && hideShelves()) { - return super.isFiltered(path, identifier, protobufBufferArray, matchedGroup, contentType, contentIndex); + if (matchedGroup == horizontalShelves) { + if (contentIndex == 0 && hideShelves()) { + return super.isFiltered(path, identifier, protobufBufferArray, matchedGroup, contentType, contentIndex); + } + + return false; } return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); From c0764e904686e3fbd672385722473a7b626ffb74 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 7 Apr 2024 16:17:56 +0000 Subject: [PATCH 14/51] chore(release): 1.8.0-dev.2 [skip ci] # [1.8.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.1...v1.8.0-dev.2) (2024-04-07) ### Bug Fixes * **YouTube - Hide layout components:** Do not hide playlist shelf in library ([c5d38a7](https://github.com/ReVanced/revanced-integrations/commit/c5d38a7e0791ebb8fe59397fff959cc94e0a7aed)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b70a5bd..9cde3fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.1...v1.8.0-dev.2) (2024-04-07) + + +### Bug Fixes + +* **YouTube - Hide layout components:** Do not hide playlist shelf in library ([c5d38a7](https://github.com/ReVanced/revanced-integrations/commit/c5d38a7e0791ebb8fe59397fff959cc94e0a7aed)) + # [1.8.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.7.1-dev.4...v1.8.0-dev.1) (2024-04-06) diff --git a/gradle.properties b/gradle.properties index a36b92b4..fd267cf9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.1 +version = 1.8.0-dev.2 From eba73c5947716f65d8c12c35f8c1c0040164eaab Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 7 Apr 2024 23:55:33 +0400 Subject: [PATCH 15/51] chore(YouTube): Fix typos, simplify some strings for translating --- .../preference/ReturnYouTubeDislikePreferenceFragment.java | 7 +++---- .../preference/SponsorBlockPreferenceFragment.java | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java index 117c2f99..c4a6c9be 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java @@ -79,10 +79,9 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment { shortsPreference = new SwitchPreference(context); shortsPreference.setChecked(Settings.RYD_SHORTS.get()); shortsPreference.setTitle(str("revanced_ryd_shorts_title")); - String shortsSummary = str("revanced_ryd_shorts_summary_on", - ReturnYouTubeDislikePatch.IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER - ? "" - : "\n\n" + str("revanced_ryd_shorts_summary_disclaimer")); + String shortsSummary = ReturnYouTubeDislikePatch.IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER + ? str("revanced_ryd_shorts_summary_on") + : str("revanced_ryd_shorts_summary_on_disclaimer"); shortsPreference.setSummaryOn(shortsSummary); shortsPreference.setSummaryOff(str("revanced_ryd_shorts_summary_off")); shortsPreference.setOnPreferenceChangeListener((pref, newValue) -> { diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java index 137509d8..371ef389 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java @@ -100,10 +100,10 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment { privateUserId.setEnabled(enabled); // If the user has a private user id, then include a subtext that mentions not to share it. - String exportSummarySubText = SponsorBlockSettings.userHasSBPrivateId() + String importExportSummary = SponsorBlockSettings.userHasSBPrivateId() ? str("revanced_sb_settings_ie_sum_warning") - : ""; - importExport.setSummary(str("revanced_sb_settings_ie_sum", exportSummarySubText)); + : str("revanced_sb_settings_ie_sum"); + importExport.setSummary(importExportSummary); apiUrl.setEnabled(enabled); importExport.setEnabled(enabled); From f2e15a2e1ff59ae7780cfbd366e5165f4e2b191d Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 10 Apr 2024 00:59:23 +0400 Subject: [PATCH 16/51] fix(YouTube - Settings): Do not show a toast if migrating old unknown settings --- .../app/revanced/integrations/shared/settings/Setting.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java b/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java index f5f7b890..499e4d0b 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java @@ -224,6 +224,7 @@ public abstract class Setting { if (!oldPrefs.preferences.contains(settingKey)) { return; // Nothing to do. } + Object newValue = setting.get(); final Object migratedValue; if (setting instanceof BooleanSetting) { @@ -238,13 +239,17 @@ public abstract class Setting { migratedValue = oldPrefs.getString(settingKey, (String) newValue); } else { Logger.printException(() -> "Unknown setting: " + setting); + // Remove otherwise it'll show a toast on every launch + oldPrefs.preferences.edit().remove(settingKey).apply(); return; } + oldPrefs.preferences.edit().remove(settingKey).apply(); // Remove the old setting. if (migratedValue.equals(newValue)) { Logger.printDebug(() -> "Value does not need migrating: " + settingKey); return; // Old value is already equal to the new setting value. } + Logger.printDebug(() -> "Migrating old preference value into current preference: " + settingKey); //noinspection unchecked setting.save(migratedValue); From 4939a22da1142214c2b13bf30fe722245c84688d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 9 Apr 2024 21:02:25 +0000 Subject: [PATCH 17/51] chore(release): 1.8.0-dev.3 [skip ci] # [1.8.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.2...v1.8.0-dev.3) (2024-04-09) ### Bug Fixes * **YouTube - Settings:** Do not show a toast if migrating old unknown settings ([f2e15a2](https://github.com/ReVanced/revanced-integrations/commit/f2e15a2e1ff59ae7780cfbd366e5165f4e2b191d)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cde3fad..92584a6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.2...v1.8.0-dev.3) (2024-04-09) + + +### Bug Fixes + +* **YouTube - Settings:** Do not show a toast if migrating old unknown settings ([f2e15a2](https://github.com/ReVanced/revanced-integrations/commit/f2e15a2e1ff59ae7780cfbd366e5165f4e2b191d)) + # [1.8.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.1...v1.8.0-dev.2) (2024-04-07) diff --git a/gradle.properties b/gradle.properties index fd267cf9..972ee826 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.2 +version = 1.8.0-dev.3 From ffc3437843c24af255d2a0dda9930d2843cac4b6 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:29:23 +0400 Subject: [PATCH 18/51] fix(YouTube - Hide Shorts components): Correctly hide Shorts if navigation tab is changed using device back button (#611) --- .../patches/AlternativeThumbnailsPatch.java | 72 +++--- .../components/KeywordContentFilter.java | 34 ++- .../components/LayoutComponentsFilter.java | 23 +- .../patches/components/ShortsFilter.java | 23 +- .../youtube/shared/NavigationBar.java | 206 +++++++++++++++--- 5 files changed, 255 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java index 888649f6..df7aab9f 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java @@ -1,19 +1,15 @@ package app.revanced.integrations.youtube.patches; +import static app.revanced.integrations.shared.StringRef.str; +import static app.revanced.integrations.youtube.settings.Settings.*; +import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton; + import android.net.Uri; + import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.revanced.integrations.shared.settings.BaseSettings; -import app.revanced.integrations.shared.settings.EnumSetting; -import app.revanced.integrations.shared.settings.Setting; -import app.revanced.integrations.youtube.settings.Settings; -import app.revanced.integrations.shared.Logger; -import app.revanced.integrations.shared.Utils; -import app.revanced.integrations.youtube.shared.NavigationBar; -import app.revanced.integrations.youtube.shared.PlayerType; - import org.chromium.net.UrlRequest; import org.chromium.net.UrlResponseInfo; import org.chromium.net.impl.CronetUrlRequest; @@ -26,13 +22,12 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ExecutionException; -import static app.revanced.integrations.shared.StringRef.str; -import static app.revanced.integrations.youtube.settings.Settings.ALT_THUMBNAIL_HOME; -import static app.revanced.integrations.youtube.settings.Settings.ALT_THUMBNAIL_LIBRARY; -import static app.revanced.integrations.youtube.settings.Settings.ALT_THUMBNAIL_PLAYER; -import static app.revanced.integrations.youtube.settings.Settings.ALT_THUMBNAIL_SEARCH; -import static app.revanced.integrations.youtube.settings.Settings.ALT_THUMBNAIL_SUBSCRIPTIONS; -import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton; +import app.revanced.integrations.shared.Logger; +import app.revanced.integrations.shared.Utils; +import app.revanced.integrations.shared.settings.Setting; +import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.youtube.shared.NavigationBar; +import app.revanced.integrations.youtube.shared.PlayerType; /** * Alternative YouTube thumbnails. @@ -134,11 +129,6 @@ public final class AlternativeThumbnailsPatch { */ private static volatile long timeToResumeDeArrowAPICalls; - /** - * Used only for debug logging. - */ - private static volatile EnumSetting currentOptionSetting; - static { dearrowApiUri = validateSettings(); final int port = dearrowApiUri.getPort(); @@ -162,23 +152,38 @@ public final class AlternativeThumbnailsPatch { return apiUri; } - private static EnumSetting optionSettingForCurrentNavigation() { + private static ThumbnailOption optionSettingForCurrentNavigation() { // Must check player type first, as search bar can be active behind the player. if (PlayerType.getCurrent().isMaximizedOrFullscreen()) { - return ALT_THUMBNAIL_PLAYER; + return ALT_THUMBNAIL_PLAYER.get(); } + // Must check second, as search can be from any tab. if (NavigationBar.isSearchBarActive()) { - return ALT_THUMBNAIL_SEARCH; + return ALT_THUMBNAIL_SEARCH.get(); } - if (NavigationButton.HOME.isSelected()) { - return ALT_THUMBNAIL_HOME; + + // Avoid checking which navigation button is selected, if all other settings are the same. + ThumbnailOption homeOption = ALT_THUMBNAIL_HOME.get(); + ThumbnailOption subscriptionsOption = ALT_THUMBNAIL_SUBSCRIPTIONS.get(); + ThumbnailOption libraryOption = ALT_THUMBNAIL_LIBRARY.get(); + if ((homeOption == subscriptionsOption) && (homeOption == libraryOption)) { + return homeOption; // All are the same option. } - if (NavigationButton.SUBSCRIPTIONS.isSelected() || NavigationButton.NOTIFICATIONS.isSelected()) { - return ALT_THUMBNAIL_SUBSCRIPTIONS; + + NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton(); + if (selectedNavButton == null) { + // Unknown tab, treat as the home tab; + return homeOption; + } + if (selectedNavButton == NavigationButton.HOME) { + return homeOption; + } + if (selectedNavButton == NavigationButton.SUBSCRIPTIONS || selectedNavButton == NavigationButton.NOTIFICATIONS) { + return subscriptionsOption; } // A library tab variant is active. - return ALT_THUMBNAIL_LIBRARY; + return libraryOption; } /** @@ -256,14 +261,7 @@ public final class AlternativeThumbnailsPatch { */ public static String overrideImageURL(String originalUrl) { try { - EnumSetting optionSetting = optionSettingForCurrentNavigation(); - ThumbnailOption option = optionSetting.get(); - if (BaseSettings.DEBUG.get()) { - if (currentOptionSetting != optionSetting) { - currentOptionSetting = optionSetting; - Logger.printDebug(() -> "Changed to setting: " + optionSetting.key); - } - } + ThumbnailOption option = optionSettingForCurrentNavigation(); if (option == ThumbnailOption.ORIGINAL) { return originalUrl; 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 ed6e63f0..95b9f466 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,37 +112,35 @@ 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() { // 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. - logNavigationState("Player active"); return Settings.HIDE_KEYWORD_CONTENT_HOME.get(); } // Must check second, as search can be from any tab. if (NavigationBar.isSearchBarActive()) { - logNavigationState("Search"); return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get(); } - if (NavigationButton.HOME.isSelected()) { - logNavigationState("Home tab"); - return Settings.HIDE_KEYWORD_CONTENT_HOME.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_SUBSCRIPTIONS_BUTTON.get(); + if (!hideHome && !hideSubscriptions) { + return false; } - if (NavigationButton.SUBSCRIPTIONS.isSelected()) { - logNavigationState("Subscription tab"); - return Settings.HIDE_SUBSCRIPTIONS_BUTTON.get(); + + 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. - logNavigationState("Ignored tab"); return false; } 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 ea1369a0..f0e560e4 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 @@ -1,15 +1,17 @@ package app.revanced.integrations.youtube.patches.components; +import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton; + import android.os.Build; import android.view.View; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import app.revanced.integrations.shared.Utils; -import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.shared.Logger; +import app.revanced.integrations.shared.Utils; import app.revanced.integrations.youtube.StringTrieSearch; +import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.youtube.shared.NavigationBar; import app.revanced.integrations.youtube.shared.PlayerType; @@ -366,13 +368,18 @@ public final class LayoutComponentsFilter extends Filter { } private static boolean hideShelves() { + // If the player is opened while library is selected, + // then filter any recommendations below the player. + if (PlayerType.getCurrent().isMaximizedOrFullscreen() + // Or if the search is active while library is selected, then also filter. + || NavigationBar.isSearchBarActive()) { + return true; + } + + // Check navigation button last. // Only filter if the library tab is not selected. // This check is important as the shelf layout is used for the library tab playlists. - return !NavigationBar.NavigationButton.libraryOrYouTabIsSelected() - // But if the player is opened while library is selected, - // then still filter any recommendations below the player. - || PlayerType.getCurrent().isMaximizedOrFullscreen() - // Or if the search is active while library is selected, then also filter. - || NavigationBar.isSearchBarActive(); + NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton(); + return selectedNavButton != null && !selectedNavButton.isLibraryOrYouTab(); } } 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 5b32d7a1..bd5a32d7 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,6 +1,7 @@ package app.revanced.integrations.youtube.patches.components; import static app.revanced.integrations.shared.Utils.hideViewUnderCondition; +import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton; import android.view.View; @@ -224,16 +225,30 @@ public final class ShortsFilter extends Filter { // For now, consider the under video results the same as the home feed. return Settings.HIDE_SHORTS_HOME.get(); } + // Must check second, as search can be from any tab. if (NavigationBar.isSearchBarActive()) { return Settings.HIDE_SHORTS_SEARCH.get(); } - if (NavigationBar.NavigationButton.HOME.isSelected()) { - return Settings.HIDE_SHORTS_HOME.get(); + + // Avoid checking navigation button status if all other settings are off. + final boolean hideHome = Settings.HIDE_SHORTS_HOME.get(); + final boolean hideSubscriptions = Settings.HIDE_SHORTS_SUBSCRIPTIONS.get(); + if (!hideHome && !hideSubscriptions) { + return false; } - if (NavigationBar.NavigationButton.SUBSCRIPTIONS.isSelected()) { - return Settings.HIDE_SHORTS_SUBSCRIPTIONS.get(); + + 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 must be in the library tab. Don't hide the history or any playlists here. return false; } diff --git a/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java b/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java index 2655a60d..58c2ec0b 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java +++ b/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java @@ -2,21 +2,29 @@ package app.revanced.integrations.youtube.shared; import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton.CREATE; +import android.app.Activity; import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; import androidx.annotation.Nullable; import java.lang.ref.WeakReference; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.Utils; +import app.revanced.integrations.shared.settings.BaseSettings; import app.revanced.integrations.youtube.settings.Settings; @SuppressWarnings("unused") public final class NavigationBar { + // + // Search bar + // + private static volatile WeakReference searchBarResultsRef = new WeakReference<>(null); /** @@ -36,11 +44,101 @@ public final class NavigationBar { return searchbarResults != null && searchbarResults.getParent() != null; } + // + // Navigation bar buttons + // + /** - * Last YT navigation enum loaded. Not necessarily the active navigation tab. + * How long to wait for the set nav button latch to be released. Maximum wait time must + * be as small as possible while still allowing enough time for the nav bar to update. + * + * YT calls it's back button handlers out of order, + * and litho starts filtering before the navigation bar is updated. + * + * Fixing this situation and not needlessly waiting requires somehow + * detecting if a back button key-press will cause a tab change. + * + * Typically after pressing the back button, the time between the first litho event and + * when the nav button is updated is about 10-20ms. Using 50-100ms here should be enough time + * and not noticeable, since YT typically takes 100-200ms (or more) to update the view anyways. + * + * This issue can also be avoided on a patch by patch basis, by avoiding calls to + * {@link NavigationButton#getSelectedNavigationButton()} unless absolutely necessary. + */ + private static final long LATCH_AWAIT_TIMEOUT_MILLISECONDS = 75; + + /** + * Used as a workaround to fix the issue of YT calling back button handlers out of order. + * Used to hold calls to {@link NavigationButton#getSelectedNavigationButton()} + * until the current navigation button can be determined. + * + * Only used when the hardware back button is pressed. */ @Nullable - private static volatile String lastYTNavigationEnumName; + private static volatile CountDownLatch navButtonLatch; + + /** + * Map of nav button layout views to Enum type. + * No synchronization is needed, and this is always accessed from the main thread. + */ + private static final Map viewToButtonMap = new WeakHashMap<>(); + + static { + // On app startup litho can start before the navigation bar is initialized. + // Force it to wait until the nav bar is updated. + createNavButtonLatch(); + } + + private static void createNavButtonLatch() { + navButtonLatch = new CountDownLatch(1); + } + + private static void releaseNavButtonLatch() { + CountDownLatch latch = navButtonLatch; + if (latch != null) { + navButtonLatch = null; + latch.countDown(); + } + } + + private static void waitForNavButtonLatchIfNeeded() { + CountDownLatch latch = navButtonLatch; + if (latch == null) { + return; + } + + if (Utils.isCurrentlyOnMainThread()) { + // The latch is released from the main thread, and waiting from the main thread will always timeout. + // This situation has only been observed when navigating out of a submenu and not changing tabs. + // and for that use case the nav bar does not change so it's safe to return here. + Logger.printDebug(() -> "Cannot block main thread waiting for nav button. Using last known navbar button status."); + return; + } + + try { + Logger.printDebug(() -> "Latch wait started"); + if (latch.await(LATCH_AWAIT_TIMEOUT_MILLISECONDS, TimeUnit.MILLISECONDS)) { + // Back button changed the navigation tab. + Logger.printDebug(() -> "Latch wait complete"); + return; + } + + // Timeout occurred, and a normal event when pressing the physical back button + // does not change navigation tabs. + releaseNavButtonLatch(); // Prevent other threads from waiting for no reason. + Logger.printDebug(() -> "Latch wait timed out"); + + } catch (InterruptedException ex) { + Logger.printException(() -> "Latch wait interrupted failure", ex); // Will never happen. + } + } + + /** + * Last YT navigation enum loaded. Not necessarily the active navigation tab. + * Always accessed from the main thread. + */ + @Nullable + private static String lastYTNavigationEnumName; /** * Injection point. @@ -57,21 +155,16 @@ public final class NavigationBar { public static void navigationTabLoaded(final View navigationButtonGroup) { try { String lastEnumName = lastYTNavigationEnumName; + for (NavigationButton button : NavigationButton.values()) { if (button.ytEnumName.equals(lastEnumName)) { - ImageView imageView = Utils.getChildView((ViewGroup) navigationButtonGroup, - true, view -> view instanceof ImageView); - - if (imageView != null) { - Logger.printDebug(() -> "navigationTabLoaded: " + lastEnumName); - - button.imageViewRef = new WeakReference<>(imageView); - navigationTabCreatedCallback(button, navigationButtonGroup); - - return; - } + Logger.printDebug(() -> "navigationTabLoaded: " + lastEnumName); + viewToButtonMap.put(navigationButtonGroup, button); + navigationTabCreatedCallback(button, navigationButtonGroup); + return; } } + // Log the unknown tab as exception level, only if debug is enabled. // This is because unknown tabs do no harm, and it's only relevant to developers. if (Settings.DEBUG.get()) { @@ -99,6 +192,46 @@ public final class NavigationBar { } } + /** + * Injection point. + */ + public static void navigationTabSelected(View navButtonImageView, boolean isSelected) { + try { + NavigationButton button = viewToButtonMap.get(navButtonImageView); + + if (button == null) { // An unknown tab was selected. + // Show a toast only if debug mode is enabled. + if (BaseSettings.DEBUG.get()) { + Logger.printException(() -> "Unknown navigation view selected: " + navButtonImageView); + } + + NavigationButton.selectedNavigationButton = null; + return; + } + + if (isSelected) { + NavigationButton.selectedNavigationButton = button; + Logger.printDebug(() -> "Changed to navigation button: " + button); + + // Release any threads waiting for the selected nav button. + releaseNavButtonLatch(); + } else if (NavigationButton.selectedNavigationButton == button) { + NavigationButton.selectedNavigationButton = null; + Logger.printDebug(() -> "Navigated away from button: " + button); + } + } catch (Exception ex) { + Logger.printException(() -> "navigationTabSelected failure", ex); + } + } + + /** + * Injection point. + */ + public static void onBackPressed(Activity activity) { + Logger.printDebug(() -> "Back button pressed"); + createNavButtonLatch(); + } + /** @noinspection EmptyMethod*/ private static void navigationTabCreatedCallback(NavigationButton button, View tabView) { // Code is added during patching. @@ -109,8 +242,7 @@ public final class NavigationBar { SHORTS("TAB_SHORTS"), /** * Create new video tab. - * - * {@link #isSelected()} always returns false, even if the create video UI is on screen. + * This tab will never be in a selected state, even if the create video UI is on screen. */ CREATE("CREATION_TAB_LARGE"), SUBSCRIPTIONS("PIVOT_SUBSCRIPTIONS"), @@ -145,41 +277,43 @@ public final class NavigationBar { // The hooked YT code does not use an enum, and a dummy name is used here. LIBRARY_YOU("YOU_LIBRARY_DUMMY_PLACEHOLDER_NAME"); + @Nullable + private static volatile NavigationButton selectedNavigationButton; + /** + * This will return null only if the currently selected tab is unknown. + * This scenario will only happen if the UI has different tabs due to an A/B user test + * or YT abruptly changes the navigation layout for some other reason. + * + * All code calling this method should handle a null return value. + * + * Due to issues with how YT processes physical back button events, + * this patch uses workarounds that can cause this method to take up to 75ms + * if the device back button was recently pressed. + * * @return The active navigation tab. - * If the user is in the create new video UI, this returns NULL. + * If the user is in the upload video UI, this returns tab that is still visually + * selected on screen (whatever tab the user was on before tapping the upload button). */ @Nullable public static NavigationButton getSelectedNavigationButton() { - for (NavigationButton button : values()) { - if (button.isSelected()) return button; - } - return null; - } - - /** - * @return If the currently selected tab is a 'You' or library type. - * Covers all known app states including incognito mode and version spoofing. - */ - public static boolean libraryOrYouTabIsSelected() { - return LIBRARY_YOU.isSelected() || LIBRARY_PIVOT_UNKNOWN.isSelected() - || LIBRARY_OLD_UI.isSelected() || LIBRARY_INCOGNITO.isSelected() - || LIBRARY_LOGGED_OUT.isSelected(); + waitForNavButtonLatchIfNeeded(); + return selectedNavigationButton; } /** * YouTube enum name for this tab. */ private final String ytEnumName; - private volatile WeakReference imageViewRef = new WeakReference<>(null); NavigationButton(String ytEnumName) { this.ytEnumName = ytEnumName; } - public boolean isSelected() { - ImageView view = imageViewRef.get(); - return view != null && view.isSelected(); + public boolean isLibraryOrYouTab() { + return this == LIBRARY_YOU || this == LIBRARY_PIVOT_UNKNOWN + || this == LIBRARY_OLD_UI || this == LIBRARY_INCOGNITO + || this == LIBRARY_LOGGED_OUT; } } } From dba707800ef4e1072ce9be11cfce38c3253e3d9f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Apr 2024 08:32:23 +0000 Subject: [PATCH 19/51] chore(release): 1.8.0-dev.4 [skip ci] # [1.8.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.3...v1.8.0-dev.4) (2024-04-10) ### Bug Fixes * **YouTube - Hide Shorts components:** Correctly hide Shorts if navigation tab is changed using device back button ([#611](https://github.com/ReVanced/revanced-integrations/issues/611)) ([ffc3437](https://github.com/ReVanced/revanced-integrations/commit/ffc3437843c24af255d2a0dda9930d2843cac4b6)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92584a6b..7e827da1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.3...v1.8.0-dev.4) (2024-04-10) + + +### Bug Fixes + +* **YouTube - Hide Shorts components:** Correctly hide Shorts if navigation tab is changed using device back button ([#611](https://github.com/ReVanced/revanced-integrations/issues/611)) ([ffc3437](https://github.com/ReVanced/revanced-integrations/commit/ffc3437843c24af255d2a0dda9930d2843cac4b6)) + # [1.8.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.2...v1.8.0-dev.3) (2024-04-09) diff --git a/gradle.properties b/gradle.properties index 972ee826..1720e4d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.3 +version = 1.8.0-dev.4 From eeaeb49f2a562d2690dae184153c303a5b1c4368 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:29:20 +0400 Subject: [PATCH 20/51] fix(YouTube - Return YouTube Dislike): Do not clip compact text when not using English --- .../patches/ReturnYouTubeDislikePatch.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java index 4938fb37..1c66cb93 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java @@ -176,12 +176,6 @@ public class ReturnYouTubeDislikePatch { textView.removeTextChangedListener(oldUiTextWatcher); textView.addTextChangedListener(oldUiTextWatcher); - /** - * If the patch is changed to include the dislikes button as a parameter to this method, - * then if the button is already selected the dislikes could be adjusted using - * {@link ReturnYouTubeDislike#setUserVote(Vote)} - */ - updateOldUIDislikesTextView(); } catch (Exception ex) { @@ -314,19 +308,25 @@ public class ReturnYouTubeDislikePatch { */ public static float onRollingNumberMeasured(String text, float measuredTextWidth) { try { - if (Settings.RYD_ENABLED.get() && !Settings.RYD_COMPACT_LAYOUT.get()) { + if (Settings.RYD_ENABLED.get()) { if (ReturnYouTubeDislike.isPreviouslyCreatedSegmentedSpan(text)) { // +1 pixel is needed for some foreign languages that measure // the text different from what is used for layout (Greek in particular). // Probably a bug in Android, but who knows. // Single line mode is also used as an additional fix for this issue. - return measuredTextWidth + ReturnYouTubeDislike.leftSeparatorBounds.right - + ReturnYouTubeDislike.leftSeparatorShapePaddingPixels + 1; + if (Settings.RYD_COMPACT_LAYOUT.get()) { + return measuredTextWidth + 1; + } + + return measuredTextWidth + 1 + + ReturnYouTubeDislike.leftSeparatorBounds.right + + ReturnYouTubeDislike.leftSeparatorShapePaddingPixels; } } } catch (Exception ex) { Logger.printException(() -> "onRollingNumberMeasured failure", ex); } + return measuredTextWidth; } @@ -344,10 +344,12 @@ public class ReturnYouTubeDislikePatch { } else { view.setCompoundDrawables(separator, null, null, null); } + // Disliking can cause the span to grow in size, which is ok and is laid out correctly, // but if the user then removes their dislike the layout will not adjust to the new shorter width. // Use a center alignment to take up any extra space. view.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + // Single line mode does not clip words if the span is larger than the view bounds. // The styled span applied to the view should always have the same bounds, // but use this feature just in case the measurements are somehow off by a few pixels. From 4fd3cc906d0c04fedd603fae0f6e5be3882857ba Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Apr 2024 14:33:37 +0000 Subject: [PATCH 21/51] chore(release): 1.8.0-dev.5 [skip ci] # [1.8.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.4...v1.8.0-dev.5) (2024-04-10) ### Bug Fixes * **YouTube - Return YouTube Dislike:** Do not clip compact text when not using English ([eeaeb49](https://github.com/ReVanced/revanced-integrations/commit/eeaeb49f2a562d2690dae184153c303a5b1c4368)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e827da1..67d44658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.4...v1.8.0-dev.5) (2024-04-10) + + +### Bug Fixes + +* **YouTube - Return YouTube Dislike:** Do not clip compact text when not using English ([eeaeb49](https://github.com/ReVanced/revanced-integrations/commit/eeaeb49f2a562d2690dae184153c303a5b1c4368)) + # [1.8.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.3...v1.8.0-dev.4) (2024-04-10) diff --git a/gradle.properties b/gradle.properties index 1720e4d6..cf92d0e4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.4 +version = 1.8.0-dev.5 From c132670400e6bdf17c46b8d04d579fb49c3d2749 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:55:57 +0400 Subject: [PATCH 22/51] fix(YouTube - Hide Shorts components): Do not show Shorts suggestions in video player, if all hide Shorts options are enabled (#613) --- .../patches/components/ShortsFilter.java | 24 +++++++++++++++---- .../youtube/shared/NavigationBar.java | 17 +++++++------ 2 files changed, 27 insertions(+), 14 deletions(-) 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 bd5a32d7..039cb9d1 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 @@ -220,20 +220,34 @@ public final class ShortsFilter extends Filter { } private static boolean shouldHideShortsFeedItems() { + final boolean hideHome = Settings.HIDE_SHORTS_HOME.get(); + final boolean hideSubscriptions = Settings.HIDE_SHORTS_SUBSCRIPTIONS.get(); + final boolean hideSearch = Settings.HIDE_SHORTS_SEARCH.get(); + + if (hideHome && hideSubscriptions && hideSearch) { + // Shorts suggestions can load in the background if a video is opened and + // then immediately minimized before any suggestions are loaded. + // In this state the player type will show minimized, which makes it not possible to + // distinguish between Shorts suggestions loading in the player and between + // scrolling thru search/home/subscription tabs while a player is minimized. + // + // To avoid this situation for users that never want to show Shorts (all hide Shorts options are enabled) + // then hide all Shorts everywhere including the Library history and Library playlists. + return true; + } + // 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_SHORTS_HOME.get(); + return hideHome; } // Must check second, as search can be from any tab. if (NavigationBar.isSearchBarActive()) { - return Settings.HIDE_SHORTS_SEARCH.get(); + return hideSearch; } - // Avoid checking navigation button status if all other settings are off. - final boolean hideHome = Settings.HIDE_SHORTS_HOME.get(); - final boolean hideSubscriptions = Settings.HIDE_SHORTS_SUBSCRIPTIONS.get(); + // Avoid checking navigation button status if all other Shorts should show. if (!hideHome && !hideSubscriptions) { return false; } diff --git a/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java b/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java index 58c2ec0b..5123e78d 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java +++ b/app/src/main/java/app/revanced/integrations/youtube/shared/NavigationBar.java @@ -197,6 +197,10 @@ public final class NavigationBar { */ public static void navigationTabSelected(View navButtonImageView, boolean isSelected) { try { + if (!isSelected) { + return; + } + NavigationButton button = viewToButtonMap.get(navButtonImageView); if (button == null) { // An unknown tab was selected. @@ -209,16 +213,11 @@ public final class NavigationBar { return; } - if (isSelected) { - NavigationButton.selectedNavigationButton = button; - Logger.printDebug(() -> "Changed to navigation button: " + button); + NavigationButton.selectedNavigationButton = button; + Logger.printDebug(() -> "Changed to navigation button: " + button); - // Release any threads waiting for the selected nav button. - releaseNavButtonLatch(); - } else if (NavigationButton.selectedNavigationButton == button) { - NavigationButton.selectedNavigationButton = null; - Logger.printDebug(() -> "Navigated away from button: " + button); - } + // Release any threads waiting for the selected nav button. + releaseNavButtonLatch(); } catch (Exception ex) { Logger.printException(() -> "navigationTabSelected failure", ex); } From 4bd805e54d70d92c64328139da0f0e70c937b351 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 12 Apr 2024 16:59:13 +0000 Subject: [PATCH 23/51] chore(release): 1.8.0-dev.6 [skip ci] # [1.8.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.5...v1.8.0-dev.6) (2024-04-12) ### Bug Fixes * **YouTube - Hide Shorts components:** Do not show Shorts suggestions in video player, if all hide Shorts options are enabled ([#613](https://github.com/ReVanced/revanced-integrations/issues/613)) ([c132670](https://github.com/ReVanced/revanced-integrations/commit/c132670400e6bdf17c46b8d04d579fb49c3d2749)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d44658..b8eb55f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.5...v1.8.0-dev.6) (2024-04-12) + + +### Bug Fixes + +* **YouTube - Hide Shorts components:** Do not show Shorts suggestions in video player, if all hide Shorts options are enabled ([#613](https://github.com/ReVanced/revanced-integrations/issues/613)) ([c132670](https://github.com/ReVanced/revanced-integrations/commit/c132670400e6bdf17c46b8d04d579fb49c3d2749)) + # [1.8.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.4...v1.8.0-dev.5) (2024-04-10) diff --git a/gradle.properties b/gradle.properties index cf92d0e4..97aaa7f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.5 +version = 1.8.0-dev.6 From acfa3c98868b6d84572ee682ad806a0282ac6dad Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 12 Apr 2024 23:43:51 +0400 Subject: [PATCH 24/51] feat(YouTube - Hide Shorts components): Hide `Shop`, `Location` and `Save sound to playlist` buttons (#614) --- .../patches/components/ShortsFilter.java | 57 ++++++++++++++++--- .../youtube/settings/Settings.java | 3 + 2 files changed, 51 insertions(+), 9 deletions(-) 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 039cb9d1..05835b50 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 @@ -33,11 +33,16 @@ public final class ShortsFilter extends Filter { private final StringFilterGroup joinButton; private final StringFilterGroup shelfHeader; + private final StringFilterGroup suggestedActionPath; + private final ByteArrayFilterGroupList suggestedActions = new ByteArrayFilterGroupList(); + private final StringFilterGroup actionBar; private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList(); public ShortsFilter() { + // // Identifier components. + // var shorts = new StringFilterGroup( null, // Setting is based on navigation state. @@ -55,14 +60,17 @@ public final class ShortsFilter extends Filter { ); // Home / subscription feed components. - var thanksButton = new StringFilterGroup( + + var thanksButton = new StringFilterGroup( // Edit: Does this item show up anymore? Settings.HIDE_SHORTS_THANKS_BUTTON, "suggested_action" ); addIdentifierCallbacks(shorts, shelfHeader, thanksButton); + // // Path components. + // // Shorts that appear in the feed/search when the device is using tablet layout. shortsCompactFeedVideoPath = new StringFilterGroup(null, "compact_video.eml"); @@ -122,13 +130,21 @@ public final class ShortsFilter extends Filter { "shorts_action_bar" ); + suggestedActionPath = new StringFilterGroup( + null, + "suggested_action.eml" + ); + addPathCallbacks( shortsCompactFeedVideoPath, - joinButton, subscribeButton, subscribeButtonPaused, + joinButton, subscribeButton, subscribeButtonPaused, suggestedActionPath, channelBar, fullVideoLinkLabel, videoTitle, reelSoundMetadata, soundButton, infoPanel, actionBar ); + // + // Action buttons + // var shortsLikeButton = new ByteArrayFilterGroup( Settings.HIDE_SHORTS_LIKE_BUTTON, "shorts_like_button" @@ -161,6 +177,24 @@ public final class ShortsFilter extends Filter { shortsShareButton, shortsRemixButton ); + + // + // Suggested actions. + // + suggestedActions.addAll( + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_SHOP_BUTTON, + "yt_outline_bag_" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_LOCATION_BUTTON, + "yt_outline_location_point_" + ), + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_SAVE_SOUND_BUTTON, + "yt_outline_list_add_" + ) + ); } @Override @@ -185,6 +219,14 @@ 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( @@ -193,14 +235,11 @@ public final class ShortsFilter extends Filter { return false; } - // Filter other path groups from pathFilterGroupList, only when reelChannelBar is visible - // to avoid false positives. - if (matchedGroup == subscribeButton || - matchedGroup == joinButton - ) { - if (path.startsWith(REEL_CHANNEL_BAR_PATH)) return super.isFiltered( + if (matchedGroup == suggestedActionPath) { + if (contentIndex == 0 && suggestedActions.check(protobufBufferArray).isFiltered()) return super.isFiltered( identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex - ); // else, return false. + ); + // else, return false; } return false; 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 e8261ff3..ed90f89d 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 @@ -160,6 +160,9 @@ public class Settings extends BaseSettings { 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_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_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", 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); From 5b4fd770dea82c1f913e2fbcdeb9b3717325d289 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 12 Apr 2024 19:46:41 +0000 Subject: [PATCH 25/51] chore(release): 1.8.0-dev.7 [skip ci] # [1.8.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.6...v1.8.0-dev.7) (2024-04-12) ### Features * **YouTube - Hide Shorts components:** Hide `Shop`, `Location` and `Save sound to playlist` buttons ([#614](https://github.com/ReVanced/revanced-integrations/issues/614)) ([acfa3c9](https://github.com/ReVanced/revanced-integrations/commit/acfa3c98868b6d84572ee682ad806a0282ac6dad)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8eb55f7..2bcbf968 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.6...v1.8.0-dev.7) (2024-04-12) + + +### Features + +* **YouTube - Hide Shorts components:** Hide `Shop`, `Location` and `Save sound to playlist` buttons ([#614](https://github.com/ReVanced/revanced-integrations/issues/614)) ([acfa3c9](https://github.com/ReVanced/revanced-integrations/commit/acfa3c98868b6d84572ee682ad806a0282ac6dad)) + # [1.8.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.5...v1.8.0-dev.6) (2024-04-12) diff --git a/gradle.properties b/gradle.properties index 97aaa7f4..3786b15f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.6 +version = 1.8.0-dev.7 From d6cd550880596de5cd2eb4a0d1325a73326d4af9 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 14 Apr 2024 02:06:41 +0200 Subject: [PATCH 26/51] feat(YouTube - Hide layout components): Hide playables --- .../youtube/patches/components/LayoutComponentsFilter.java | 6 ++++++ .../revanced/integrations/youtube/settings/Settings.java | 1 + 2 files changed, 7 insertions(+) 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 f0e560e4..a0adedde 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 @@ -177,6 +177,11 @@ public final class LayoutComponentsFilter extends Filter { "fullscreen_related_videos" ); + final var playables = new StringFilterGroup( + Settings.HIDE_PLAYABLES, + "horizontal_gaming_shelf.eml" + ); + final var quickActions = new StringFilterGroup( Settings.HIDE_QUICK_ACTIONS, "quick_actions" @@ -256,6 +261,7 @@ public final class LayoutComponentsFilter extends Filter { latestPosts, channelWatermark, communityGuidelines, + playables, quickActions, relatedVideos, compactBanner, 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 ed90f89d..2e3a3801 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 @@ -117,6 +117,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_NOTIFY_ME_BUTTON = new BooleanSetting("revanced_hide_notify_me_button", TRUE); public static final BooleanSetting HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE); public static final BooleanSetting HIDE_PREVIEW_COMMENT = new BooleanSetting("revanced_hide_preview_comment", FALSE, true); + public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_quick_actions", TRUE); public static final BooleanSetting HIDE_QUICK_ACTIONS = new BooleanSetting("revanced_hide_quick_actions", FALSE); public static final BooleanSetting HIDE_RELATED_VIDEOS = new BooleanSetting("revanced_hide_related_videos", FALSE); public static final BooleanSetting HIDE_SEARCH_RESULT_SHELF_HEADER = new BooleanSetting("revanced_hide_search_result_shelf_header", FALSE); From 96f42b3892256bc9c80306e9c1991a29f2eb7a5e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 14 Apr 2024 00:10:19 +0000 Subject: [PATCH 27/51] chore(release): 1.8.0-dev.8 [skip ci] # [1.8.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.7...v1.8.0-dev.8) (2024-04-14) ### Features * **YouTube - Hide layout components:** Hide playables ([d6cd550](https://github.com/ReVanced/revanced-integrations/commit/d6cd550880596de5cd2eb4a0d1325a73326d4af9)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bcbf968..45953416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.7...v1.8.0-dev.8) (2024-04-14) + + +### Features + +* **YouTube - Hide layout components:** Hide playables ([d6cd550](https://github.com/ReVanced/revanced-integrations/commit/d6cd550880596de5cd2eb4a0d1325a73326d4af9)) + # [1.8.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.6...v1.8.0-dev.7) (2024-04-12) diff --git a/gradle.properties b/gradle.properties index 3786b15f..95fdd24d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.7 +version = 1.8.0-dev.8 From a2b15433cffec082394a50d14f7eef625a6351c1 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 14 Apr 2024 13:30:41 +0400 Subject: [PATCH 28/51] fix: Use correct hide playables setting key --- .../app/revanced/integrations/youtube/settings/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2e3a3801..d6617681 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 @@ -117,7 +117,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_NOTIFY_ME_BUTTON = new BooleanSetting("revanced_hide_notify_me_button", TRUE); public static final BooleanSetting HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE); public static final BooleanSetting HIDE_PREVIEW_COMMENT = new BooleanSetting("revanced_hide_preview_comment", FALSE, true); - public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_quick_actions", TRUE); + public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_playables", TRUE); public static final BooleanSetting HIDE_QUICK_ACTIONS = new BooleanSetting("revanced_hide_quick_actions", FALSE); public static final BooleanSetting HIDE_RELATED_VIDEOS = new BooleanSetting("revanced_hide_related_videos", FALSE); public static final BooleanSetting HIDE_SEARCH_RESULT_SHELF_HEADER = new BooleanSetting("revanced_hide_search_result_shelf_header", FALSE); From 79a3a44961d211dcc9832921e6168fb9166524f5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 14 Apr 2024 09:33:39 +0000 Subject: [PATCH 29/51] chore(release): 1.8.0-dev.9 [skip ci] # [1.8.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.8...v1.8.0-dev.9) (2024-04-14) ### Bug Fixes * Use correct hide playables setting key ([a2b1543](https://github.com/ReVanced/revanced-integrations/commit/a2b15433cffec082394a50d14f7eef625a6351c1)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45953416..5c2cd0e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.8...v1.8.0-dev.9) (2024-04-14) + + +### Bug Fixes + +* Use correct hide playables setting key ([a2b1543](https://github.com/ReVanced/revanced-integrations/commit/a2b15433cffec082394a50d14f7eef625a6351c1)) + # [1.8.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.7...v1.8.0-dev.8) (2024-04-14) diff --git a/gradle.properties b/gradle.properties index 95fdd24d..8539044b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.8 +version = 1.8.0-dev.9 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 30/51] 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); From e9cd8986516a5c388a9755c34d1b7e594f987cf9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 14 Apr 2024 14:57:08 +0000 Subject: [PATCH 31/51] chore(release): 1.8.0-dev.10 [skip ci] # [1.8.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.9...v1.8.0-dev.10) (2024-04-14) ### Features * **YouTube - Hide Shorts components:** Hide tagged products, hide search suggestions ([#615](https://github.com/ReVanced/revanced-integrations/issues/615)) ([0586fb7](https://github.com/ReVanced/revanced-integrations/commit/0586fb70e347c25742e03102441cfb37315b5937)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c2cd0e5..6b0018ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.9...v1.8.0-dev.10) (2024-04-14) + + +### Features + +* **YouTube - Hide Shorts components:** Hide tagged products, hide search suggestions ([#615](https://github.com/ReVanced/revanced-integrations/issues/615)) ([0586fb7](https://github.com/ReVanced/revanced-integrations/commit/0586fb70e347c25742e03102441cfb37315b5937)) + # [1.8.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.8...v1.8.0-dev.9) (2024-04-14) diff --git a/gradle.properties b/gradle.properties index 8539044b..26dac1ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.9 +version = 1.8.0-dev.10 From 9108205445c533550db454731d4f9460a3241a03 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 14 Apr 2024 23:37:17 +0400 Subject: [PATCH 32/51] fix(YouTube - Return YouTube Dislike): Do not show error toast if API success response contains new lines (#612) --- .../requests/ReturnYouTubeDislikeApi.java | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java index 73db5f00..9b22aafc 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java +++ b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java @@ -279,7 +279,7 @@ public class ReturnYouTubeDislikeApi { } if (responseCode == HTTP_STATUS_CODE_SUCCESS) { - // do not disconnect, the same server connection will likely be used again soon + // Do not disconnect, the same server connection will likely be used again soon. JSONObject json = Requester.parseJSONObject(connection); try { RYDVoteData votingData = new RYDVoteData(json); @@ -377,20 +377,17 @@ public class ReturnYouTubeDislikeApi { connection.disconnect(); // disconnect, as no more connections will be made for a little while return null; } - String result = null; if (responseCode == HTTP_STATUS_CODE_SUCCESS) { - result = Requester.parseJson(connection); - if (result.equalsIgnoreCase("true")) { - Logger.printDebug(() -> "Registration confirmation successful"); - return userId; - } + Logger.printDebug(() -> "Registration confirmation successful"); + return userId; } - final String resultLog = result == null ? "(no response)" : result; + + // Something went wrong, might as well disconnect. + String response = Requester.parseJsonAndDisconnect(connection); Logger.printInfo(() -> "Failed to confirm registration for user: " + userId - + " solution: " + solution + " responseCode: " + responseCode + " responseString: " + resultLog); + + " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "''"); handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null, true); - connection.disconnect(); // something went wrong, might as well disconnect } catch (SocketTimeoutException ex) { handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex, false); } catch (IOException ex) { @@ -461,6 +458,7 @@ public class ReturnYouTubeDislikeApi { String solution = solvePuzzle(challenge, difficulty); return confirmVote(videoId, userId, solution); } + Logger.printInfo(() -> "Failed to send vote for video: " + videoId + " vote: " + vote + " response code was: " + responseCode); handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), @@ -501,20 +499,17 @@ public class ReturnYouTubeDislikeApi { connection.disconnect(); // disconnect, as no more connections will be made for a little while return false; } - String result = null; if (responseCode == HTTP_STATUS_CODE_SUCCESS) { - result = Requester.parseJson(connection); - if (result.equalsIgnoreCase("true")) { - Logger.printDebug(() -> "Vote confirm successful for video: " + videoId); - return true; - } + Logger.printDebug(() -> "Vote confirm successful for video: " + videoId); + return true; } - final String resultLog = result == null ? "(no response)" : result; + + // Something went wrong, might as well disconnect. + String response = Requester.parseJsonAndDisconnect(connection); Logger.printInfo(() -> "Failed to confirm vote for video: " + videoId - + " solution: " + solution + " responseCode: " + responseCode + " responseString: " + resultLog); + + " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "'"); handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null, true); - connection.disconnect(); // something went wrong, might as well disconnect } catch (SocketTimeoutException ex) { handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex, false); } catch (IOException ex) { From 92c591735a10da31b30620bd9a6d30f0a85e2b15 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 14 Apr 2024 19:40:10 +0000 Subject: [PATCH 33/51] chore(release): 1.8.0-dev.11 [skip ci] # [1.8.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.10...v1.8.0-dev.11) (2024-04-14) ### Bug Fixes * **YouTube - Return YouTube Dislike:** Do not show error toast if API success response contains new lines ([#612](https://github.com/ReVanced/revanced-integrations/issues/612)) ([9108205](https://github.com/ReVanced/revanced-integrations/commit/9108205445c533550db454731d4f9460a3241a03)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b0018ae..afcdb064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.10...v1.8.0-dev.11) (2024-04-14) + + +### Bug Fixes + +* **YouTube - Return YouTube Dislike:** Do not show error toast if API success response contains new lines ([#612](https://github.com/ReVanced/revanced-integrations/issues/612)) ([9108205](https://github.com/ReVanced/revanced-integrations/commit/9108205445c533550db454731d4f9460a3241a03)) + # [1.8.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.9...v1.8.0-dev.10) (2024-04-14) diff --git a/gradle.properties b/gradle.properties index 26dac1ae..4eb0f747 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.10 +version = 1.8.0-dev.11 From 13dc17288d13d024a3fbe318ee0fb23a0d46af85 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:18:48 +0400 Subject: [PATCH 34/51] fix(YouTube - Hide ads): rename `Hide paid content` to `Hide paid promotion label` (#616) --- .../youtube/patches/components/LayoutComponentsFilter.java | 6 +++--- .../revanced/integrations/youtube/settings/Settings.java | 2 +- 2 files changed, 4 insertions(+), 4 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 a0adedde..0f69f546 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 @@ -113,8 +113,8 @@ public final class LayoutComponentsFilter extends Filter { "medical_panel" ); - final var paidContent = new StringFilterGroup( - Settings.HIDE_PAID_CONTENT, + final var paidPromotion = new StringFilterGroup( + Settings.HIDE_PAID_PROMOTION_LABEL, "paid_content_overlay" ); @@ -256,7 +256,7 @@ public final class LayoutComponentsFilter extends Filter { notifyMe, channelBar, communityPosts, - paidContent, + paidPromotion, searchResultVideo, latestPosts, channelWatermark, 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 f7432af5..98770fea 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 @@ -49,7 +49,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_GET_PREMIUM = new BooleanSetting("revanced_hide_get_premium", TRUE); public static final BooleanSetting HIDE_HIDE_LATEST_POSTS = new BooleanSetting("revanced_hide_latest_posts_ads", TRUE); public static final BooleanSetting HIDE_MERCHANDISE_BANNERS = new BooleanSetting("revanced_hide_merchandise_banners", TRUE); - public static final BooleanSetting HIDE_PAID_CONTENT = new BooleanSetting("revanced_hide_paid_content_ads", TRUE); + public static final BooleanSetting HIDE_PAID_PROMOTION_LABEL = new BooleanSetting("revanced_hide_paid_promotion_label", TRUE); public static final BooleanSetting HIDE_PRODUCTS_BANNER = new BooleanSetting("revanced_hide_products_banner", TRUE); public static final BooleanSetting HIDE_SHOPPING_LINKS = new BooleanSetting("revanced_hide_shopping_links", TRUE); public static final BooleanSetting HIDE_SELF_SPONSOR = new BooleanSetting("revanced_hide_self_sponsor_ads", TRUE); From 8e36a018f459e88987626888c0a16c5b081ac241 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 15 Apr 2024 15:21:42 +0000 Subject: [PATCH 35/51] chore(release): 1.8.0-dev.12 [skip ci] # [1.8.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.11...v1.8.0-dev.12) (2024-04-15) ### Bug Fixes * **YouTube - Hide ads:** rename `Hide paid content` to `Hide paid promotion label` ([#616](https://github.com/ReVanced/revanced-integrations/issues/616)) ([13dc172](https://github.com/ReVanced/revanced-integrations/commit/13dc17288d13d024a3fbe318ee0fb23a0d46af85)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afcdb064..61685fc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.11...v1.8.0-dev.12) (2024-04-15) + + +### Bug Fixes + +* **YouTube - Hide ads:** rename `Hide paid content` to `Hide paid promotion label` ([#616](https://github.com/ReVanced/revanced-integrations/issues/616)) ([13dc172](https://github.com/ReVanced/revanced-integrations/commit/13dc17288d13d024a3fbe318ee0fb23a0d46af85)) + # [1.8.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.10...v1.8.0-dev.11) (2024-04-14) diff --git a/gradle.properties b/gradle.properties index 4eb0f747..9df66908 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.11 +version = 1.8.0-dev.12 From bba421ddb63597bf918ecccacfd4a33493016b9f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 16 Apr 2024 06:43:40 +0400 Subject: [PATCH 36/51] fix(YouTube - Hide Shorts components): Hide suggested actions in incognito mode --- .../integrations/youtube/patches/components/ShortsFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 cbe254aa..ad78ac8e 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 @@ -220,7 +220,8 @@ public final class ShortsFilter extends Filter { } if (matchedGroup == suggestedAction) { - if (contentIndex == 0 && suggestedActionsGroupList.check(protobufBufferArray).isFiltered()) { + // Suggested actions can be at the start or in the middle of a path. + if (suggestedActionsGroupList.check(protobufBufferArray).isFiltered()) { return super.isFiltered( identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex ); From d60dcf98ab0bbc5017bd0226d2424f266439fb2c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 16 Apr 2024 02:46:53 +0000 Subject: [PATCH 37/51] chore(release): 1.8.0-dev.13 [skip ci] # [1.8.0-dev.13](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.12...v1.8.0-dev.13) (2024-04-16) ### Bug Fixes * **YouTube - Hide Shorts components:** Hide suggested actions in incognito mode ([bba421d](https://github.com/ReVanced/revanced-integrations/commit/bba421ddb63597bf918ecccacfd4a33493016b9f)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61685fc2..8dc5df47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.13](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.12...v1.8.0-dev.13) (2024-04-16) + + +### Bug Fixes + +* **YouTube - Hide Shorts components:** Hide suggested actions in incognito mode ([bba421d](https://github.com/ReVanced/revanced-integrations/commit/bba421ddb63597bf918ecccacfd4a33493016b9f)) + # [1.8.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.11...v1.8.0-dev.12) (2024-04-15) diff --git a/gradle.properties b/gradle.properties index 9df66908..6e2db839 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.12 +version = 1.8.0-dev.13 From 9938bbf0de9592db015ae0cfea83e855e12f0c7e Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:00:35 +0400 Subject: [PATCH 38/51] fix(YouTube - Hide Shorts components): Hide subscribe button in channel bar --- .../youtube/patches/components/ShortsFilter.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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 ad78ac8e..c03d4518 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 @@ -17,7 +17,12 @@ import app.revanced.integrations.youtube.shared.PlayerType; @SuppressWarnings("unused") public final class ShortsFilter extends Filter { public static PivotBar pivotBar; // Set by patch. - private final String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml"; + + private final static String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml"; + /** + * For subscribe button that appears in the channel bar. + */ + private final static String REEL_METAPANEL_PATH = "reel_metapanel.eml"; private final StringFilterGroup shortsCompactFeedVideoPath; private final ByteArrayFilterGroup shortsCompactFeedVideoBuffer; @@ -192,8 +197,8 @@ public final class ShortsFilter extends Filter { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (contentType == FilterContentType.PATH) { if (matchedGroup == subscribeButton || matchedGroup == joinButton) { - // Filter only when reelChannelBar is visible to avoid false positives. - if (path.startsWith(REEL_CHANNEL_BAR_PATH)) { + // Selectively filter to avoid false positive filtering of other subscribe/join buttons. + if (path.startsWith(REEL_CHANNEL_BAR_PATH) || path.startsWith(REEL_METAPANEL_PATH)) { return super.isFiltered( identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex ); From f5720f71a65fd3c9ec39381ef506e79222a4b071 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 17 Apr 2024 10:04:02 +0000 Subject: [PATCH 39/51] chore(release): 1.8.0-dev.14 [skip ci] # [1.8.0-dev.14](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.13...v1.8.0-dev.14) (2024-04-17) ### Bug Fixes * **YouTube - Hide Shorts components:** Hide subscribe button in channel bar ([9938bbf](https://github.com/ReVanced/revanced-integrations/commit/9938bbf0de9592db015ae0cfea83e855e12f0c7e)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dc5df47..e1140954 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.14](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.13...v1.8.0-dev.14) (2024-04-17) + + +### Bug Fixes + +* **YouTube - Hide Shorts components:** Hide subscribe button in channel bar ([9938bbf](https://github.com/ReVanced/revanced-integrations/commit/9938bbf0de9592db015ae0cfea83e855e12f0c7e)) + # [1.8.0-dev.13](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.12...v1.8.0-dev.13) (2024-04-16) diff --git a/gradle.properties b/gradle.properties index 6e2db839..3512d0d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.13 +version = 1.8.0-dev.14 From b8f260ebd3e7c2dc50a57cd060b76f2e0fc4a89c Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:00:52 +0400 Subject: [PATCH 40/51] feat(YouTube): Add 'About' preference to settings menu (#608) Co-authored-by: oSumAtrIX --- .../revanced/integrations/shared/Utils.java | 81 +++-- .../AbstractPreferenceFragment.java | 5 +- .../preference/ImportExportPreference.java | 2 +- .../preference/ReVancedAboutPreference.java | 312 ++++++++++++++++++ .../ResettableEditTextPreference.java | 6 +- .../integrations/youtube/ThemeHelper.java | 57 +++- .../announcements/AnnouncementsPatch.java | 2 +- .../patches/spoof/requests/PlayerRoutes.java | 4 +- .../youtube/requests/Requester.java | 90 ++--- .../requests/ReturnYouTubeDislikeApi.java | 10 +- ...ativeThumbnailsAboutDeArrowPreference.java | 2 +- .../ReVancedYouTubeAboutPreference.java | 32 ++ .../sponsorblock/requests/SBRequester.java | 6 +- 13 files changed, 518 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/app/revanced/integrations/shared/settings/preference/ReVancedAboutPreference.java create mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedYouTubeAboutPreference.java 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 371100d1..bdad852f 100644 --- a/app/src/main/java/app/revanced/integrations/shared/Utils.java +++ b/app/src/main/java/app/revanced/integrations/shared/Utils.java @@ -35,6 +35,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import app.revanced.integrations.shared.settings.BooleanSetting; +import app.revanced.integrations.shared.settings.preference.ReVancedAboutPreference; import kotlin.text.Regex; public class Utils { @@ -47,30 +48,44 @@ public class Utils { private Utils() { } // utility class - public static String getVersionName() { - if (versionName != null) return versionName; + /** + * Injection point. + * + * @return The manifest 'Version' entry of the patches.jar used during patching. + */ + public static String getPatchesReleaseVersion() { + return ""; // Value is replaced during patching. + } - PackageInfo packageInfo; - try { - final var packageName = Objects.requireNonNull(getContext()).getPackageName(); + /** + * @return The version name of the app, such as "YouTube". + */ + public static String getAppVersionName() { + if (versionName == null) { + try { + final var packageName = Objects.requireNonNull(getContext()).getPackageName(); - PackageManager packageManager = context.getPackageManager(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) - packageInfo = packageManager.getPackageInfo( - packageName, - PackageManager.PackageInfoFlags.of(0) - ); - else - packageInfo = packageManager.getPackageInfo( - packageName, - 0 - ); - } catch (PackageManager.NameNotFoundException e) { - Logger.printException(() -> "Failed to get package info", e); - return null; + PackageManager packageManager = context.getPackageManager(); + PackageInfo packageInfo; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + packageInfo = packageManager.getPackageInfo( + packageName, + PackageManager.PackageInfoFlags.of(0) + ); + } else { + packageInfo = packageManager.getPackageInfo( + packageName, + 0 + ); + } + versionName = packageInfo.versionName; + } catch (Exception ex) { + Logger.printException(() -> "Failed to get package info", ex); + versionName = "Unknown"; + } } - return versionName = packageInfo.versionName; + return versionName; } /** @@ -185,6 +200,7 @@ public class Utils { } public static int getResourceColor(@NonNull String resourceIdentifierName) throws Resources.NotFoundException { + //noinspection deprecation return getContext().getResources().getColor(getResourceIdentifier(resourceIdentifierName, "color")); } @@ -323,7 +339,7 @@ public class Utils { try { runnable.run(); } catch (Exception ex) { - Logger.printException(() -> runnable.getClass() + ": " + ex.getMessage(), ex); + Logger.printException(() -> runnable.getClass().getSimpleName() + ": " + ex.getMessage(), ex); } }; new Handler(Looper.getMainLooper()).postDelayed(loggingRunnable, delayMillis); @@ -445,11 +461,8 @@ public class Utils { this.keySuffix = keySuffix; } - /** - * Defaults to {@link #UNSORTED} if key is null or has no sort suffix. - */ @NonNull - static Sort fromKey(@Nullable String key) { + static Sort fromKey(@Nullable String key, @NonNull Sort defaultSort) { if (key != null) { for (Sort sort : values()) { if (key.endsWith(sort.keySuffix)) { @@ -457,7 +470,7 @@ public class Utils { } } } - return UNSORTED; + return defaultSort; } } @@ -479,19 +492,26 @@ public class Utils { * If a preference has no key or no {@link Sort} suffix, * then the preferences are left unsorted. */ + @SuppressWarnings("deprecation") public static void sortPreferenceGroups(@NonNull PreferenceGroup group) { - Sort sort = Sort.fromKey(group.getKey()); + Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED); SortedMap preferences = new TreeMap<>(); for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) { Preference preference = group.getPreference(i); + final Sort preferenceSort; if (preference instanceof PreferenceGroup) { sortPreferenceGroups((PreferenceGroup) preference); + preferenceSort = groupSort; // Sort value for groups is for it's content, not itself. + } else { + // Allow individual preferences to set a key sorting. + // Used to force a preference to the top or bottom of a group. + preferenceSort = Sort.fromKey(preference.getKey(), groupSort); } final String sortValue; - switch (sort) { + switch (preferenceSort) { case BY_TITLE: sortValue = removePunctuationConvertToLowercase(preference.getTitle()); break; @@ -511,8 +531,9 @@ public class Utils { for (Preference pref : preferences.values()) { int order = index++; - // If the preference is a PreferenceScreen or is an intent preference, move to the top. - if (pref instanceof PreferenceScreen || pref.getIntent() != null) { + // Move any screens, intents, and the one off About preference to the top. + if (pref instanceof PreferenceScreen || pref instanceof ReVancedAboutPreference + || pref.getIntent() != null) { // Arbitrary high number. order -= 1000; } diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java index 34a348a3..b7fa68ac 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java @@ -16,10 +16,7 @@ import app.revanced.integrations.shared.settings.Setting; import static app.revanced.integrations.shared.StringRef.str; -/** - * - * - * @noinspection deprecation, DataFlowIssue , unused */ +@SuppressWarnings({"unused", "deprecation"}) public abstract class AbstractPreferenceFragment extends PreferenceFragment { /** * Indicates that if a preference changes, diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/preference/ImportExportPreference.java b/app/src/main/java/app/revanced/integrations/shared/settings/preference/ImportExportPreference.java index 0a9b54c1..5c8e7c9b 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/preference/ImportExportPreference.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/preference/ImportExportPreference.java @@ -15,7 +15,7 @@ import app.revanced.integrations.shared.Utils; import static app.revanced.integrations.shared.StringRef.str; -/** @noinspection deprecation, unused */ +@SuppressWarnings({"unused", "deprecation"}) public class ImportExportPreference extends EditTextPreference implements Preference.OnPreferenceClickListener { private String existingSettings; diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/preference/ReVancedAboutPreference.java b/app/src/main/java/app/revanced/integrations/shared/settings/preference/ReVancedAboutPreference.java new file mode 100644 index 00000000..f5911a01 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/shared/settings/preference/ReVancedAboutPreference.java @@ -0,0 +1,312 @@ +package app.revanced.integrations.shared.settings.preference; + +import static app.revanced.integrations.shared.StringRef.str; +import static app.revanced.integrations.youtube.requests.Route.Method.GET; + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.preference.Preference; +import android.util.AttributeSet; +import android.view.Window; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.List; + +import app.revanced.integrations.shared.Logger; +import app.revanced.integrations.shared.Utils; +import app.revanced.integrations.youtube.requests.Requester; +import app.revanced.integrations.youtube.requests.Route; + +/** + * Opens a dialog showing the links from {@link SocialLinksRoutes}. + */ +@SuppressWarnings({"unused", "deprecation"}) +public class ReVancedAboutPreference extends Preference { + + private static String useNonBreakingHyphens(String text) { + // Replace any dashes with non breaking dashes, so the English text 'pre-release' + // and the dev release number does not break and cover two lines. + return text.replace("-", "‑"); // #8209 = non breaking hyphen. + } + + private static String getColorHexString(int color) { + return String.format("#%06X", (0x00FFFFFF & color)); + } + + protected boolean isDarkModeEnabled() { + Configuration config = getContext().getResources().getConfiguration(); + final int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK; + return currentNightMode == Configuration.UI_MODE_NIGHT_YES; + } + + /** + * Subclasses can override this and provide a themed color. + */ + protected int getLightColor() { + return Color.WHITE; + } + + /** + * Subclasses can override this and provide a themed color. + */ + protected int getDarkColor() { + return Color.BLACK; + } + + private String createDialogHtml(ReVancedSocialLink[] socialLinks) { + final boolean isNetworkConnected = Utils.isNetworkConnected(); + + StringBuilder builder = new StringBuilder(); + builder.append(""); + builder.append(""); + + final boolean isDarkMode = isDarkModeEnabled(); + String backgroundColorHex = getColorHexString(isDarkMode ? getDarkColor() : getLightColor()); + String foregroundColorHex = getColorHexString(isDarkMode ? getLightColor() : getDarkColor()); + // Apply light/dark mode colors. + builder.append(String.format( + "", + backgroundColorHex, foregroundColorHex, foregroundColorHex)); + + if (isNetworkConnected) { + builder.append(""); + } + + String patchesVersion = Utils.getPatchesReleaseVersion(); + + // Add the title. + builder.append("

") + .append("ReVanced") + .append("

"); + + builder.append("

") + // Replace hyphens with non breaking dashes so the version number does not break lines. + .append(useNonBreakingHyphens(str("revanced_settings_about_links_body", patchesVersion))) + .append("

"); + + // Add a disclaimer if using a dev release. + if (patchesVersion.contains("dev")) { + builder.append("

") + // English text 'Pre-release' can break lines. + .append(useNonBreakingHyphens(str("revanced_settings_about_links_dev_header"))) + .append("

"); + + builder.append("

") + .append(str("revanced_settings_about_links_dev_body")) + .append("

"); + } + + builder.append("

") + .append(str("revanced_settings_about_links_header")) + .append("

"); + + builder.append("
"); + for (ReVancedSocialLink social : socialLinks) { + builder.append("
"); + builder.append(String.format("%s", social.url, social.name)); + builder.append("
"); + } + builder.append("
"); + + builder.append(""); + return builder.toString(); + } + + { + setOnPreferenceClickListener(pref -> { + // Show a progress spinner if the social links are not fetched yet. + if (!SocialLinksRoutes.hasFetchedLinks() && Utils.isNetworkConnected()) { + ProgressDialog progress = new ProgressDialog(getContext()); + progress.setProgressStyle(ProgressDialog.STYLE_SPINNER); + progress.show(); + Utils.runOnBackgroundThread(() -> fetchLinksAndShowDialog(progress)); + } else { + // No network call required and can run now. + fetchLinksAndShowDialog(null); + } + + return false; + }); + } + + private void fetchLinksAndShowDialog(@Nullable ProgressDialog progress) { + ReVancedSocialLink[] socialLinks = SocialLinksRoutes.fetchSocialLinks(); + String htmlDialog = createDialogHtml(socialLinks); + + Utils.runOnMainThreadNowOrLater(() -> { + if (progress != null) { + progress.dismiss(); + } + new WebViewDialog(getContext(), htmlDialog).show(); + }); + } + + public ReVancedAboutPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + public ReVancedAboutPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + public ReVancedAboutPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + public ReVancedAboutPreference(Context context) { + super(context); + } +} + +/** + * Displays html content as a dialog. Any links a user taps on are opened in an external browser. + */ +class WebViewDialog extends Dialog { + + private final String htmlContent; + + public WebViewDialog(@NonNull Context context, @NonNull String htmlContent) { + super(context); + this.htmlContent = htmlContent; + } + + // JS required to hide any broken images. No remote javascript is ever loaded. + @SuppressLint("SetJavaScriptEnabled") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + + WebView webView = new WebView(getContext()); + webView.getSettings().setJavaScriptEnabled(true); + webView.setWebViewClient(new OpenLinksExternallyWebClient()); + webView.loadDataWithBaseURL(null, htmlContent, "text/html", "utf-8", null); + + setContentView(webView); + } + + private class OpenLinksExternallyWebClient extends WebViewClient { + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + getContext().startActivity(intent); + } catch (Exception ex) { + Logger.printException(() -> "Open link failure", ex); + } + // Dismiss the about dialog using a delay, + // otherwise without a delay the UI looks hectic with the dialog dismissing + // to show the settings while simultaneously a web browser is opening. + Utils.runOnMainThreadDelayed(WebViewDialog.this::dismiss, 500); + return true; + } + } +} + +class ReVancedSocialLink { + final boolean preferred; + final String name; + final String url; + + ReVancedSocialLink(JSONObject json) throws JSONException { + this(json.getBoolean("preferred"), + json.getString("name"), + json.getString("url") + ); + } + + ReVancedSocialLink(boolean preferred, String name, String url) { + this.preferred = preferred; + this.name = name; + this.url = url; + } + + @NonNull + @Override + public String toString() { + return "ReVancedSocialLink{" + + "preferred=" + preferred + + ", name='" + name + '\'' + + ", url='" + url + '\'' + + '}'; + } +} + +class SocialLinksRoutes { + /** + * Links to use if fetch links api call fails. + */ + private static final ReVancedSocialLink[] NO_CONNECTION_STATIC_LINKS = { + new ReVancedSocialLink(true, "ReVanced.app", "https://revanced.app") + }; + + private static final String SOCIAL_LINKS_PROVIDER = "https://api.revanced.app/v2"; + private static final Route.CompiledRoute GET_SOCIAL = new Route(GET, "/socials").compile(); + + @Nullable + private static volatile ReVancedSocialLink[] fetchedLinks; + + static boolean hasFetchedLinks() { + return fetchedLinks != null; + } + + static ReVancedSocialLink[] fetchSocialLinks() { + try { + if (hasFetchedLinks()) return fetchedLinks; + + // Check if there is no internet connection. + if (!Utils.isNetworkConnected()) return NO_CONNECTION_STATIC_LINKS; + + HttpURLConnection connection = Requester.getConnectionFromCompiledRoute(SOCIAL_LINKS_PROVIDER, GET_SOCIAL); + connection.setConnectTimeout(5000); + connection.setReadTimeout(5000); + Logger.printDebug(() -> "Fetching social links from: " + connection.getURL()); + + // Do not show an exception toast if the server is down + final int responseCode = connection.getResponseCode(); + if (responseCode != 200) { + Logger.printDebug(() -> "Failed to get social links. Response code: " + responseCode); + return NO_CONNECTION_STATIC_LINKS; + } + + JSONObject json = Requester.parseJSONObjectAndDisconnect(connection); + JSONArray socials = json.getJSONArray("socials"); + + List links = new ArrayList<>(); + for (int i = 0, length = socials.length(); i < length; i++) { + ReVancedSocialLink link = new ReVancedSocialLink(socials.getJSONObject(i)); + links.add(link); + } + Logger.printDebug(() -> "links: " + links); + + return fetchedLinks = links.toArray(new ReVancedSocialLink[0]); + + } catch (SocketTimeoutException ex) { + Logger.printInfo(() -> "Could not fetch social links", ex); // No toast. + } catch (JSONException ex) { + Logger.printException(() -> "Could not parse about information", ex); + } catch (Exception ex) { + Logger.printException(() -> "Failed to get about information", ex); + } + + return NO_CONNECTION_STATIC_LINKS; + } +} diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/preference/ResettableEditTextPreference.java b/app/src/main/java/app/revanced/integrations/shared/settings/preference/ResettableEditTextPreference.java index 804b51c4..4cf1f277 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/preference/ResettableEditTextPreference.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/preference/ResettableEditTextPreference.java @@ -14,7 +14,7 @@ import java.util.Objects; import static app.revanced.integrations.shared.StringRef.str; -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "deprecation"}) public class ResettableEditTextPreference extends EditTextPreference { public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { @@ -33,7 +33,7 @@ public class ResettableEditTextPreference extends EditTextPreference { @Override protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { super.onPrepareDialogBuilder(builder); - Setting setting = Setting.getSettingFromPath(getKey()); + Setting setting = Setting.getSettingFromPath(getKey()); if (setting != null) { builder.setNeutralButton(str("revanced_settings_reset"), null); } @@ -50,7 +50,7 @@ public class ResettableEditTextPreference extends EditTextPreference { } button.setOnClickListener(v -> { try { - Setting setting = Objects.requireNonNull(Setting.getSettingFromPath(getKey())); + Setting setting = Objects.requireNonNull(Setting.getSettingFromPath(getKey())); String defaultStringValue = setting.defaultValue.toString(); EditText editText = getEditText(); editText.setText(defaultStringValue); 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 0faa46b1..0cc8061c 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/ThemeHelper.java +++ b/app/src/main/java/app/revanced/integrations/youtube/ThemeHelper.java @@ -1,14 +1,23 @@ package app.revanced.integrations.youtube; import android.app.Activity; +import android.graphics.Color; + +import androidx.annotation.Nullable; + import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.Utils; public class ThemeHelper { + @Nullable + private static Integer darkThemeColor, lightThemeColor; private static int themeValue; - public static void setTheme(Object value) { - final int newOrdinalValue = ((Enum) value).ordinal(); + /** + * Injection point. + */ + public static void setTheme(Enum value) { + final int newOrdinalValue = value.ordinal(); if (themeValue != newOrdinalValue) { themeValue = newOrdinalValue; Logger.printDebug(() -> "Theme value: " + newOrdinalValue); @@ -26,4 +35,48 @@ public class ThemeHelper { activity.setTheme(Utils.getResourceIdentifier(theme, "style")); } + /** + * Injection point. + */ + private static String darkThemeResourceName() { + // Value is changed by Theme patch, if included. + return "@android:color/black"; + } + + /** + * @return The dark theme color as specified by the Theme patch (if included), + * or the Android color of black. + */ + public static int getDarkThemeColor() { + if (darkThemeColor == null) { + darkThemeColor = getColorInt(darkThemeResourceName()); + } + return darkThemeColor; + } + + /** + * Injection point. + */ + private static String lightThemeResourceName() { + // Value is changed by Theme patch, if included. + return "@android:color/white"; + } + + /** + * @return The light theme color as specified by the Theme patch (if included), + * or the Android color of white. + */ + public static int getLightThemeColor() { + if (lightThemeColor == null) { + lightThemeColor = getColorInt(lightThemeResourceName()); + } + return lightThemeColor; + } + + private static int getColorInt(String colorString) { + if (colorString.startsWith("#")) { + return Color.parseColor(colorString); + } + return Utils.getResourceColor(colorString); + } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch.java index db1e3755..eec599ec 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch.java @@ -61,7 +61,7 @@ public final class AnnouncementsPatch { return; } - var jsonString = Requester.parseInputStreamAndClose(connection.getInputStream(), false); + var jsonString = Requester.parseStringAndDisconnect(connection); // Parse the announcement. Fall-back to raw string if it fails. diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/requests/PlayerRoutes.java b/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/requests/PlayerRoutes.java index 67e69502..7909387f 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/requests/PlayerRoutes.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/requests/PlayerRoutes.java @@ -37,7 +37,7 @@ final class PlayerRoutes { JSONObject client = new JSONObject(); client.put("clientName", "ANDROID"); - client.put("clientVersion", Utils.getVersionName()); + client.put("clientVersion", Utils.getAppVersionName()); client.put("androidSdkVersion", 34); context.put("client", client); @@ -85,7 +85,7 @@ final class PlayerRoutes { connection.setRequestProperty( "User-Agent", "com.google.android.youtube/" + - Utils.getVersionName() + + Utils.getAppVersionName() + " (Linux; U; Android 12; GB) gzip" ); connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); diff --git a/app/src/main/java/app/revanced/integrations/youtube/requests/Requester.java b/app/src/main/java/app/revanced/integrations/youtube/requests/Requester.java index 5c109f98..ef409b52 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/requests/Requester.java +++ b/app/src/main/java/app/revanced/integrations/youtube/requests/Requester.java @@ -24,7 +24,10 @@ public class Requester { String url = apiUrl + route.getCompiledRoute(); HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod(route.getMethod().name()); - connection.setRequestProperty("User-Agent", System.getProperty("http.agent") + "; ReVanced/" + Utils.getVersionName()); + String agentString = System.getProperty("http.agent") + + "; ReVanced/" + Utils.getAppVersionName() + + " (" + Utils.getPatchesReleaseVersion() + ")"; + connection.setRequestProperty("User-Agent", agentString); return connection; } @@ -32,72 +35,79 @@ public class Requester { /** * Parse the {@link HttpURLConnection}, and closes the underlying InputStream. */ - public static String parseJson(HttpURLConnection connection) throws IOException { - return parseInputStreamAndClose(connection.getInputStream(), true); - } - - /** - * Parse the {@link HttpURLConnection}, close the underlying InputStream, and disconnect. - * - * Should only be used if other requests to the server are unlikely in the near future - * - * @see #parseJson(HttpURLConnection) - */ - public static String parseJsonAndDisconnect(HttpURLConnection connection) throws IOException { - String result = parseJson(connection); - connection.disconnect(); - return result; - } - - /** - * Parse the {@link HttpURLConnection}, and closes the underlying InputStream. - * - * @param stripNewLineCharacters if newline (\n) characters should be stripped from the InputStream - */ - public static String parseInputStreamAndClose(InputStream inputStream, boolean stripNewLineCharacters) throws IOException { + private static String parseInputStreamAndClose(InputStream inputStream) throws IOException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { StringBuilder jsonBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { jsonBuilder.append(line); - if (!stripNewLineCharacters) - jsonBuilder.append("\n"); + jsonBuilder.append("\n"); } return jsonBuilder.toString(); } } /** - * Parse the {@link HttpURLConnection}, and closes the underlying InputStream. + * Parse the {@link HttpURLConnection} response as a String. + * This does not close the url connection. If further requests to this host are unlikely + * in the near future, then instead use {@link #parseStringAndDisconnect(HttpURLConnection)}. */ - public static String parseErrorJson(HttpURLConnection connection) throws IOException { - return parseInputStreamAndClose(connection.getErrorStream(), false); + public static String parseString(HttpURLConnection connection) throws IOException { + return parseInputStreamAndClose(connection.getInputStream()); } /** - * Parse the {@link HttpURLConnection}, close the underlying InputStream, and disconnect. + * Parse the {@link HttpURLConnection} response as a String, and disconnect. * - * Should only be used if other requests to the server are unlikely in the near future + * Should only be used if other requests to the server in the near future are unlikely * - * @see #parseErrorJson(HttpURLConnection) + * @see #parseString(HttpURLConnection) */ - public static String parseErrorJsonAndDisconnect(HttpURLConnection connection) throws IOException { - String result = parseErrorJson(connection); + public static String parseStringAndDisconnect(HttpURLConnection connection) throws IOException { + String result = parseString(connection); connection.disconnect(); return result; } /** - * Parse the {@link HttpURLConnection}, and closes the underlying InputStream. + * Parse the {@link HttpURLConnection} error stream as a String. + * If the server sent no error response data, this returns an empty string. + */ + public static String parseErrorString(HttpURLConnection connection) throws IOException { + InputStream errorStream = connection.getErrorStream(); + if (errorStream == null) { + return ""; + } + return parseInputStreamAndClose(errorStream); + } + + /** + * Parse the {@link HttpURLConnection} error stream as a String, and disconnect. + * If the server sent no error response data, this returns an empty string. + * + * Should only be used if other requests to the server are unlikely in the near future. + * + * @see #parseErrorString(HttpURLConnection) + */ + public static String parseErrorStringAndDisconnect(HttpURLConnection connection) throws IOException { + String result = parseErrorString(connection); + connection.disconnect(); + return result; + } + + /** + * Parse the {@link HttpURLConnection} response into a JSONObject. + * This does not close the url connection. If further requests to this host are unlikely + * in the near future, then instead use {@link #parseJSONObjectAndDisconnect(HttpURLConnection)}. */ public static JSONObject parseJSONObject(HttpURLConnection connection) throws JSONException, IOException { - return new JSONObject(parseJson(connection)); + return new JSONObject(parseString(connection)); } /** * Parse the {@link HttpURLConnection}, close the underlying InputStream, and disconnect. * - * Should only be used if other requests to the server are unlikely in the near future + * Should only be used if other requests to the server in the near future are unlikely * * @see #parseJSONObject(HttpURLConnection) */ @@ -109,15 +119,17 @@ public class Requester { /** * Parse the {@link HttpURLConnection}, and closes the underlying InputStream. + * This does not close the url connection. If further requests to this host are unlikely + * in the near future, then instead use {@link #parseJSONArrayAndDisconnect(HttpURLConnection)}. */ public static JSONArray parseJSONArray(HttpURLConnection connection) throws JSONException, IOException { - return new JSONArray(parseJson(connection)); + return new JSONArray(parseString(connection)); } /** * Parse the {@link HttpURLConnection}, close the underlying InputStream, and disconnect. * - * Should only be used if other requests to the server are unlikely in the near future + * Should only be used if other requests to the server in the near future are unlikely * * @see #parseJSONArray(HttpURLConnection) */ diff --git a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java index 9b22aafc..bc729e47 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java +++ b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java @@ -1,7 +1,7 @@ package app.revanced.integrations.youtube.returnyoutubedislike.requests; -import static app.revanced.integrations.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeRoutes.getRYDConnectionFromRoute; import static app.revanced.integrations.shared.StringRef.str; +import static app.revanced.integrations.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeRoutes.getRYDConnectionFromRoute; import android.util.Base64; @@ -22,11 +22,11 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Objects; +import app.revanced.integrations.shared.Logger; +import app.revanced.integrations.shared.Utils; import app.revanced.integrations.youtube.requests.Requester; import app.revanced.integrations.youtube.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.integrations.youtube.settings.Settings; -import app.revanced.integrations.shared.Logger; -import app.revanced.integrations.shared.Utils; public class ReturnYouTubeDislikeApi { /** @@ -383,7 +383,7 @@ public class ReturnYouTubeDislikeApi { } // Something went wrong, might as well disconnect. - String response = Requester.parseJsonAndDisconnect(connection); + String response = Requester.parseStringAndDisconnect(connection); Logger.printInfo(() -> "Failed to confirm registration for user: " + userId + " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "''"); handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), @@ -505,7 +505,7 @@ public class ReturnYouTubeDislikeApi { } // Something went wrong, might as well disconnect. - String response = Requester.parseJsonAndDisconnect(connection); + String response = Requester.parseStringAndDisconnect(connection); Logger.printInfo(() -> "Failed to confirm vote for video: " + videoId + " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "'"); handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/AlternativeThumbnailsAboutDeArrowPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/AlternativeThumbnailsAboutDeArrowPreference.java index b631e2e1..f0153e7e 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/AlternativeThumbnailsAboutDeArrowPreference.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/AlternativeThumbnailsAboutDeArrowPreference.java @@ -9,7 +9,7 @@ import android.util.AttributeSet; /** * Allows tapping the DeArrow about preference to open the DeArrow website. */ -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "deprecation"}) public class AlternativeThumbnailsAboutDeArrowPreference extends Preference { { setOnPreferenceClickListener(pref -> { diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedYouTubeAboutPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedYouTubeAboutPreference.java new file mode 100644 index 00000000..33601651 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedYouTubeAboutPreference.java @@ -0,0 +1,32 @@ +package app.revanced.integrations.youtube.settings.preference; + +import android.content.Context; +import android.util.AttributeSet; + +import app.revanced.integrations.shared.settings.preference.ReVancedAboutPreference; +import app.revanced.integrations.youtube.ThemeHelper; + +@SuppressWarnings("unused") +public class ReVancedYouTubeAboutPreference extends ReVancedAboutPreference { + + public int getLightColor() { + return ThemeHelper.getLightThemeColor(); + } + + public int getDarkColor() { + return ThemeHelper.getDarkThemeColor(); + } + + public ReVancedYouTubeAboutPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + public ReVancedYouTubeAboutPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + public ReVancedYouTubeAboutPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + public ReVancedYouTubeAboutPreference(Context context) { + super(context); + } +} diff --git a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/requests/SBRequester.java b/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/requests/SBRequester.java index 020fd038..9e25e9f6 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/requests/SBRequester.java +++ b/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/requests/SBRequester.java @@ -159,13 +159,13 @@ public class SBRequester { messageToToast = str("revanced_sb_submit_failed_duplicate"); break; case 403: - messageToToast = str("revanced_sb_submit_failed_forbidden", Requester.parseErrorJsonAndDisconnect(connection)); + messageToToast = str("revanced_sb_submit_failed_forbidden", Requester.parseErrorStringAndDisconnect(connection)); break; case 429: messageToToast = str("revanced_sb_submit_failed_rate_limit"); break; case 400: - messageToToast = str("revanced_sb_submit_failed_invalid", Requester.parseErrorJsonAndDisconnect(connection)); + messageToToast = str("revanced_sb_submit_failed_invalid", Requester.parseErrorStringAndDisconnect(connection)); break; default: messageToToast = str("revanced_sb_submit_failed_unknown_error", responseCode, connection.getResponseMessage()); @@ -223,7 +223,7 @@ public class SBRequester { break; case 403: Utils.showToastLong( - str("revanced_sb_vote_failed_forbidden", Requester.parseErrorJsonAndDisconnect(connection))); + str("revanced_sb_vote_failed_forbidden", Requester.parseErrorStringAndDisconnect(connection))); break; default: Utils.showToastLong( From 7cd0c6c3c17b8ff290c39c2fd0c74902bdf63cf1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 17 Apr 2024 16:04:27 +0000 Subject: [PATCH 41/51] chore(release): 1.8.0-dev.15 [skip ci] # [1.8.0-dev.15](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.14...v1.8.0-dev.15) (2024-04-17) ### Features * **YouTube:** Add 'About' preference to settings menu ([#608](https://github.com/ReVanced/revanced-integrations/issues/608)) ([b8f260e](https://github.com/ReVanced/revanced-integrations/commit/b8f260ebd3e7c2dc50a57cd060b76f2e0fc4a89c)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1140954..2edd275b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.15](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.14...v1.8.0-dev.15) (2024-04-17) + + +### Features + +* **YouTube:** Add 'About' preference to settings menu ([#608](https://github.com/ReVanced/revanced-integrations/issues/608)) ([b8f260e](https://github.com/ReVanced/revanced-integrations/commit/b8f260ebd3e7c2dc50a57cd060b76f2e0fc4a89c)) + # [1.8.0-dev.14](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.13...v1.8.0-dev.14) (2024-04-17) diff --git a/gradle.properties b/gradle.properties index 3512d0d9..d6eb471c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.14 +version = 1.8.0-dev.15 From ba308690cf83067d3ddd54622eebcbd14bc15ac8 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:35:58 +0400 Subject: [PATCH 42/51] fix(YouTube - Hide layout components): Hide horizontal tile shelves --- .../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 0f69f546..90ed3841 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 @@ -247,7 +247,8 @@ public final class LayoutComponentsFilter extends Filter { horizontalShelves = new StringFilterGroup( Settings.HIDE_HORIZONTAL_SHELVES, "horizontal_video_shelf.eml", - "horizontal_shelf.eml" + "horizontal_shelf.eml", + "horizontal_tile_shelf.eml" ); addPathCallbacks( From 4cacbf6f2ccd4c34b6c37e03a569b35a83d6354c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Apr 2024 08:39:17 +0000 Subject: [PATCH 43/51] chore(release): 1.8.0-dev.16 [skip ci] # [1.8.0-dev.16](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.15...v1.8.0-dev.16) (2024-04-18) ### Bug Fixes * **YouTube - Hide layout components:** Hide horizontal tile shelves ([ba30869](https://github.com/ReVanced/revanced-integrations/commit/ba308690cf83067d3ddd54622eebcbd14bc15ac8)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2edd275b..4dd98cd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.16](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.15...v1.8.0-dev.16) (2024-04-18) + + +### Bug Fixes + +* **YouTube - Hide layout components:** Hide horizontal tile shelves ([ba30869](https://github.com/ReVanced/revanced-integrations/commit/ba308690cf83067d3ddd54622eebcbd14bc15ac8)) + # [1.8.0-dev.15](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.14...v1.8.0-dev.15) (2024-04-17) diff --git a/gradle.properties b/gradle.properties index d6eb471c..29e32191 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.15 +version = 1.8.0-dev.16 From 3ce100ced57d7099c2209d9a955484f1e7d418e0 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:57:17 +0400 Subject: [PATCH 44/51] fix(YouTube - Hide Shorts components): Hide paid promotion label --- .../youtube/patches/components/ShortsFilter.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) 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 c03d4518..371fde56 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 @@ -20,7 +20,7 @@ public final class ShortsFilter extends Filter { private final static String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml"; /** - * For subscribe button that appears in the channel bar. + * For paid promotion label and subscribe button that appears in the channel bar. */ private final static String REEL_METAPANEL_PATH = "reel_metapanel.eml"; @@ -29,6 +29,7 @@ public final class ShortsFilter extends Filter { private final StringFilterGroup subscribeButton; private final StringFilterGroup joinButton; + private final StringFilterGroup paidPromotionButton; private final StringFilterGroup shelfHeader; private final StringFilterGroup suggestedAction; @@ -117,6 +118,11 @@ public final class ShortsFilter extends Filter { "subscribe_button" ); + paidPromotionButton = new StringFilterGroup( + Settings.HIDE_PAID_PROMOTION_LABEL, + "reel_player_disclosure.eml" + ); + actionBar = new StringFilterGroup( null, "shorts_action_bar" @@ -129,8 +135,8 @@ public final class ShortsFilter extends Filter { addPathCallbacks( shortsCompactFeedVideoPath, suggestedAction, actionBar, joinButton, subscribeButton, - pausedOverlayButtons, channelBar, fullVideoLinkLabel, videoTitle, reelSoundMetadata, - soundButton, infoPanel + paidPromotionButton, pausedOverlayButtons, channelBar, fullVideoLinkLabel, videoTitle, + reelSoundMetadata, soundButton, infoPanel ); // @@ -196,7 +202,7 @@ 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) { - if (matchedGroup == subscribeButton || matchedGroup == joinButton) { + if (matchedGroup == subscribeButton || matchedGroup == joinButton || matchedGroup == paidPromotionButton) { // Selectively filter to avoid false positive filtering of other subscribe/join buttons. if (path.startsWith(REEL_CHANNEL_BAR_PATH) || path.startsWith(REEL_METAPANEL_PATH)) { return super.isFiltered( From bcc9126107cdd533fc0d4b888d00dbd6f3297e50 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Apr 2024 11:00:38 +0000 Subject: [PATCH 45/51] chore(release): 1.8.0-dev.17 [skip ci] # [1.8.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.16...v1.8.0-dev.17) (2024-04-18) ### Bug Fixes * **YouTube - Hide Shorts components:** Hide paid promotion label ([3ce100c](https://github.com/ReVanced/revanced-integrations/commit/3ce100ced57d7099c2209d9a955484f1e7d418e0)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dd98cd0..1a70810d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.16...v1.8.0-dev.17) (2024-04-18) + + +### Bug Fixes + +* **YouTube - Hide Shorts components:** Hide paid promotion label ([3ce100c](https://github.com/ReVanced/revanced-integrations/commit/3ce100ced57d7099c2209d9a955484f1e7d418e0)) + # [1.8.0-dev.16](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.15...v1.8.0-dev.16) (2024-04-18) diff --git a/gradle.properties b/gradle.properties index 29e32191..c5f7ec5d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.16 +version = 1.8.0-dev.17 From 786ac9d2b71886964454fcb748e656d1beed1964 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:18:52 +0400 Subject: [PATCH 46/51] fix(YouTube - Spoof device dimensions): Warn about potential performance issues (#617) --- .../app/revanced/integrations/youtube/settings/Settings.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 98770fea..505ad451 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 @@ -223,7 +223,8 @@ public class Settings extends BaseSettings { parent(SPOOF_SIGNATURE)); public static final BooleanSetting SPOOF_STORYBOARD_RENDERER = new BooleanSetting("revanced_spoof_storyboard", TRUE, true, parent(SPOOF_SIGNATURE)); - public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true); + public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true, + "revanced_spoof_device_dimensions_user_dialog_message"); public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE); public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE); @Deprecated From 3ff5dcd05fbab3aadcadb46f7f0205e1f4d75a4a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Apr 2024 13:21:46 +0000 Subject: [PATCH 47/51] chore(release): 1.8.0-dev.18 [skip ci] # [1.8.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.17...v1.8.0-dev.18) (2024-04-18) ### Bug Fixes * **YouTube - Spoof device dimensions:** Warn about potential performance issues ([#617](https://github.com/ReVanced/revanced-integrations/issues/617)) ([786ac9d](https://github.com/ReVanced/revanced-integrations/commit/786ac9d2b71886964454fcb748e656d1beed1964)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a70810d..3d5d81c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.17...v1.8.0-dev.18) (2024-04-18) + + +### Bug Fixes + +* **YouTube - Spoof device dimensions:** Warn about potential performance issues ([#617](https://github.com/ReVanced/revanced-integrations/issues/617)) ([786ac9d](https://github.com/ReVanced/revanced-integrations/commit/786ac9d2b71886964454fcb748e656d1beed1964)) + # [1.8.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.16...v1.8.0-dev.17) (2024-04-18) diff --git a/gradle.properties b/gradle.properties index c5f7ec5d..537810ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.17 +version = 1.8.0-dev.18 From c3bfa77d62b15dedfed8f697583f2f0805f0c2c1 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:40:26 +0400 Subject: [PATCH 48/51] fix(YouTube - Hide keyword content): Correctly hide content in the subscription tab --- .../youtube/patches/components/KeywordContentFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 95b9f466..acb9c9b2 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 @@ -118,6 +118,7 @@ final class KeywordContentFilter extends Filter { // 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(); @@ -125,7 +126,7 @@ final class KeywordContentFilter extends Filter { // 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_SUBSCRIPTIONS_BUTTON.get(); + final boolean hideSubscriptions = Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS.get(); if (!hideHome && !hideSubscriptions) { return false; } From efd03012d04a8b0fc358faa73a1b58721e3fd29c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Apr 2024 18:43:48 +0000 Subject: [PATCH 49/51] chore(release): 1.8.0-dev.19 [skip ci] # [1.8.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.18...v1.8.0-dev.19) (2024-04-18) ### Bug Fixes * **YouTube - Hide keyword content:** Correctly hide content in the subscription tab ([c3bfa77](https://github.com/ReVanced/revanced-integrations/commit/c3bfa77d62b15dedfed8f697583f2f0805f0c2c1)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d5d81c3..6c9554d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.18...v1.8.0-dev.19) (2024-04-18) + + +### Bug Fixes + +* **YouTube - Hide keyword content:** Correctly hide content in the subscription tab ([c3bfa77](https://github.com/ReVanced/revanced-integrations/commit/c3bfa77d62b15dedfed8f697583f2f0805f0c2c1)) + # [1.8.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.17...v1.8.0-dev.18) (2024-04-18) diff --git a/gradle.properties b/gradle.properties index 537810ba..511bbbf0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.18 +version = 1.8.0-dev.19 From 1c8e2b29410048a352cb6aad3dd02773459f91a0 Mon Sep 17 00:00:00 2001 From: MarcaD <152095496+MarcaDian@users.noreply.github.com> Date: Sun, 21 Apr 2024 02:59:23 +0300 Subject: [PATCH 50/51] feat(YouTube - Swipe controls): Save and restore brightness and add auto-brightness toggle (#610) Co-authored-by: oSumAtrIX --- .../youtube/settings/Settings.java | 6 +-- .../SwipeControlsConfigurationProvider.kt | 12 +++++ .../SwipeControlsHostActivity.kt | 27 +++++++---- .../controller/ScreenBrightnessController.kt | 46 ++++++++++--------- .../core/VolumeAndBrightnessScroller.kt | 9 +++- .../views/SwipeControlsOverlayLayout.kt | 10 ++-- 6 files changed, 72 insertions(+), 38 deletions(-) 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 505ad451..b74098c7 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 @@ -249,9 +249,9 @@ public class Settings extends BaseSettings { parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); public static final LongSetting SWIPE_OVERLAY_TIMEOUT = new LongSetting("revanced_swipe_overlay_timeout", 500L, true, parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); - public static final BooleanSetting SWIPE_SAVE_AND_RESTORE_BRIGHTNESS = new BooleanSetting("revanced_swipe_save_and_restore_brightness", TRUE, true, - parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); - + public static final BooleanSetting SWIPE_SAVE_AND_RESTORE_BRIGHTNESS = new BooleanSetting("revanced_swipe_save_and_restore_brightness", TRUE, true, parent(SWIPE_BRIGHTNESS)); + public static final FloatSetting SWIPE_BRIGHTNESS_VALUE = new FloatSetting("revanced_swipe_brightness_value", -1f); + public static final BooleanSetting SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS = new BooleanSetting("revanced_swipe_lowest_value_enable_auto_brightness", FALSE, true, parent(SWIPE_BRIGHTNESS)); // Debugging /** * When enabled, share the debug logs with care. diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt index 0e2d7997..893ccd57 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt @@ -104,5 +104,17 @@ class SwipeControlsConfigurationProvider( val shouldSaveAndRestoreBrightness: Boolean get() = Settings.SWIPE_SAVE_AND_RESTORE_BRIGHTNESS.get() + /** + * should auto-brightness be enabled at the lowest value of the brightness gesture + */ + val shouldLowestValueEnableAutoBrightness: Boolean + get() = Settings.SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS.get() + + /** + * variable that stores the brightness gesture value in the settings + */ + var savedScreenBrightnessValue: Float + get() = Settings.SWIPE_BRIGHTNESS_VALUE.get() + set(value) = Settings.SWIPE_BRIGHTNESS_VALUE.save(value) //endregion } diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsHostActivity.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsHostActivity.kt index e6f233e8..55236314 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsHostActivity.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/SwipeControlsHostActivity.kt @@ -166,20 +166,31 @@ class SwipeControlsHostActivity : Activity() { contentRoot.addView(overlay) } + // Flag that indicates whether the brightness has been saved and restored default brightness + private var isBrightnessSaved = false + /** * called when the player type changes * * @param type the new player type */ private fun onPlayerTypeChanged(type: PlayerType) { - if (config.shouldSaveAndRestoreBrightness) { - when (type) { - PlayerType.WATCH_WHILE_FULLSCREEN -> screen?.restore() - else -> { - screen?.save() - screen?.restoreDefaultBrightness() - } + when { + // If saving and restoring brightness is enabled, and the player type is WATCH_WHILE_FULLSCREEN, + // and brightness has already been saved, then restore the screen brightness + config.shouldSaveAndRestoreBrightness && type == PlayerType.WATCH_WHILE_FULLSCREEN && isBrightnessSaved -> { + screen?.restore() + isBrightnessSaved = false } + // If saving and restoring brightness is enabled, and brightness has not been saved, + // then save the current screen state, restore default brightness, and mark brightness as saved + config.shouldSaveAndRestoreBrightness && !isBrightnessSaved -> { + screen?.save() + screen?.restoreDefaultBrightness() + isBrightnessSaved = true + } + // If saving and restoring brightness is disabled, simply keep the default brightness + else -> screen?.restoreDefaultBrightness() } } @@ -222,4 +233,4 @@ class SwipeControlsHostActivity : Activity() { var currentHost: WeakReference = WeakReference(null) private set } -} +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/ScreenBrightnessController.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/ScreenBrightnessController.kt index 1cf282e8..08e27004 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/ScreenBrightnessController.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/ScreenBrightnessController.kt @@ -1,21 +1,17 @@ package app.revanced.integrations.youtube.swipecontrols.controller -import android.app.Activity import android.view.WindowManager +import app.revanced.integrations.youtube.swipecontrols.SwipeControlsHostActivity import app.revanced.integrations.youtube.swipecontrols.misc.clamp /** * controller to adjust the screen brightness level * - * @param host the host activity of which the brightness is adjusted + * @param host the host activity of which the brightness is adjusted, the main controller instance */ class ScreenBrightnessController( - private val host: Activity, + val host: SwipeControlsHostActivity, ) { - /** - * screen brightness saved by [save] - */ - private var savedScreenBrightness: Float? = null /** * the current screen brightness in percent, ranging from 0.0 to 100.0 @@ -26,13 +22,6 @@ class ScreenBrightnessController( rawScreenBrightness = (value.toFloat() / 100f).clamp(0f, 1f) } - /** - * restore the screen brightness to the default device brightness - */ - fun restoreDefaultBrightness() { - rawScreenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE - } - /** * is the screen brightness set to device- default? */ @@ -40,22 +29,35 @@ class ScreenBrightnessController( get() = (rawScreenBrightness == WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE) /** - * save the current screen brightness, to be brought back using [restore] + * restore the screen brightness to the default device brightness + */ + fun restoreDefaultBrightness() { + rawScreenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE + } + + // Flag that indicates whether the brightness has been restored + private var isBrightnessRestored = false + + /** + * save the current screen brightness into settings, to be brought back using [restore] */ fun save() { - if (savedScreenBrightness == null) { - savedScreenBrightness = rawScreenBrightness + if (isBrightnessRestored) { + // Saves the current screen brightness value into settings + host.config.savedScreenBrightnessValue = rawScreenBrightness + // Reset the flag + isBrightnessRestored = false } } /** - * restore the screen brightness saved using [save] + * restore the screen brightness from settings saved using [save] */ fun restore() { - savedScreenBrightness?.let { - rawScreenBrightness = it - } - savedScreenBrightness = null + // Restores the screen brightness value from the saved settings + rawScreenBrightness = host.config.savedScreenBrightnessValue + // Mark that brightness has been restored + isBrightnessRestored = true } /** diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/gesture/core/VolumeAndBrightnessScroller.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/gesture/core/VolumeAndBrightnessScroller.kt index dec14b81..f15478ec 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/gesture/core/VolumeAndBrightnessScroller.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/gesture/core/VolumeAndBrightnessScroller.kt @@ -77,12 +77,17 @@ class VolumeAndBrightnessScrollerImpl( ), ) { _, _, direction -> screenController?.run { - if (screenBrightness > 0 || direction > 0) { + val shouldAdjustBrightness = if (host.config.shouldLowestValueEnableAutoBrightness) { + screenBrightness > 0 || direction > 0 + } else { + screenBrightness >= 0 || direction >= 0 + } + + if (shouldAdjustBrightness) { screenBrightness += direction } else { restoreDefaultBrightness() } - overlayController.onBrightnessChanged(screenBrightness) } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt index dbe2434f..f68fcda1 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt @@ -11,6 +11,7 @@ import android.view.View import android.view.ViewGroup import android.widget.RelativeLayout import android.widget.TextView +import app.revanced.integrations.shared.StringRef.str import app.revanced.integrations.shared.Utils import app.revanced.integrations.youtube.swipecontrols.SwipeControlsConfigurationProvider import app.revanced.integrations.youtube.swipecontrols.misc.SwipeControlsOverlay @@ -122,10 +123,13 @@ class SwipeControlsOverlayLayout( } override fun onBrightnessChanged(brightness: Double) { - if (brightness > 0) { + if (config.shouldLowestValueEnableAutoBrightness && brightness <= 0) { + showFeedbackView( + str("revanced_swipe_lowest_value_enable_auto_brightness_overlay_text"), + autoBrightnessIcon, + ) + } else if (brightness >= 0) { showFeedbackView("${round(brightness).toInt()}%", manualBrightnessIcon) - } else { - showFeedbackView("AUTO", autoBrightnessIcon) } } From d06b94cbe604eee1a6d94c1b918c8b521703e106 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 21 Apr 2024 00:02:28 +0000 Subject: [PATCH 51/51] chore(release): 1.8.0-dev.20 [skip ci] # [1.8.0-dev.20](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.19...v1.8.0-dev.20) (2024-04-21) ### Features * **YouTube - Swipe controls:** Save and restore brightness and add auto-brightness toggle ([#610](https://github.com/ReVanced/revanced-integrations/issues/610)) ([1c8e2b2](https://github.com/ReVanced/revanced-integrations/commit/1c8e2b29410048a352cb6aad3dd02773459f91a0)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c9554d8..f0e4bcfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.8.0-dev.20](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.19...v1.8.0-dev.20) (2024-04-21) + + +### Features + +* **YouTube - Swipe controls:** Save and restore brightness and add auto-brightness toggle ([#610](https://github.com/ReVanced/revanced-integrations/issues/610)) ([1c8e2b2](https://github.com/ReVanced/revanced-integrations/commit/1c8e2b29410048a352cb6aad3dd02773459f91a0)) + # [1.8.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v1.8.0-dev.18...v1.8.0-dev.19) (2024-04-18) diff --git a/gradle.properties b/gradle.properties index 511bbbf0..d049f495 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.8.0-dev.19 +version = 1.8.0-dev.20