From 6b00f90fb7561d59de59d76d43fff8c1d057dce6 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:58:17 +0200 Subject: [PATCH 01/21] fix(YouTube): Rename `Restore old seekbar thumbnails` and `Restore old quality menu` (#510) --- .../EnableOldSeekbarThumbnailsPatch.java | 9 - .../RestoreOldSeekbarThumbnailsPatch.java | 10 ++ .../PlaybackSpeedMenuFilterPatch.java | 6 +- .../VideoQualityMenuFilterPatch.java | 7 +- ...a => RestoreOldVideoQualityMenuPatch.java} | 7 +- .../integrations/settings/SettingsEnum.java | 164 +++++++++--------- 6 files changed, 109 insertions(+), 94 deletions(-) delete mode 100644 app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java create mode 100644 app/src/main/java/app/revanced/integrations/patches/RestoreOldSeekbarThumbnailsPatch.java rename app/src/main/java/app/revanced/integrations/patches/playback/quality/{OldVideoQualityMenuPatch.java => RestoreOldVideoQualityMenuPatch.java} (91%) diff --git a/app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java b/app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java deleted file mode 100644 index a24ba796..00000000 --- a/app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.integrations.patches; - -import app.revanced.integrations.settings.SettingsEnum; - -public final class EnableOldSeekbarThumbnailsPatch { - public static boolean enableOldSeekbarThumbnails() { - return !SettingsEnum.ENABLE_OLD_SEEKBAR_THUMBNAILS.getBoolean(); - } -} diff --git a/app/src/main/java/app/revanced/integrations/patches/RestoreOldSeekbarThumbnailsPatch.java b/app/src/main/java/app/revanced/integrations/patches/RestoreOldSeekbarThumbnailsPatch.java new file mode 100644 index 00000000..c5bfeb80 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/RestoreOldSeekbarThumbnailsPatch.java @@ -0,0 +1,10 @@ +package app.revanced.integrations.patches; + +import app.revanced.integrations.settings.SettingsEnum; + +@SuppressWarnings("unused") +public final class RestoreOldSeekbarThumbnailsPatch { + public static boolean useFullscreenSeekbarThumbnails() { + return !SettingsEnum.RESTORE_OLD_SEEKBAR_THUMBNAILS.getBoolean(); + } +} diff --git a/app/src/main/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java index 00b11af3..0f4b9bcf 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java @@ -2,7 +2,11 @@ package app.revanced.integrations.patches.components; import androidx.annotation.Nullable; -// Abuse LithoFilter for CustomPlaybackSpeedPatch. +import app.revanced.integrations.patches.playback.speed.CustomPlaybackSpeedPatch; + +/** + * Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}. + */ public final class PlaybackSpeedMenuFilterPatch extends Filter { // Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread. public static volatile boolean isPlaybackSpeedMenuVisible; diff --git a/app/src/main/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java index 8b5d9643..d09f4ddc 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java @@ -2,16 +2,19 @@ package app.revanced.integrations.patches.components; import androidx.annotation.Nullable; +import app.revanced.integrations.patches.playback.quality.RestoreOldVideoQualityMenuPatch; import app.revanced.integrations.settings.SettingsEnum; -// Abuse LithoFilter for OldVideoQualityMenuPatch. +/** + * Abuse LithoFilter for {@link RestoreOldVideoQualityMenuPatch}. + */ public final class VideoQualityMenuFilterPatch extends Filter { // Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread. public static volatile boolean isVideoQualityMenuVisible; public VideoQualityMenuFilterPatch() { pathFilterGroupList.addAll(new StringFilterGroup( - SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU, + SettingsEnum.RESTORE_OLD_VIDEO_QUALITY_MENU, "quick_quality_sheet_content.eml-js" )); } diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java similarity index 91% rename from app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java rename to app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java index 47053674..92a66ca2 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java @@ -14,13 +14,14 @@ import app.revanced.integrations.utils.LogHelper; * Two methods are required, because the quality menu is a RecyclerView in the new YouTube version * and a ListView in the old one. */ -public final class OldVideoQualityMenuPatch { +@SuppressWarnings("unused") +public final class RestoreOldVideoQualityMenuPatch { /** * Injection point. */ public static void onFlyoutMenuCreate(RecyclerView recyclerView) { - if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; + if (!SettingsEnum.RESTORE_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; recyclerView.getViewTreeObserver().addOnDrawListener(() -> { try { @@ -45,7 +46,7 @@ public final class OldVideoQualityMenuPatch { * Injection point. Only used if spoofing to an old app version. */ public static void showOldVideoQualityMenu(final ListView listView) { - if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; + if (!SettingsEnum.RESTORE_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { @Override diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index e6fda854..53a911e5 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -32,7 +32,8 @@ public enum SettingsEnum { // Video HDR_AUTO_BRIGHTNESS("revanced_hdr_auto_brightness", BOOLEAN, TRUE), - SHOW_OLD_VIDEO_QUALITY_MENU("revanced_show_old_video_quality_menu", BOOLEAN, TRUE), + @Deprecated SHOW_OLD_VIDEO_QUALITY_MENU("revanced_show_old_video_quality_menu", BOOLEAN, TRUE), + RESTORE_OLD_VIDEO_QUALITY_MENU("revanced_restore_old_video_quality_menu", BOOLEAN, TRUE), REMEMBER_VIDEO_QUALITY_LAST_SELECTED("revanced_remember_video_quality_last_selected", BOOLEAN, TRUE), VIDEO_QUALITY_DEFAULT_WIFI("revanced_video_quality_default_wifi", INTEGER, -2), VIDEO_QUALITY_DEFAULT_MOBILE("revanced_video_quality_default_mobile", INTEGER, -2), @@ -44,41 +45,106 @@ public enum SettingsEnum { // Ads HIDE_BUTTONED_ADS("revanced_hide_buttoned_ads", BOOLEAN, TRUE), HIDE_GENERAL_ADS("revanced_hide_general_ads", BOOLEAN, TRUE), + HIDE_GET_PREMIUM("revanced_hide_get_premium", BOOLEAN, TRUE), HIDE_HIDE_LATEST_POSTS("revanced_hide_latest_posts_ads", BOOLEAN, TRUE), + HIDE_MERCHANDISE_BANNERS("revanced_hide_merchandise_banners", BOOLEAN, TRUE), HIDE_PAID_CONTENT("revanced_hide_paid_content_ads", BOOLEAN, TRUE), + HIDE_PRODUCTS_BANNER("revanced_hide_products_banner", BOOLEAN, TRUE), HIDE_SELF_SPONSOR("revanced_hide_self_sponsor_ads", BOOLEAN, TRUE), HIDE_VIDEO_ADS("revanced_hide_video_ads", BOOLEAN, TRUE, true), - CUSTOM_FILTER("revanced_custom_filter", BOOLEAN, FALSE), - CUSTOM_FILTER_STRINGS("revanced_custom_filter_strings", STRING, "", true, parents(CUSTOM_FILTER)), + HIDE_WEB_SEARCH_RESULTS("revanced_hide_web_search_results", BOOLEAN, TRUE), // Layout + ALT_THUMBNAIL("revanced_alt_thumbnail", BOOLEAN, FALSE), + ALT_THUMBNAIL_TYPE("revanced_alt_thumbnail_type", INTEGER, 2, parents(ALT_THUMBNAIL)), + ALT_THUMBNAIL_FAST_QUALITY("revanced_alt_thumbnail_fast_quality", BOOLEAN, FALSE, parents(ALT_THUMBNAIL)), + CUSTOM_FILTER("revanced_custom_filter", BOOLEAN, FALSE), + CUSTOM_FILTER_STRINGS("revanced_custom_filter_strings", STRING, "", true, parents(CUSTOM_FILTER)), + DISABLE_FULLSCREEN_AMBIENT_MODE("revanced_disable_fullscreen_ambient_mode", BOOLEAN, TRUE, true), + DISABLE_RESUMING_SHORTS_PLAYER("revanced_disable_resuming_shorts_player", BOOLEAN, FALSE), + DISABLE_SUGGESTED_VIDEO_END_SCREEN("revanced_disable_suggested_video_end_screen", BOOLEAN, TRUE), + GRADIENT_LOADING_SCREEN("revanced_gradient_loading_screen", BOOLEAN, FALSE), + HIDE_ALBUM_CARDS("revanced_hide_album_cards", BOOLEAN, FALSE, true), + HIDE_ARTIST_CARDS("revanced_hide_artist_cards", BOOLEAN, FALSE), + HIDE_AUTOPLAY_BUTTON("revanced_hide_autoplay_button", BOOLEAN, TRUE, true), + HIDE_BREAKING_NEWS("revanced_hide_breaking_news", BOOLEAN, TRUE, true), + HIDE_CAPTIONS_BUTTON("revanced_hide_captions_button", BOOLEAN, FALSE), + HIDE_CAST_BUTTON("revanced_hide_cast_button", BOOLEAN, TRUE, true), HIDE_CHANNEL_BAR("revanced_hide_channel_bar", BOOLEAN, FALSE), HIDE_CHANNEL_MEMBER_SHELF("revanced_hide_channel_member_shelf", BOOLEAN, TRUE), - HIDE_EXPANDABLE_CHIP("revanced_hide_expandable_chip", BOOLEAN, TRUE), - HIDE_VIDEO_QUALITY_MENU_FOOTER("revanced_hide_video_quality_menu_footer", BOOLEAN, TRUE), HIDE_CHAPTERS("revanced_hide_chapters", BOOLEAN, TRUE), + HIDE_CHIPS_SHELF("revanced_hide_chips_shelf", BOOLEAN, TRUE), + HIDE_COMMENTS_SECTION("revanced_hide_comments_section", BOOLEAN, FALSE, true), HIDE_COMMUNITY_GUIDELINES("revanced_hide_community_guidelines", BOOLEAN, TRUE), HIDE_COMMUNITY_POSTS("revanced_hide_community_posts", BOOLEAN, FALSE), HIDE_COMPACT_BANNER("revanced_hide_compact_banner", BOOLEAN, TRUE), + HIDE_CREATE_BUTTON("revanced_hide_create_button", BOOLEAN, TRUE, true), + HIDE_CROWDFUNDING_BOX("revanced_hide_crowdfunding_box", BOOLEAN, FALSE, true), + HIDE_EMAIL_ADDRESS("revanced_hide_email_address", BOOLEAN, FALSE), HIDE_EMERGENCY_BOX("revanced_hide_emergency_box", BOOLEAN, TRUE), + HIDE_ENDSCREEN_CARDS("revanced_hide_endscreen_cards", BOOLEAN, TRUE), + HIDE_EXPANDABLE_CHIP("revanced_hide_expandable_chip", BOOLEAN, TRUE), HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE), + HIDE_FILTER_BAR_FEED_IN_FEED("revanced_hide_filter_bar_feed_in_feed", BOOLEAN, FALSE, true), + HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS("revanced_hide_filter_bar_feed_in_related_videos", BOOLEAN, FALSE, true), + HIDE_FILTER_BAR_FEED_IN_SEARCH("revanced_hide_filter_bar_feed_in_search", BOOLEAN, FALSE, true), + HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", BOOLEAN, TRUE, true), + HIDE_FULLSCREEN_PANELS("revanced_hide_fullscreen_panels", BOOLEAN, TRUE, true), HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE), - HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), - HIDE_SEARCH_RESULT_SHELF_HEADER("revanced_hide_search_result_shelf_header", BOOLEAN, FALSE), - HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE), - HIDE_JOIN_MEMBERSHIP_BUTTON("revanced_hide_join_membership_button", BOOLEAN, TRUE), HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE), - HIDE_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE), HIDE_HIDE_INFO_PANELS("revanced_hide_info_panels", BOOLEAN, TRUE), + HIDE_HOME_BUTTON("revanced_hide_home_button", BOOLEAN, FALSE, true), + HIDE_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE), + HIDE_INFO_CARDS("revanced_hide_info_cards", BOOLEAN, TRUE), + HIDE_JOIN_MEMBERSHIP_BUTTON("revanced_hide_join_membership_button", BOOLEAN, TRUE), + HIDE_LOAD_MORE_BUTTON("revanced_hide_load_more_button", BOOLEAN, TRUE, true), HIDE_MEDICAL_PANELS("revanced_hide_medical_panels", BOOLEAN, TRUE), - HIDE_MERCHANDISE_BANNERS("revanced_hide_merchandise_banners", BOOLEAN, TRUE), + HIDE_MIX_PLAYLISTS("revanced_hide_mix_playlists", BOOLEAN, TRUE), HIDE_MOVIES_SECTION("revanced_hide_movies_section", BOOLEAN, TRUE), - HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES("revanced_hide_subscribers_community_guidelines", BOOLEAN, TRUE), - HIDE_PRODUCTS_BANNER("revanced_hide_products_banner", BOOLEAN, TRUE), - HIDE_WEB_SEARCH_RESULTS("revanced_hide_web_search_results", BOOLEAN, TRUE), + HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE), + HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE), + HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true), HIDE_QUICK_ACTIONS("revanced_hide_quick_actions", BOOLEAN, FALSE), HIDE_RELATED_VIDEOS("revanced_hide_related_videos", BOOLEAN, FALSE), - HIDE_MIX_PLAYLISTS("revanced_hide_mix_playlists", BOOLEAN, TRUE), + HIDE_SEARCH_RESULT_SHELF_HEADER("revanced_hide_search_result_shelf_header", BOOLEAN, FALSE), + HIDE_SHORTS_BUTTON("revanced_hide_shorts_button", BOOLEAN, TRUE, true), + HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES("revanced_hide_subscribers_community_guidelines", BOOLEAN, TRUE), + HIDE_SUBSCRIPTIONS_BUTTON("revanced_hide_subscriptions_button", BOOLEAN, FALSE, true), + HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), + HIDE_TIMESTAMP("revanced_hide_timestamp", BOOLEAN, FALSE), + @Deprecated HIDE_VIDEO_WATERMARK("revanced_hide_video_watermark", BOOLEAN, TRUE), + HIDE_VIDEO_CHANNEL_WATERMARK("revanced_hide_channel_watermark", BOOLEAN, TRUE), + HIDE_VIDEO_QUALITY_MENU_FOOTER("revanced_hide_video_quality_menu_footer", BOOLEAN, TRUE), + PLAYER_OVERLAY_OPACITY("revanced_player_overlay_opacity", INTEGER, 100, true), + PLAYER_POPUP_PANELS("revanced_hide_player_popup_panels", BOOLEAN, FALSE), + SPOOF_APP_VERSION("revanced_spoof_app_version", BOOLEAN, FALSE, true, "revanced_spoof_app_version_user_dialog_message"), + SPOOF_APP_VERSION_TARGET("revanced_spoof_app_version_target", STRING, "17.08.35", true, parents(SPOOF_APP_VERSION)), + SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON("revanced_switch_create_with_notifications_button", BOOLEAN, TRUE, true), + TABLET_LAYOUT("revanced_tablet_layout", BOOLEAN, FALSE, true, "revanced_tablet_layout_user_dialog_message"), + USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true), + WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true), + + // Shorts + HIDE_SHORTS("revanced_hide_shorts", BOOLEAN, FALSE, true), + HIDE_SHORTS_JOIN_BUTTON("revanced_hide_shorts_join_button", BOOLEAN, TRUE), + HIDE_SHORTS_SUBSCRIBE_BUTTON("revanced_hide_shorts_subscribe_button", BOOLEAN, TRUE), + HIDE_SHORTS_SUBSCRIBE_BUTTON_PAUSED("revanced_hide_shorts_subscribe_button_paused", BOOLEAN, FALSE), + HIDE_SHORTS_THANKS_BUTTON("revanced_hide_shorts_thanks_button", BOOLEAN, TRUE), + HIDE_SHORTS_COMMENTS_BUTTON("revanced_hide_shorts_comments_button", BOOLEAN, FALSE), + HIDE_SHORTS_REMIX_BUTTON("revanced_hide_shorts_remix_button", BOOLEAN, TRUE), + HIDE_SHORTS_SHARE_BUTTON("revanced_hide_shorts_share_button", BOOLEAN, FALSE), + HIDE_SHORTS_INFO_PANEL("revanced_hide_shorts_info_panel", BOOLEAN, TRUE), + HIDE_SHORTS_SOUND_BUTTON("revanced_hide_shorts_sound_button", BOOLEAN, FALSE), + HIDE_SHORTS_CHANNEL_BAR("revanced_hide_shorts_channel_bar", BOOLEAN, FALSE), + HIDE_SHORTS_NAVIGATION_BAR("revanced_hide_shorts_navigation_bar", BOOLEAN, TRUE, true), + + // Seekbar + @Deprecated ENABLE_OLD_SEEKBAR_THUMBNAILS("revanced_enable_old_seekbar_thumbnails", BOOLEAN, TRUE), + RESTORE_OLD_SEEKBAR_THUMBNAILS("revanced_restore_old_seekbar_thumbnails", BOOLEAN, TRUE), + HIDE_SEEKBAR("revanced_hide_seekbar", BOOLEAN, FALSE), + HIDE_SEEKBAR_THUMBNAIL("revanced_hide_seekbar_thumbnail", BOOLEAN, FALSE), + SEEKBAR_CUSTOM_COLOR("revanced_seekbar_custom_color", BOOLEAN, TRUE, true), + SEEKBAR_CUSTOM_COLOR_VALUE("revanced_seekbar_custom_color_value", STRING, "#FF0000", true, parents(SEEKBAR_CUSTOM_COLOR)), // Action buttons HIDE_LIKE_DISLIKE_BUTTON("revanced_hide_like_dislike_button", BOOLEAN, FALSE), @@ -92,69 +158,7 @@ public enum SettingsEnum { HIDE_PLAYLIST_BUTTON("revanced_hide_playlist_button", BOOLEAN, FALSE), HIDE_SHOP_BUTTON("revanced_hide_shop_button", BOOLEAN, TRUE), - // Layout - PLAYER_OVERLAY_OPACITY("revanced_player_overlay_opacity", INTEGER, 100, true), - DISABLE_RESUMING_SHORTS_PLAYER("revanced_disable_resuming_shorts_player", BOOLEAN, FALSE), - HIDE_ALBUM_CARDS("revanced_hide_album_cards", BOOLEAN, FALSE, true), - HIDE_ARTIST_CARDS("revanced_hide_artist_cards", BOOLEAN, FALSE), - HIDE_AUTOPLAY_BUTTON("revanced_hide_autoplay_button", BOOLEAN, TRUE, true), - HIDE_BREAKING_NEWS("revanced_hide_breaking_news", BOOLEAN, TRUE, true), - HIDE_CAPTIONS_BUTTON("revanced_hide_captions_button", BOOLEAN, FALSE), - HIDE_CAST_BUTTON("revanced_hide_cast_button", BOOLEAN, TRUE, true), - HIDE_COMMENTS_SECTION("revanced_hide_comments_section", BOOLEAN, FALSE, true), - HIDE_CREATE_BUTTON("revanced_hide_create_button", BOOLEAN, TRUE, true), - HIDE_CHIPS_SHELF("revanced_hide_chips_shelf", BOOLEAN, TRUE), - HIDE_CROWDFUNDING_BOX("revanced_hide_crowdfunding_box", BOOLEAN, FALSE, true), - HIDE_EMAIL_ADDRESS("revanced_hide_email_address", BOOLEAN, FALSE), - HIDE_ENDSCREEN_CARDS("revanced_hide_endscreen_cards", BOOLEAN, TRUE), - HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", BOOLEAN, TRUE, true), - HIDE_FULLSCREEN_PANELS("revanced_hide_fullscreen_panels", BOOLEAN, TRUE, true), - HIDE_GET_PREMIUM("revanced_hide_get_premium", BOOLEAN, TRUE), - HIDE_INFO_CARDS("revanced_hide_info_cards", BOOLEAN, TRUE), - HIDE_LOAD_MORE_BUTTON("revanced_hide_load_more_button", BOOLEAN, TRUE, true), - HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE), - HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true), - HIDE_SEEKBAR("revanced_hide_seekbar", BOOLEAN, FALSE), - HIDE_SEEKBAR_THUMBNAIL("revanced_hide_seekbar_thumbnail", BOOLEAN, FALSE), - HIDE_HOME_BUTTON("revanced_hide_home_button", BOOLEAN, FALSE, true), - HIDE_SHORTS_BUTTON("revanced_hide_shorts_button", BOOLEAN, TRUE, true), - HIDE_SUBSCRIPTIONS_BUTTON("revanced_hide_subscriptions_button", BOOLEAN, FALSE, true), - HIDE_TIMESTAMP("revanced_hide_timestamp", BOOLEAN, FALSE), - HIDE_VIDEO_WATERMARK("revanced_hide_video_watermark", BOOLEAN, TRUE), - HIDE_VIDEO_CHANNEL_WATERMARK("revanced_hide_channel_watermark", BOOLEAN, TRUE), - PLAYER_POPUP_PANELS("revanced_hide_player_popup_panels", BOOLEAN, FALSE), - SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON("revanced_switch_create_with_notifications_button", BOOLEAN, TRUE, true), - SPOOF_APP_VERSION("revanced_spoof_app_version", BOOLEAN, FALSE, true, "revanced_spoof_app_version_user_dialog_message"), - SPOOF_APP_VERSION_TARGET("revanced_spoof_app_version_target", STRING, "17.08.35", true, parents(SPOOF_APP_VERSION)), - USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true), - TABLET_LAYOUT("revanced_tablet_layout", BOOLEAN, FALSE, true, "revanced_tablet_layout_user_dialog_message"), - WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true), - GRADIENT_LOADING_SCREEN("revanced_gradient_loading_screen", BOOLEAN, FALSE), - SEEKBAR_CUSTOM_COLOR("revanced_seekbar_custom_color", BOOLEAN, TRUE, true), - SEEKBAR_CUSTOM_COLOR_VALUE("revanced_seekbar_custom_color_value", STRING, "#FF0000", true, parents(SEEKBAR_CUSTOM_COLOR)), - HIDE_FILTER_BAR_FEED_IN_FEED("revanced_hide_filter_bar_feed_in_feed", BOOLEAN, FALSE, true), - HIDE_FILTER_BAR_FEED_IN_SEARCH("revanced_hide_filter_bar_feed_in_search", BOOLEAN, FALSE, true), - HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS("revanced_hide_filter_bar_feed_in_related_videos", BOOLEAN, FALSE, true), - HIDE_SHORTS_JOIN_BUTTON("revanced_hide_shorts_join_button", BOOLEAN, TRUE), - HIDE_SHORTS_SUBSCRIBE_BUTTON("revanced_hide_shorts_subscribe_button", BOOLEAN, TRUE), - HIDE_SHORTS_SUBSCRIBE_BUTTON_PAUSED("revanced_hide_shorts_subscribe_button_paused", BOOLEAN, FALSE), - HIDE_SHORTS_THANKS_BUTTON("revanced_hide_shorts_thanks_button", BOOLEAN, TRUE), - HIDE_SHORTS_COMMENTS_BUTTON("revanced_hide_shorts_comments_button", BOOLEAN, FALSE), - HIDE_SHORTS_REMIX_BUTTON("revanced_hide_shorts_remix_button", BOOLEAN, TRUE), - HIDE_SHORTS_SHARE_BUTTON("revanced_hide_shorts_share_button", BOOLEAN, FALSE), - HIDE_SHORTS_INFO_PANEL("revanced_hide_shorts_info_panel", BOOLEAN, TRUE), - HIDE_SHORTS_SOUND_BUTTON("revanced_hide_shorts_sound_button", BOOLEAN, FALSE), - HIDE_SHORTS_CHANNEL_BAR("revanced_hide_shorts_channel_bar", BOOLEAN, FALSE), - HIDE_SHORTS_NAVIGATION_BAR("revanced_hide_shorts_navigation_bar", BOOLEAN, TRUE, true), - HIDE_SHORTS("revanced_hide_shorts", BOOLEAN, FALSE, true), - DISABLE_SUGGESTED_VIDEO_END_SCREEN("revanced_disable_suggested_video_end_screen", BOOLEAN, TRUE), - ENABLE_OLD_SEEKBAR_THUMBNAILS("revanced_enable_old_seekbar_thumbnails", BOOLEAN, TRUE), - DISABLE_FULLSCREEN_AMBIENT_MODE("revanced_disable_fullscreen_ambient_mode", BOOLEAN, TRUE, true), - ALT_THUMBNAIL("revanced_alt_thumbnail", BOOLEAN, FALSE), - ALT_THUMBNAIL_TYPE("revanced_alt_thumbnail_type", INTEGER, 2, parents(ALT_THUMBNAIL)), - ALT_THUMBNAIL_FAST_QUALITY("revanced_alt_thumbnail_fast_quality", BOOLEAN, FALSE, parents(ALT_THUMBNAIL)), - - //Player flyout menu items + // Player flyout menu items HIDE_CAPTIONS_MENU("revanced_hide_player_flyout_captions", BOOLEAN, FALSE), HIDE_ADDITIONAL_SETTINGS_MENU("revanced_hide_player_flyout_additional_settings", BOOLEAN, FALSE), HIDE_LOOP_VIDEO_MENU("revanced_hide_player_flyout_loop_video", BOOLEAN, FALSE), @@ -172,8 +176,8 @@ public enum SettingsEnum { EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true), AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE), SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE), + @Deprecated DISABLE_FINE_SCRUBBING_GESTURE("revanced_disable_fine_scrubbing_gesture", BOOLEAN, TRUE), DISABLE_PRECISE_SEEKING_GESTURE("revanced_disable_precise_seeking_gesture", BOOLEAN, TRUE), - DISABLE_FINE_SCRUBBING_GESTURE("revanced_disable_fine_scrubbing_gesture", BOOLEAN, TRUE), SPOOF_SIGNATURE("revanced_spoof_signature_verification_enabled", BOOLEAN, TRUE, true, "revanced_spoof_signature_verification_enabled_user_dialog_message"), SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false, @@ -383,6 +387,8 @@ public enum SettingsEnum { migrateOldSettingToNew(HIDE_VIDEO_WATERMARK, HIDE_VIDEO_CHANNEL_WATERMARK); migrateOldSettingToNew(DISABLE_FINE_SCRUBBING_GESTURE, DISABLE_PRECISE_SEEKING_GESTURE); + migrateOldSettingToNew(SHOW_OLD_VIDEO_QUALITY_MENU, RESTORE_OLD_VIDEO_QUALITY_MENU); + migrateOldSettingToNew(ENABLE_OLD_SEEKBAR_THUMBNAILS, RESTORE_OLD_SEEKBAR_THUMBNAILS); // Do _not_ delete this SB private user id migration property until sometime in 2024. // This is the only setting that cannot be reconfigured if lost, From e94de61eb02d439235fd10315ab85131ef518103 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 6 Nov 2023 12:00:54 +0000 Subject: [PATCH 02/21] chore(release): 0.121.1-dev.1 [skip ci] ## [0.121.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0...v0.121.1-dev.1) (2023-11-06) ### Bug Fixes * **YouTube:** Rename `Restore old seekbar thumbnails` and `Restore old quality menu` ([#510](https://github.com/ReVanced/revanced-integrations/issues/510)) ([6b00f90](https://github.com/ReVanced/revanced-integrations/commit/6b00f90fb7561d59de59d76d43fff8c1d057dce6)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a82768b..46714027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.121.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0...v0.121.1-dev.1) (2023-11-06) + + +### Bug Fixes + +* **YouTube:** Rename `Restore old seekbar thumbnails` and `Restore old quality menu` ([#510](https://github.com/ReVanced/revanced-integrations/issues/510)) ([6b00f90](https://github.com/ReVanced/revanced-integrations/commit/6b00f90fb7561d59de59d76d43fff8c1d057dce6)) + # [0.121.0](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0...v0.121.0) (2023-11-04) diff --git a/gradle.properties b/gradle.properties index d5c51293..4b36ead3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.0 +version = 0.121.1-dev.1 From 4f57d560425a40386a014da05fe26bb9c22f090f Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 6 Nov 2023 23:23:05 +0100 Subject: [PATCH 03/21] fix(YouTube - Disable suggested video end screen): Do not spam click to disable the screen --- .../DisableSuggestedVideoEndScreenPatch.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java index 6a5c3ca3..bc0d7f8c 100644 --- a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java @@ -14,13 +14,23 @@ public final class DisableSuggestedVideoEndScreenPatch { public static void closeEndScreen(final ImageView imageView) { if (!SettingsEnum.DISABLE_SUGGESTED_VIDEO_END_SCREEN.getBoolean()) return; - // Get the view which can be listened to for layout changes. + // Get a parent view which can be listened to for layout changes. final var parent = imageView.getParent().getParent(); // Prevent adding the listener multiple times. if (lastView == parent) return; lastView = (ViewGroup)parent; - lastView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> imageView.performClick()); + lastView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, + int oldRight, int oldBottom) { + // Disable sound effects to prevent the click sound. + imageView.performClick(); + + // Remove the listener to prevent it from being called multiple times. + lastView.removeOnLayoutChangeListener(this); + } + }); } } From 6e414ec6c2a40d70f810b0ade1d8c41cadafff8d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 6 Nov 2023 23:25:35 +0100 Subject: [PATCH 04/21] fix(YouTube): Prevent playing touch interaction sound when unintended --- .../patches/DisableSuggestedVideoEndScreenPatch.java | 1 + .../quality/RestoreOldVideoQualityMenuPatch.java | 1 + .../playback/speed/CustomPlaybackSpeedPatch.java | 11 ++++++----- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java index bc0d7f8c..8b04a192 100644 --- a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java @@ -26,6 +26,7 @@ public final class DisableSuggestedVideoEndScreenPatch { public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { // Disable sound effects to prevent the click sound. + imageView.setSoundEffectsEnabled(false); imageView.performClick(); // Remove the listener to prevent it from being called multiple times. diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java index 92a66ca2..0fee1039 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java @@ -33,6 +33,7 @@ public final class RestoreOldVideoQualityMenuPatch { View advancedQualityView = ((ViewGroup) recyclerView.getChildAt(0)).getChildAt(3); if (advancedQualityView != null) { // Click the "Advanced" quality menu to show the "old" quality menu. + advancedQualityView.setSoundEffectsEnabled(false); advancedQualityView.performClick(); } } diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java index 5e318578..30f79e64 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -4,16 +4,14 @@ import android.preference.ListPreference; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; - -import java.util.Arrays; - import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; +import java.util.Arrays; + public class CustomPlaybackSpeedPatch { /** * Maximum playback speed, exclusive value. Custom speeds must be less than this value. @@ -111,7 +109,10 @@ public class CustomPlaybackSpeedPatch { // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView. // This only shows in phone layout. - parentView4th.getChildAt(0).performClick(); + + final var touchInsidedView = parentView4th.getChildAt(0); + touchInsidedView.setSoundEffectsEnabled(false); + touchInsidedView.performClick(); // In tablet layout there is no Dismiss View, instead we just hide all two parent views. parentView3rd.setVisibility(View.GONE); From 37b3b6a8371181eb4fda8969323cff2afa4db2bc Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 7 Nov 2023 11:46:38 +0000 Subject: [PATCH 05/21] chore(release): 0.121.1-dev.2 [skip ci] ## [0.121.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.1...v0.121.1-dev.2) (2023-11-07) ### Bug Fixes * **YouTube - Disable suggested video end screen:** Do not spam click to disable the screen ([4f57d56](https://github.com/ReVanced/revanced-integrations/commit/4f57d560425a40386a014da05fe26bb9c22f090f)) * **YouTube:** Prevent playing touch interaction sound when unintended ([6e414ec](https://github.com/ReVanced/revanced-integrations/commit/6e414ec6c2a40d70f810b0ade1d8c41cadafff8d)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46714027..2beb47a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [0.121.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.1...v0.121.1-dev.2) (2023-11-07) + + +### Bug Fixes + +* **YouTube - Disable suggested video end screen:** Do not spam click to disable the screen ([4f57d56](https://github.com/ReVanced/revanced-integrations/commit/4f57d560425a40386a014da05fe26bb9c22f090f)) +* **YouTube:** Prevent playing touch interaction sound when unintended ([6e414ec](https://github.com/ReVanced/revanced-integrations/commit/6e414ec6c2a40d70f810b0ade1d8c41cadafff8d)) + ## [0.121.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0...v0.121.1-dev.1) (2023-11-06) diff --git a/gradle.properties b/gradle.properties index 4b36ead3..b67ffbc8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.1-dev.1 +version = 0.121.1-dev.2 From 50933dc42d4ef77fb45a978e19d306dad5070540 Mon Sep 17 00:00:00 2001 From: Linus <23507341+Linus789@users.noreply.github.com> Date: Fri, 10 Nov 2023 01:06:01 +0000 Subject: [PATCH 06/21] fix(Remove screenshot restriction): Improve reliability (#471) --- .../removerestriction/RemoveScreenshotRestrictionPatch.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/app/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.java b/app/src/main/java/app/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.java index 8c3eeecb..f43de82c 100644 --- a/app/src/main/java/app/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.java +++ b/app/src/main/java/app/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.java @@ -5,6 +5,10 @@ import android.view.WindowManager; public class RemoveScreenshotRestrictionPatch { + public static void addFlags(Window window, int flags) { + window.addFlags(flags & ~WindowManager.LayoutParams.FLAG_SECURE); + } + public static void setFlags(Window window, int flags, int mask) { window.setFlags(flags & ~WindowManager.LayoutParams.FLAG_SECURE, mask & ~WindowManager.LayoutParams.FLAG_SECURE); } From 831041b43214e4c6e934dae6ab0046f5e2c44a12 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 10 Nov 2023 01:09:33 +0000 Subject: [PATCH 07/21] chore(release): 0.121.1-dev.3 [skip ci] ## [0.121.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.2...v0.121.1-dev.3) (2023-11-10) ### Bug Fixes * **Remove screenshot restriction:** Improve reliability ([#471](https://github.com/ReVanced/revanced-integrations/issues/471)) ([50933dc](https://github.com/ReVanced/revanced-integrations/commit/50933dc42d4ef77fb45a978e19d306dad5070540)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2beb47a6..6a2992b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.121.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.2...v0.121.1-dev.3) (2023-11-10) + + +### Bug Fixes + +* **Remove screenshot restriction:** Improve reliability ([#471](https://github.com/ReVanced/revanced-integrations/issues/471)) ([50933dc](https://github.com/ReVanced/revanced-integrations/commit/50933dc42d4ef77fb45a978e19d306dad5070540)) + ## [0.121.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.1...v0.121.1-dev.2) (2023-11-07) diff --git a/gradle.properties b/gradle.properties index b67ffbc8..c9a867d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.1-dev.2 +version = 0.121.1-dev.3 From 11f97ac354344aac3d101f8874e38273da15f9e6 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:22:41 +0200 Subject: [PATCH 08/21] fix(YouTube - Client spoof): Fix low resolution precise seeking thumbnails (#513) --- .../patches/spoof/SpoofSignaturePatch.java | 104 ++++++++++++++---- .../patches/spoof/StoryboardRenderer.java | 11 +- .../requests/StoryboardRendererRequester.java | 8 +- .../integrations/settings/SettingsEnum.java | 3 + 4 files changed, 99 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 16a284d0..06534d03 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -3,6 +3,10 @@ package app.revanced.integrations.patches.spoof; import static app.revanced.integrations.patches.spoof.requests.StoryboardRendererRequester.getStoryboardRenderer; import static app.revanced.integrations.utils.ReVancedUtils.containsAny; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + import androidx.annotation.Nullable; import java.util.concurrent.ExecutionException; @@ -51,11 +55,15 @@ public class SpoofSignaturePatch { private static volatile Future rendererFuture; + private static volatile boolean useOriginalStoryboardRenderer; + + private static volatile boolean isPlayingShorts; + @Nullable private static StoryboardRenderer getRenderer() { if (rendererFuture != null) { try { - return rendererFuture.get(5000, TimeUnit.MILLISECONDS); + return rendererFuture.get(4000, TimeUnit.MILLISECONDS); } catch (TimeoutException ex) { LogHelper.printDebug(() -> "Could not get renderer (get timed out)"); } catch (ExecutionException | InterruptedException ex) { @@ -81,27 +89,38 @@ public class SpoofSignaturePatch { // Clip's player parameters contain a lot of information (e.g. video start and end time or whether it loops) // For this reason, the player parameters of a clip are usually very long (150~300 characters). // Clips are 60 seconds or less in length, so no spoofing. - var isClip = parameters.length() > 150; - if (isClip) return parameters; + if (useOriginalStoryboardRenderer = parameters.length() > 150) return parameters; // Shorts do not need to be spoofed. - if (parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; + if (useOriginalStoryboardRenderer = parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) { + isPlayingShorts = true; + return parameters; + } + isPlayingShorts = false; - boolean isPlayingFeed = PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL && containsAny(parameters, AUTOPLAY_PARAMETERS); - if (isPlayingFeed) return SettingsEnum.SPOOF_SIGNATURE_IN_FEED.getBoolean() ? - // Prepend the scrim parameter to mute videos in feed. - SCRIM_PARAMETER + INCOGNITO_PARAMETERS : - // In order to prevent videos that are auto-played in feed to be added to history, - // only spoof the parameter if the video is not playing in the feed. - // This will cause playback issues in the feed, but it's better than manipulating the history. - parameters; + boolean isPlayingFeed = PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL + && containsAny(parameters, AUTOPLAY_PARAMETERS); + if (isPlayingFeed) { + if (useOriginalStoryboardRenderer = !SettingsEnum.SPOOF_SIGNATURE_IN_FEED.getBoolean()) { + // Don't spoof the feed video playback. This will cause video playback issues, + // but only if user continues watching for more than 1 minute. + return parameters; + } + // Spoof the feed video. Video will show up in watch history and video subtitles are missing. + fetchStoryboardRenderer(); + return SCRIM_PARAMETER + INCOGNITO_PARAMETERS; + } fetchStoryboardRenderer(); - return INCOGNITO_PARAMETERS; } private static void fetchStoryboardRenderer() { + if (!SettingsEnum.SPOOF_STORYBOARD_RENDERER.getBoolean()) { + lastPlayerResponseVideoId = null; + rendererFuture = null; + return; + } String videoId = VideoInformation.getPlayerResponseVideoId(); if (!videoId.equals(lastPlayerResponseVideoId)) { rendererFuture = ReVancedUtils.submitOnBackgroundThread(() -> getStoryboardRenderer(videoId)); @@ -115,11 +134,17 @@ public class SpoofSignaturePatch { getRenderer(); } - /** - * Injection point. - */ - public static boolean getSeekbarThumbnailOverrideValue() { - return SettingsEnum.SPOOF_SIGNATURE.getBoolean(); + private static String getStoryboardRendererSpec(String originalStoryboardRendererSpec, + boolean returnNullIfLiveStream) { + if (SettingsEnum.SPOOF_SIGNATURE.getBoolean() && !useOriginalStoryboardRenderer) { + StoryboardRenderer renderer = getRenderer(); + if (renderer != null) { + if (returnNullIfLiveStream && renderer.isLiveStream()) return null; + return renderer.getSpec(); + } + } + + return originalStoryboardRendererSpec; } /** @@ -128,19 +153,24 @@ public class SpoofSignaturePatch { */ @Nullable public static String getStoryboardRendererSpec(String originalStoryboardRendererSpec) { - if (SettingsEnum.SPOOF_SIGNATURE.getBoolean()) { - StoryboardRenderer renderer = getRenderer(); - if (renderer != null) return renderer.getSpec(); - } + return getStoryboardRendererSpec(originalStoryboardRendererSpec, false); + } - return originalStoryboardRendererSpec; + /** + * Injection point. + * Uses additional check to handle live streams. + * Called from background threads and from the main thread. + */ + @Nullable + public static String getStoryboardDecoderRendererSpec(String originalStoryboardRendererSpec) { + return getStoryboardRendererSpec(originalStoryboardRendererSpec, true); } /** * Injection point. */ public static int getRecommendedLevel(int originalLevel) { - if (SettingsEnum.SPOOF_SIGNATURE.getBoolean()) { + if (SettingsEnum.SPOOF_SIGNATURE.getBoolean() && !useOriginalStoryboardRenderer) { StoryboardRenderer renderer = getRenderer(); if (renderer != null) { Integer recommendedLevel = renderer.getRecommendedLevel(); @@ -150,4 +180,30 @@ public class SpoofSignaturePatch { return originalLevel; } + + /** + * Injection point. Forces seekbar to be shown for paid videos or + * if {@link SettingsEnum#SPOOF_STORYBOARD_RENDERER} is not enabled. + */ + public static boolean getSeekbarThumbnailOverrideValue() { + return SettingsEnum.SPOOF_SIGNATURE.getBoolean(); + } + + /** + * Injection point. + * + * @param view seekbar thumbnail view. Includes both shorts and regular videos. + */ + public static void seekbarImageViewCreated(ImageView view) { + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean() + || SettingsEnum.SPOOF_STORYBOARD_RENDERER.getBoolean()) { + return; + } + if (isPlayingShorts) return; + + view.setVisibility(View.GONE); + // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). + ViewGroup parentLayout = (ViewGroup) view.getParent(); + parentLayout.setPadding(0, 0, 0, 0); + } } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java b/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java index d0e70988..32f5608c 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java @@ -7,11 +7,13 @@ import org.jetbrains.annotations.NotNull; public final class StoryboardRenderer { private final String spec; + private final boolean isLiveStream; @Nullable private final Integer recommendedLevel; - public StoryboardRenderer(String spec, @Nullable Integer recommendedLevel) { + public StoryboardRenderer(String spec, boolean isLiveStream, @Nullable Integer recommendedLevel) { this.spec = spec; + this.isLiveStream = isLiveStream; this.recommendedLevel = recommendedLevel; } @@ -20,6 +22,10 @@ public final class StoryboardRenderer { return spec; } + public boolean isLiveStream() { + return isLiveStream; + } + /** * @return Recommended image quality level, or NULL if no recommendation exists. */ @@ -32,7 +38,8 @@ public final class StoryboardRenderer { @Override public String toString() { return "StoryboardRenderer{" + - "spec='" + spec + '\'' + + "isLiveStream=" + isLiveStream + + ", spec='" + spec + '\'' + ", recommendedLevel=" + recommendedLevel + '}'; } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java index 61828a04..38904dc2 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java @@ -22,6 +22,7 @@ public class StoryboardRendererRequester { @Nullable private static JSONObject fetchPlayerResponse(@NonNull String requestBody) { + final long startTime = System.currentTimeMillis(); try { ReVancedUtils.verifyOffMainThread(); Objects.requireNonNull(requestBody); @@ -40,6 +41,8 @@ public class StoryboardRendererRequester { LogHelper.printException(() -> "API timed out", ex); } catch (Exception ex) { LogHelper.printException(() -> "Failed to fetch storyboard URL", ex); + } finally { + LogHelper.printDebug(() -> "Request took: " + (System.currentTimeMillis() - startTime) + "ms"); } return null; @@ -72,14 +75,17 @@ public class StoryboardRendererRequester { @Nullable private static StoryboardRenderer getStoryboardRendererUsingResponse(@NonNull JSONObject playerResponse) { try { + LogHelper.printDebug(() -> "Parsing response: " + playerResponse); final JSONObject storyboards = playerResponse.getJSONObject("storyboards"); - final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer") + final boolean isLiveStream = storyboards.has("playerLiveStoryboardSpecRenderer"); + final String storyboardsRendererTag = isLiveStream ? "playerLiveStoryboardSpecRenderer" : "playerStoryboardSpecRenderer"; final var rendererElement = storyboards.getJSONObject(storyboardsRendererTag); StoryboardRenderer renderer = new StoryboardRenderer( rendererElement.getString("spec"), + isLiveStream, rendererElement.has("recommendedLevel") ? rendererElement.getInt("recommendedLevel") : null diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 53a911e5..105bea54 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -182,6 +182,9 @@ public enum SettingsEnum { "revanced_spoof_signature_verification_enabled_user_dialog_message"), SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false, parents(SPOOF_SIGNATURE)), + SPOOF_STORYBOARD_RENDERER("revanced_spoof_storyboard", BOOLEAN, TRUE, true, + parents(SPOOF_SIGNATURE)), + SPOOF_DEVICE_DIMENSIONS("revanced_spoof_device_dimensions", BOOLEAN, FALSE, true), BYPASS_URL_REDIRECTS("revanced_bypass_url_redirects", BOOLEAN, TRUE), ANNOUNCEMENTS("revanced_announcements", BOOLEAN, TRUE), From db0fb46a396ad5f3301b32773d19638ca0af92cb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 11 Nov 2023 18:26:36 +0000 Subject: [PATCH 09/21] chore(release): 0.121.1-dev.4 [skip ci] ## [0.121.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.3...v0.121.1-dev.4) (2023-11-11) ### Bug Fixes * **YouTube - Client spoof:** Fix low resolution precise seeking thumbnails ([#513](https://github.com/ReVanced/revanced-integrations/issues/513)) ([11f97ac](https://github.com/ReVanced/revanced-integrations/commit/11f97ac354344aac3d101f8874e38273da15f9e6)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a2992b9..5768a391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.121.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.3...v0.121.1-dev.4) (2023-11-11) + + +### Bug Fixes + +* **YouTube - Client spoof:** Fix low resolution precise seeking thumbnails ([#513](https://github.com/ReVanced/revanced-integrations/issues/513)) ([11f97ac](https://github.com/ReVanced/revanced-integrations/commit/11f97ac354344aac3d101f8874e38273da15f9e6)) + ## [0.121.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.2...v0.121.1-dev.3) (2023-11-10) diff --git a/gradle.properties b/gradle.properties index c9a867d8..e24192a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.1-dev.3 +version = 0.121.1-dev.4 From e84b7b328ea48e86d240d38cf83aa960f87d6902 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 12 Nov 2023 01:27:19 +0100 Subject: [PATCH 10/21] feat(YouTube): Add `Remove tracking query parameter` patch Implementation references taken from github.com/inotia00/revanced-patches/commit/4037d9c85b7e37f8635f8fdcc1efea85dcddb5e2. --- .../RemoveTrackingQueryParameterPatch.java | 16 ++++++++++++++++ .../integrations/settings/SettingsEnum.java | 1 + 2 files changed, 17 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/RemoveTrackingQueryParameterPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/RemoveTrackingQueryParameterPatch.java b/app/src/main/java/app/revanced/integrations/patches/RemoveTrackingQueryParameterPatch.java new file mode 100644 index 00000000..4910f586 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/RemoveTrackingQueryParameterPatch.java @@ -0,0 +1,16 @@ +package app.revanced.integrations.patches; + +import app.revanced.integrations.settings.SettingsEnum; + +public final class RemoveTrackingQueryParameterPatch { + private static final String NEW_TRACKING_PARAMETER_REGEX = ".si=.+"; + private static final String OLD_TRACKING_PARAMETER_REGEX = ".feature=.+"; + + public static String sanitize(String url) { + if (!SettingsEnum.REMOVE_TRACKING_QUERY_PARAMETER.getBoolean()) return url; + + return url + .replaceAll(NEW_TRACKING_PARAMETER_REGEX, "") + .replaceAll(OLD_TRACKING_PARAMETER_REGEX, ""); + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 105bea54..937fa02a 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -190,6 +190,7 @@ public enum SettingsEnum { ANNOUNCEMENTS("revanced_announcements", BOOLEAN, TRUE), ANNOUNCEMENT_CONSUMER("revanced_announcement_consumer", STRING, ""), ANNOUNCEMENT_LAST_HASH("revanced_announcement_last_hash", STRING, ""), + REMOVE_TRACKING_QUERY_PARAMETER("revanced_remove_tracking_query_parameter", BOOLEAN, TRUE), // Swipe controls SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE), From b1ce7a75eba53312d9522c87321ac83cb16d83cf Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 12 Nov 2023 16:02:05 +0100 Subject: [PATCH 11/21] feat(YouTube): Add `Enable slide to seek` patch Implementation references taken from github.com/inotia00/revanced-patches/commit/0ede1987544aa0068f28665c6c029df23a30afe2 --- .../revanced/integrations/patches/SlideToSeekPatch.java | 9 +++++++++ .../app/revanced/integrations/settings/SettingsEnum.java | 1 + 2 files changed, 10 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/SlideToSeekPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/SlideToSeekPatch.java b/app/src/main/java/app/revanced/integrations/patches/SlideToSeekPatch.java new file mode 100644 index 00000000..ec739f5f --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/SlideToSeekPatch.java @@ -0,0 +1,9 @@ +package app.revanced.integrations.patches; + +import app.revanced.integrations.settings.SettingsEnum; + +public final class SlideToSeekPatch { + public static boolean isSlideToSeekDisabled() { + return !SettingsEnum.SLIDE_TO_SEEK.getBoolean(); + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 937fa02a..d830d06b 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -176,6 +176,7 @@ public enum SettingsEnum { EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true), AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE), SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE), + SLIDE_TO_SEEK("revanced_slide_to_seek", BOOLEAN, FALSE), @Deprecated DISABLE_FINE_SCRUBBING_GESTURE("revanced_disable_fine_scrubbing_gesture", BOOLEAN, TRUE), DISABLE_PRECISE_SEEKING_GESTURE("revanced_disable_precise_seeking_gesture", BOOLEAN, TRUE), SPOOF_SIGNATURE("revanced_spoof_signature_verification_enabled", BOOLEAN, TRUE, true, From 5f30100fd59c1e61c0236bc54cfcd03212994cab Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 12 Nov 2023 16:23:56 +0100 Subject: [PATCH 12/21] fix(YouTube - Hide layout components): Reduce false positives when hiding mix playlists Implementation references taken from github.com/inotia00/revanced-integrations/commit/cfaf3d6356f316623ad32b10719b1b5ef0ba25b9 --- .../components/LayoutComponentsFilter.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 21134ae7..6589976a 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -2,10 +2,8 @@ package app.revanced.integrations.patches.components; import android.os.Build; - import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; - import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.StringTrieSearch; @@ -13,6 +11,9 @@ import app.revanced.integrations.utils.StringTrieSearch; @RequiresApi(api = Build.VERSION_CODES.N) public final class LayoutComponentsFilter extends Filter { private final StringTrieSearch exceptions = new StringTrieSearch(); + private static final StringTrieSearch mixPlaylistsExceptions = new StringTrieSearch(); + private static ByteArrayAsStringFilterGroup mixPlaylistsExceptions2; + private final CustomFilterGroup custom; private static final ByteArrayAsStringFilterGroup mixPlaylists = new ByteArrayAsStringFilterGroup( @@ -34,6 +35,16 @@ public final class LayoutComponentsFilter extends Filter { "library_recent_shelf" ); + mixPlaylistsExceptions.addPatterns( + "V.ED", // Playlist browse id. + "java.lang.ref.WeakReference" + ); + + mixPlaylistsExceptions2 = new ByteArrayAsStringFilterGroup( + null, + "cell_description_body" + ); + custom = new CustomFilterGroup( SettingsEnum.CUSTOM_FILTER, SettingsEnum.CUSTOM_FILTER_STRINGS @@ -243,13 +254,19 @@ public final class LayoutComponentsFilter extends Filter { * Injection point. * Called from a different place then the other filters. */ - public static boolean filterMixPlaylists(final byte[] bytes) { - final boolean isMixPlaylistFiltered = mixPlaylists.check(bytes).isFiltered(); + public static boolean filterMixPlaylists(final Object conversionContext, final byte[] bytes) { + // Prevent playlist items being hidden, if a mix playlist is present in it. + if (mixPlaylistsExceptions.matches(conversionContext.toString())) + return false; - if (isMixPlaylistFiltered) - LogHelper.printDebug(() -> "Filtered mix playlist"); + if (!mixPlaylists.check(bytes).isFiltered()) return false; + + // Prevent hiding the description of some videos accidentally. + if (mixPlaylistsExceptions2.check(bytes).isFiltered()) return false; + + LogHelper.printDebug(() -> "Filtered mix playlist"); + return true; - return isMixPlaylistFiltered; } public static boolean showWatermark() { From 847cce43f6436c592c680820960f5270f799cb8d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 12 Nov 2023 16:31:44 +0100 Subject: [PATCH 13/21] perf(YouTube - Client spoof): Reduce timeout to fetch storyboard renderer Because this is blocking the UI thread, a short timeout is preferable. --- .../integrations/patches/spoof/SpoofSignaturePatch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 06534d03..af7e7cb0 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -63,7 +63,7 @@ public class SpoofSignaturePatch { private static StoryboardRenderer getRenderer() { if (rendererFuture != null) { try { - return rendererFuture.get(4000, TimeUnit.MILLISECONDS); + return rendererFuture.get(2000, TimeUnit.MILLISECONDS); } catch (TimeoutException ex) { LogHelper.printDebug(() -> "Could not get renderer (get timed out)"); } catch (ExecutionException | InterruptedException ex) { From 828ff6f31e2f15bf50899ab1e403bdc40cc09d07 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 12 Nov 2023 16:40:32 +0100 Subject: [PATCH 14/21] fix(YouTube - Disable suggested video end screen): Properly hide it every time the screen appears Previously, the screen appeared, which a handler was attached to, in order to hide it again, but the handler was removed again from the same screen, so the next time it appeared, it was not hidden. --- .../DisableSuggestedVideoEndScreenPatch.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java index 8b04a192..117238cd 100644 --- a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java @@ -21,17 +21,10 @@ public final class DisableSuggestedVideoEndScreenPatch { if (lastView == parent) return; lastView = (ViewGroup)parent; - lastView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, - int oldRight, int oldBottom) { - // Disable sound effects to prevent the click sound. - imageView.setSoundEffectsEnabled(false); - imageView.performClick(); - - // Remove the listener to prevent it from being called multiple times. - lastView.removeOnLayoutChangeListener(this); - } + lastView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + // Disable sound effects to prevent the click sound. + imageView.setSoundEffectsEnabled(false); + imageView.performClick(); }); } } From 130f629f6bfe7446a32246d05dab15780e760d09 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 12 Nov 2023 16:08:25 +0000 Subject: [PATCH 15/21] chore(release): 0.122.0-dev.1 [skip ci] # [0.122.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.4...v0.122.0-dev.1) (2023-11-12) ### Bug Fixes * **YouTube - Disable suggested video end screen:** Properly hide it every time the screen appears ([828ff6f](https://github.com/ReVanced/revanced-integrations/commit/828ff6f31e2f15bf50899ab1e403bdc40cc09d07)) * **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([5f30100](https://github.com/ReVanced/revanced-integrations/commit/5f30100fd59c1e61c0236bc54cfcd03212994cab)) ### Features * **YouTube:** Add `Enable slide to seek` patch ([b1ce7a7](https://github.com/ReVanced/revanced-integrations/commit/b1ce7a75eba53312d9522c87321ac83cb16d83cf)) * **YouTube:** Add `Remove tracking query parameter` patch ([e84b7b3](https://github.com/ReVanced/revanced-integrations/commit/e84b7b328ea48e86d240d38cf83aa960f87d6902)) ### Performance Improvements * **YouTube - Client spoof:** Reduce timeout to fetch storyboard renderer ([847cce4](https://github.com/ReVanced/revanced-integrations/commit/847cce43f6436c592c680820960f5270f799cb8d)) --- CHANGELOG.md | 19 +++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5768a391..90e4499e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +# [0.122.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.4...v0.122.0-dev.1) (2023-11-12) + + +### Bug Fixes + +* **YouTube - Disable suggested video end screen:** Properly hide it every time the screen appears ([828ff6f](https://github.com/ReVanced/revanced-integrations/commit/828ff6f31e2f15bf50899ab1e403bdc40cc09d07)) +* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([5f30100](https://github.com/ReVanced/revanced-integrations/commit/5f30100fd59c1e61c0236bc54cfcd03212994cab)) + + +### Features + +* **YouTube:** Add `Enable slide to seek` patch ([b1ce7a7](https://github.com/ReVanced/revanced-integrations/commit/b1ce7a75eba53312d9522c87321ac83cb16d83cf)) +* **YouTube:** Add `Remove tracking query parameter` patch ([e84b7b3](https://github.com/ReVanced/revanced-integrations/commit/e84b7b328ea48e86d240d38cf83aa960f87d6902)) + + +### Performance Improvements + +* **YouTube - Client spoof:** Reduce timeout to fetch storyboard renderer ([847cce4](https://github.com/ReVanced/revanced-integrations/commit/847cce43f6436c592c680820960f5270f799cb8d)) + ## [0.121.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.3...v0.121.1-dev.4) (2023-11-11) diff --git a/gradle.properties b/gradle.properties index e24192a9..c4a9e7ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.1-dev.4 +version = 0.122.0-dev.1 From 8b5d2d1871c19421eb39ce38a7039c86e5d8d08b Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 17 Nov 2023 12:21:59 +0200 Subject: [PATCH 16/21] fix(YouTube - Disable resuming Shorts on startup): Adjust patch name (#516) --- .../DisableResumingStartupShortsPlayerPatch.java | 14 ++++++++++++++ .../patches/DisableStartupShortsPlayerPatch.java | 10 ---------- 2 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/app/revanced/integrations/patches/DisableResumingStartupShortsPlayerPatch.java delete mode 100644 app/src/main/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableResumingStartupShortsPlayerPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableResumingStartupShortsPlayerPatch.java new file mode 100644 index 00000000..0fccefea --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/DisableResumingStartupShortsPlayerPatch.java @@ -0,0 +1,14 @@ +package app.revanced.integrations.patches; + +import app.revanced.integrations.settings.SettingsEnum; + +/** @noinspection unused*/ +public class DisableResumingStartupShortsPlayerPatch { + + /** + * Injection point. + */ + public static boolean disableResumingStartupShortsPlayer() { + return SettingsEnum.DISABLE_RESUMING_SHORTS_PLAYER.getBoolean(); + } +} diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java deleted file mode 100644 index aa8c4cf3..00000000 --- a/app/src/main/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.integrations.patches; - -import app.revanced.integrations.settings.SettingsEnum; - -public class DisableStartupShortsPlayerPatch { - //Used by app.revanced.patches.youtube.layout.startupshortsreset.patch.DisableShortsOnStartupPatch - public static boolean disableStartupShortsPlayer() { - return SettingsEnum.DISABLE_RESUMING_SHORTS_PLAYER.getBoolean(); - } -} From 9a6ec6be8c451407b8000822e8a55d8fb9b0f42c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 17 Nov 2023 10:24:57 +0000 Subject: [PATCH 17/21] chore(release): 0.122.0-dev.2 [skip ci] # [0.122.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.1...v0.122.0-dev.2) (2023-11-17) ### Bug Fixes * **YouTube - Disable resuming Shorts on startup:** Adjust patch name ([#516](https://github.com/ReVanced/revanced-integrations/issues/516)) ([8b5d2d1](https://github.com/ReVanced/revanced-integrations/commit/8b5d2d1871c19421eb39ce38a7039c86e5d8d08b)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90e4499e..be08a5e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.122.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.1...v0.122.0-dev.2) (2023-11-17) + + +### Bug Fixes + +* **YouTube - Disable resuming Shorts on startup:** Adjust patch name ([#516](https://github.com/ReVanced/revanced-integrations/issues/516)) ([8b5d2d1](https://github.com/ReVanced/revanced-integrations/commit/8b5d2d1871c19421eb39ce38a7039c86e5d8d08b)) + # [0.122.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.121.1-dev.4...v0.122.0-dev.1) (2023-11-12) diff --git a/gradle.properties b/gradle.properties index c4a9e7ef..d65fd68e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.122.0-dev.1 +version = 0.122.0-dev.2 From a5245b85a829a86b535cf305cac49d14b709708d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 18 Nov 2023 00:50:55 +0100 Subject: [PATCH 18/21] feat(YouTube - Return YouTube Dislike): Support version `18.43.45` and `18.44.41` (#514) Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> --- .../patches/HideBreakingNewsPatch.java | 11 +- .../patches/ReturnYouTubeDislikePatch.java | 326 ++++++++++++------ .../ReturnYouTubeDislikeFilterPatch.java | 2 +- .../patches/spoof/SpoofAppVersionPatch.java | 15 +- .../ReturnYouTubeDislike.java | 163 +++++++-- .../requests/ReturnYouTubeDislikeApi.java | 2 +- .../ReturnYouTubeDislikeSettingsFragment.java | 4 +- .../integrations/utils/ReVancedUtils.java | 2 +- 8 files changed, 376 insertions(+), 149 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/HideBreakingNewsPatch.java b/app/src/main/java/app/revanced/integrations/patches/HideBreakingNewsPatch.java index 465c2836..bb2d76b2 100644 --- a/app/src/main/java/app/revanced/integrations/patches/HideBreakingNewsPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/HideBreakingNewsPatch.java @@ -2,28 +2,27 @@ package app.revanced.integrations.patches; import android.view.View; +import app.revanced.integrations.patches.spoof.SpoofAppVersionPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.ReVancedUtils; public class HideBreakingNewsPatch { /** - * When spoofing to app versions older than 17.30.35, the watch history preview bar uses + * 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 boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory() { - return SettingsEnum.SPOOF_APP_VERSION.getBoolean() - && SettingsEnum.SPOOF_APP_VERSION_TARGET.getString().compareTo("17.30.35") < 0; - } + private static final boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory = + SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("17.31.00"); /** * Injection point. */ public static void hideBreakingNews(View view) { if (!SettingsEnum.HIDE_BREAKING_NEWS.getBoolean() - || isSpoofingOldVersionWithHorizontalCardListWatchHistory()) return; + || isSpoofingOldVersionWithHorizontalCardListWatchHistory) return; ReVancedUtils.hideViewByLayoutParams(view); } } diff --git a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index cd5ef761..c4e39572 100644 --- a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -1,19 +1,20 @@ package app.revanced.integrations.patches; -import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; - import android.graphics.Rect; +import android.graphics.drawable.ShapeDrawable; import android.os.Build; -import android.text.Editable; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.TextWatcher; +import android.text.*; +import android.view.Gravity; import android.view.View; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import app.revanced.integrations.patches.components.ReturnYouTubeDislikeFilterPatch; +import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.shared.PlayerType; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -21,12 +22,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; -import app.revanced.integrations.patches.components.ReturnYouTubeDislikeFilterPatch; -import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.shared.PlayerType; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; +import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; /** * Handles all interaction of UI patch components. @@ -35,13 +31,14 @@ import app.revanced.integrations.utils.ReVancedUtils; * Litho based Shorts player can experience temporarily frozen video playback if the RYD fetch takes too long. * * Temporary work around: - * Enable app spoofing to version 18.20.39 or older, as that uses a non litho Shorts player. + * Enable app spoofing to version 18.33.40 or older, as that uses a non litho Shorts player. * * Permanent fix (yet to be implemented), either of: * - Modify patch to hook onto the Shorts Litho TextView, and update the dislikes asynchronously. * - Find a way to force Litho to rebuild it's component tree * (and use that hook to force the shorts dislikes to update after the fetch is completed). */ +@SuppressWarnings("unused") public class ReturnYouTubeDislikePatch { /** @@ -75,12 +72,18 @@ public class ReturnYouTubeDislikePatch { if (!rydEnabled) { // Must remove all values to protect against using stale data // if the user enables RYD while a video is on screen. - currentVideoData = null; - lastLithoShortsVideoData = null; - lithoShortsShouldUseCurrentData = false; + clearData(); } } + private static void clearData() { + currentVideoData = null; + lastLithoShortsVideoData = null; + lithoShortsShouldUseCurrentData = false; + // Rolling number text should not be cleared, + // as it's used if incognito Short is opened/closed + // while a regular video is on screen. + } // // 17.x non litho regular video player. @@ -137,7 +140,7 @@ public class ReturnYouTubeDislikePatch { if (oldUITextView == null) { return; } - oldUIReplacementSpan = videoData.getDislikesSpanForRegularVideo(oldUIOriginalSpan, false); + oldUIReplacementSpan = videoData.getDislikesSpanForRegularVideo(oldUIOriginalSpan, false, false); if (!oldUIReplacementSpan.equals(oldUITextView.getText())) { oldUITextView.setText(oldUIReplacementSpan); } @@ -188,55 +191,70 @@ public class ReturnYouTubeDislikePatch { /** * Injection point. * + * For Litho segmented buttons and Litho Shorts player. + */ + @NonNull + public static CharSequence onLithoTextLoaded(@NonNull Object conversionContext, + @Nullable AtomicReference textRef, + @NonNull CharSequence original) { + return onLithoTextLoaded(conversionContext, textRef, original, false); + } + + /** * Called when a litho text component is initially created, * and also when a Span is later reused again (such as scrolling off/on screen). * * This method is sometimes called on the main thread, but it usually is called _off_ the main thread. * This method can be called multiple times for the same UI element (including after dislikes was added). * - * @param textRef Cache reference to the like/dislike char sequence, + * @param textRef Optional cache reference to the like/dislike char sequence, * which may or may not be the same as the original span parameter. * If dislikes are added, the atomic reference must be set to the replacement span. - * @param original Original span that was created or reused by Litho. - * @return The original span (if nothing should change), or a replacement span that contains dislikes. + * @param original Original char sequence was created or reused by Litho. + * @param isRollingNumber If the span is for a Rolling Number. + * @return The original char sequence (if nothing should change), or a replacement char sequence that contains dislikes. */ @NonNull - public static CharSequence onLithoTextLoaded(@NonNull Object conversionContext, - @NonNull AtomicReference textRef, - @NonNull CharSequence original) { + private static CharSequence onLithoTextLoaded(@NonNull Object conversionContext, + @Nullable AtomicReference textRef, + @NonNull CharSequence original, + boolean isRollingNumber) { try { if (!SettingsEnum.RYD_ENABLED.getBoolean()) { return original; } String conversionContextString = conversionContext.toString(); - // Remove this log statement after the a/b new litho dislikes is fixed. - LogHelper.printDebug(() -> "conversionContext: " + conversionContextString); - final Spanned replacement; + final CharSequence replacement; if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) { - // Regular video + // Regular video. ReturnYouTubeDislike videoData = currentVideoData; if (videoData == null) { return original; // User enabled RYD while a video was on screen. } - replacement = videoData.getDislikesSpanForRegularVideo((Spannable) original, true); - // When spoofing between 17.09.xx and 17.30.xx the UI is the old layout but uses litho - // and the dislikes is "|dislike_button.eml|" - // but spoofing to that range gives a broken UI layout so no point checking for that. - } else if (conversionContextString.contains("|shorts_dislike_button.eml|")) { + if (!(original instanceof Spanned)) { + original = new SpannableString(original); + } + replacement = videoData.getDislikesSpanForRegularVideo((Spanned) original, + true, isRollingNumber); + + // When spoofing between 17.09.xx and 17.30.xx the UI is the old layout + // but uses litho and the dislikes is "|dislike_button.eml|". + // But spoofing to that range gives a broken UI layout so no point checking for that. + } else if (!isRollingNumber && conversionContextString.contains("|shorts_dislike_button.eml|")) { // Litho Shorts player. if (!SettingsEnum.RYD_SHORTS.getBoolean()) { // Must clear the current video here, otherwise if the user opens a regular video // then opens a litho short (while keeping the regular video on screen), then closes the short, // the original video may show the incorrect dislike value. - currentVideoData = null; + clearData(); return original; } ReturnYouTubeDislike videoData = lastLithoShortsVideoData; if (videoData == null) { // The Shorts litho video id filter did not detect the video id. - // This is normal if in incognito mode, but otherwise is not normal. + // This is normal in incognito mode, but otherwise is abnormal. LogHelper.printDebug(() -> "Cannot modify Shorts litho span, data is null"); return original; } @@ -250,12 +268,12 @@ public class ReturnYouTubeDislikePatch { } LogHelper.printDebug(() -> "Using current video data for litho span"); } - replacement = videoData.getDislikeSpanForShort((Spannable) original); + replacement = videoData.getDislikeSpanForShort((Spanned) original); } else { return original; } - textRef.set(replacement); + if (textRef != null) textRef.set(replacement); return replacement; } catch (Exception ex) { LogHelper.printException(() -> "onLithoTextLoaded failure", ex); @@ -263,6 +281,123 @@ public class ReturnYouTubeDislikePatch { return original; } + // + // Rolling Number + // + + /** + * Current regular video rolling number text, if rolling number is in use. + * This is saved to a field as it's used in every draw() call. + */ + @Nullable + private static volatile CharSequence rollingNumberSpan; + + /** + * Injection point. + */ + public static String onRollingNumberLoaded(@NonNull Object conversionContext, + @NonNull String original) { + try { + CharSequence replacement = onLithoTextLoaded(conversionContext, null, original, true); + if (!replacement.toString().equals(original)) { + rollingNumberSpan = replacement; + return replacement.toString(); + } // Else, the text was not a likes count but instead the view count or something else. + } catch (Exception ex) { + LogHelper.printException(() -> "onRollingNumberLoaded failure", ex); + } + return original; + } + + /** + * Remove Rolling Number text view modifications made by this patch. + * Required as it appears text views can be reused for other rolling numbers (view count, upload time, etc). + */ + private static void removeRollingNumberPatchChanges(TextView view) { + if (view.getCompoundDrawablePadding() != 0) { + LogHelper.printDebug(() -> "Removing rolling number styling from TextView"); + view.setCompoundDrawablePadding(0); + view.setCompoundDrawables(null, null, null, null); + view.setGravity(Gravity.NO_GRAVITY); + view.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT); + view.setSingleLine(false); + } + } + + /** + * Add Rolling Number text view modifications. + */ + private static void addRollingNumberPatchChanges(TextView view) { + if (view.getCompoundDrawablePadding() == 0) { + LogHelper.printDebug(() -> "Adding rolling number styling to TextView"); + // YouTube Rolling Numbers do not use compound drawables or drawable padding. + // + // Single line mode prevents entire words from being entirely clipped, + // and instead only clips the portion of text that runs off. + // The text should not clip due to the empty end padding, + // but use the feature just in case. + view.setSingleLine(true); + // Center align to distribute the horizontal padding. + view.setGravity(Gravity.CENTER); + view.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + ShapeDrawable shapeDrawable = ReturnYouTubeDislike.getLeftSeparatorDrawable(); + view.setCompoundDrawables(shapeDrawable, null, null, null); + view.setCompoundDrawablePadding(ReturnYouTubeDislike.leftSeparatorShapePaddingPixels); + } + } + + /** + * Injection point. + */ + public static CharSequence updateRollingNumber(TextView view, CharSequence original) { + try { + if (!SettingsEnum.RYD_ENABLED.getBoolean()) { + removeRollingNumberPatchChanges(view); + return original; + } + // Called for all instances of RollingNumber, so must check if text is for a dislikes. + // Text will already have the correct content but it's missing the drawable separators. + if (!ReturnYouTubeDislike.isPreviouslyCreatedSegmentedSpan(original.toString())) { + // The text is the video view count, upload time, or some other text. + removeRollingNumberPatchChanges(view); + return original; + } + + CharSequence replacement = rollingNumberSpan; + if (replacement == null) { + // User enabled RYD while a video was open, + // or user opened/closed a Short while a regular video was opened. + LogHelper.printDebug(() -> "Cannot update rolling number (field is null"); + removeRollingNumberPatchChanges(view); + return original; + } + + // TextView does not display the tall left separator correctly, + // as it goes outside the height bounds and messes up the layout. + // Fix this by applying the left separator as a text view compound drawable. + // This creates a new issue as the compound drawable is not taken into the + // layout width sizing, but that is fixed in the span itself where it uses a blank + // padding string that adds to the layout width but is later ignored during UI drawing. + if (SettingsEnum.RYD_COMPACT_LAYOUT.getBoolean()) { + // Do not apply any TextView changes, and text should always fit without clipping. + removeRollingNumberPatchChanges(view); + } else { + addRollingNumberPatchChanges(view); + } + + // Remove any padding set by Rolling Number. + view.setPadding(0, 0, 0, 0); + + // When displaying dislikes, the rolling animation is not visually correct + // and the dislikes always animate (even though the dislike count has not changed). + // The animation is caused by an image span attached to the span, + // and using only the modified segmented span prevents the animation from showing. + return replacement; + } catch (Exception ex) { + LogHelper.printException(() -> "updateRollingNumber failure", ex); + return original; + } + } // // Non litho Shorts player. @@ -301,7 +436,7 @@ public class ReturnYouTubeDislikePatch { if (!SettingsEnum.RYD_SHORTS.getBoolean()) { // Must clear the data here, in case a new video was loaded while PlayerType // suggested the video was not a short (can happen when spoofing to an old app version). - currentVideoData = null; + clearData(); return false; } LogHelper.printDebug(() -> "setShortsDislikes"); @@ -405,90 +540,59 @@ public class ReturnYouTubeDislikePatch { * Injection point. Uses 'playback response' video id hook to preload RYD. */ public static void preloadVideoId(@NonNull String videoId, boolean videoIsOpeningOrPlaying) { - // Shorts shelf in home and subscription feed causes player response hook to be called, - // and the 'is opening/playing' parameter will be false. - // This hook will be called again when the Short is actually opened. - if (!videoIsOpeningOrPlaying || !SettingsEnum.RYD_ENABLED.getBoolean()) { - return; + try { + // Shorts shelf in home and subscription feed causes player response hook to be called, + // and the 'is opening/playing' parameter will be false. + // This hook will be called again when the Short is actually opened. + if (!videoIsOpeningOrPlaying || !SettingsEnum.RYD_ENABLED.getBoolean()) { + return; + } + if (!SettingsEnum.RYD_SHORTS.getBoolean() && PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized()) { + return; + } + if (videoId.equals(lastPrefetchedVideoId)) { + return; + } + lastPrefetchedVideoId = videoId; + LogHelper.printDebug(() -> "Prefetching RYD for video: " + videoId); + ReturnYouTubeDislike.getFetchForVideoId(videoId); + } catch (Exception ex) { + LogHelper.printException(() -> "preloadVideoId failure", ex); } - if (!SettingsEnum.RYD_SHORTS.getBoolean() && PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized()) { - return; - } - if (videoId.equals(lastPrefetchedVideoId)) { - return; - } - lastPrefetchedVideoId = videoId; - LogHelper.printDebug(() -> "Prefetching RYD for video: " + videoId); - ReturnYouTubeDislike.getFetchForVideoId(videoId); } /** * Injection point. Uses 'current playing' video id hook. Always called on main thread. */ public static void newVideoLoaded(@NonNull String videoId) { - newVideoLoaded(videoId, false); - } - - /** - * Called both on and off main thread. - * - * @param isShortsLithoVideoId If the video id is from {@link ReturnYouTubeDislikeFilterPatch}. - * if true, then the video id can be null indicating the filter did - * not find any video id. - */ - public static void newVideoLoaded(@Nullable String videoId, boolean isShortsLithoVideoId) { try { if (!SettingsEnum.RYD_ENABLED.getBoolean()) return; + Objects.requireNonNull(videoId); PlayerType currentPlayerType = PlayerType.getCurrent(); final boolean isNoneHiddenOrSlidingMinimized = currentPlayerType.isNoneHiddenOrSlidingMinimized(); if (isNoneHiddenOrSlidingMinimized && !SettingsEnum.RYD_SHORTS.getBoolean()) { // Must clear here, otherwise the wrong data can be used for a minimized regular video. - currentVideoData = null; + clearData(); return; } - if (isShortsLithoVideoId) { - // Litho Shorts video. - if (videoIdIsSame(lastLithoShortsVideoData, videoId)) { - return; - } - if (videoId == null) { - // Litho filter did not detect the video id. App is in incognito mode, - // or the proto buffer structure was changed and the video id is no longer present. - // Must clear both currently playing and last litho data otherwise the - // next regular video may use the wrong data. - LogHelper.printDebug(() -> "Litho filter did not find any video ids"); - currentVideoData = null; - lastLithoShortsVideoData = null; - lithoShortsShouldUseCurrentData = false; - return; - } - ReturnYouTubeDislike videoData = ReturnYouTubeDislike.getFetchForVideoId(videoId); - videoData.setVideoIdIsShort(true); - lastLithoShortsVideoData = videoData; - lithoShortsShouldUseCurrentData = false; - } else { - Objects.requireNonNull(videoId); - // All other playback (including non-litho Shorts). - if (videoIdIsSame(currentVideoData, videoId)) { - return; - } - ReturnYouTubeDislike data = ReturnYouTubeDislike.getFetchForVideoId(videoId); - // Pre-emptively set the data to short status. - // Required to prevent Shorts data from being used on a minimized video in incognito mode. - if (isNoneHiddenOrSlidingMinimized) { - data.setVideoIdIsShort(true); - } - currentVideoData = data; + if (videoIdIsSame(currentVideoData, videoId)) { + return; } + LogHelper.printDebug(() -> "New video id: " + videoId + " playerType: " + currentPlayerType); - LogHelper.printDebug(() -> "New video id: " + videoId + " playerType: " + currentPlayerType - + " isShortsLithoHook: " + isShortsLithoVideoId); + ReturnYouTubeDislike data = ReturnYouTubeDislike.getFetchForVideoId(videoId); + // Pre-emptively set the data to short status. + // Required to prevent Shorts data from being used on a minimized video in incognito mode. + if (isNoneHiddenOrSlidingMinimized) { + data.setVideoIdIsShort(true); + } + currentVideoData = data; // Current video id hook can be called out of order with the non litho Shorts text view hook. // Must manually update again here. - if (!isShortsLithoVideoId && isNoneHiddenOrSlidingMinimized) { + if (isNoneHiddenOrSlidingMinimized) { updateOnScreenShortsTextViews(true); } } catch (Exception ex) { @@ -496,6 +600,26 @@ public class ReturnYouTubeDislikePatch { } } + public static void setLastLithoShortsVideoId(@Nullable String videoId) { + if (videoIdIsSame(lastLithoShortsVideoData, videoId)) { + return; + } + if (videoId == null) { + // Litho filter did not detect the video id. App is in incognito mode, + // or the proto buffer structure was changed and the video id is no longer present. + // Must clear both currently playing and last litho data otherwise the + // next regular video may use the wrong data. + LogHelper.printDebug(() -> "Litho filter did not find any video ids"); + clearData(); + return; + } + LogHelper.printDebug(() -> "New litho Shorts video id: " + videoId); + ReturnYouTubeDislike videoData = ReturnYouTubeDislike.getFetchForVideoId(videoId); + videoData.setVideoIdIsShort(true); + lastLithoShortsVideoData = videoData; + lithoShortsShouldUseCurrentData = false; + } + private static boolean videoIdIsSame(@Nullable ReturnYouTubeDislike fetch, @Nullable String videoId) { return (fetch == null && videoId == null) || (fetch != null && fetch.getVideoId().equals(videoId)); diff --git a/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java index b1ff2d2e..48c44f36 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java @@ -93,7 +93,7 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter { // Must pass a null id to correctly clear out the current video data. // Otherwise if a Short is opened in non-incognito, then incognito is enabled and another Short is opened, // the new incognito Short will show the old prior data. - ReturnYouTubeDislikePatch.newVideoLoaded(matchedVideoId, true); + ReturnYouTubeDislikePatch.setLastLithoShortsVideoId(matchedVideoId); } return false; diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java index c43d6031..a861708f 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java @@ -4,10 +4,19 @@ import app.revanced.integrations.settings.SettingsEnum; public class SpoofAppVersionPatch { + private static final boolean SPOOF_APP_VERSION_ENABLED = SettingsEnum.SPOOF_APP_VERSION.getBoolean(); + private static final String SPOOF_APP_VERSION_TARGET = SettingsEnum.SPOOF_APP_VERSION_TARGET.getString(); + + /** + * Injection point + */ public static String getYouTubeVersionOverride(String version) { - if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()) { - return SettingsEnum.SPOOF_APP_VERSION_TARGET.getString(); - } + if (SPOOF_APP_VERSION_ENABLED) return SPOOF_APP_VERSION_TARGET; return version; } + + public static boolean isSpoofingToEqualOrLessThan(String version) { + return SPOOF_APP_VERSION_ENABLED && SPOOF_APP_VERSION_TARGET.compareTo(version) <= 0; + } + } diff --git a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java index 98907086..f1ed3d12 100644 --- a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java @@ -17,6 +17,7 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; +import android.text.style.ReplacementSpan; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -69,7 +70,7 @@ public class ReturnYouTubeDislike { * Must be less than 5 seconds, as per: * https://developer.android.com/topic/performance/vitals/anr */ - private static final long MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH = 4500; + private static final long MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH = 4000; /** * How long to retain successful RYD fetches. @@ -84,9 +85,9 @@ public class ReturnYouTubeDislike { /** * Unique placeholder character, used to detect if a segmented span already has dislikes added to it. - * Can be any almost any non-visible character. + * Must be something YouTube is unlikely to use, as it's searched for in all usage of Rolling Number. */ - private static final char MIDDLE_SEPARATOR_CHARACTER = '\u2009'; // 'narrow space' character + private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye' /** * Cached lookup of all video ids. @@ -115,6 +116,12 @@ public class ReturnYouTubeDislike { private static final Rect leftSeparatorBounds; private static final Rect middleSeparatorBounds; + /** + * Left separator horizontal padding for Rolling Number layout. + */ + public static final int leftSeparatorShapePaddingPixels; + private static final ShapeDrawable leftSeparatorShape; + static { DisplayMetrics dp = Objects.requireNonNull(ReVancedUtils.getContext()).getResources().getDisplayMetrics(); @@ -124,6 +131,11 @@ public class ReturnYouTubeDislike { final int middleSeparatorSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp); middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize); + + leftSeparatorShapePaddingPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10.0f, dp); + + leftSeparatorShape = new ShapeDrawable(new RectShape()); + leftSeparatorShape.setBounds(leftSeparatorBounds); } private final String videoId; @@ -167,19 +179,31 @@ public class ReturnYouTubeDislike { @GuardedBy("this") private SpannableString replacementLikeDislikeSpan; + private static int getSeparatorColor() { + return ThemeHelper.isDarkTheme() + ? 0x33FFFFFF // transparent dark gray + : 0xFFD9D9D9; // light gray + } + + public static ShapeDrawable getLeftSeparatorDrawable() { + leftSeparatorShape.getPaint().setColor(getSeparatorColor()); + return leftSeparatorShape; + } + /** * @param isSegmentedButton If UI is using the segmented single UI component for both like and dislike. */ @NonNull - private static SpannableString createDislikeSpan(@NonNull Spanned oldSpannable, boolean isSegmentedButton, @NonNull RYDVoteData voteData) { + private static SpannableString createDislikeSpan(@NonNull Spanned oldSpannable, + boolean isSegmentedButton, + boolean isRollingNumber, + @NonNull RYDVoteData voteData) { if (!isSegmentedButton) { // Simple replacement of 'dislike' with a number/percentage. return newSpannableWithDislikes(oldSpannable, voteData); } - // Note: Some locales use right to left layout (arabic, hebrew, etc), - // and care must be taken to retain the existing RTL encoding character on the likes string, - // otherwise text will incorrectly show as left to right. + // Note: Some locales use right to left layout (Arabic, Hebrew, etc). // If making changes to this code, change device settings to a RTL language and verify layout is correct. String oldLikesString = oldSpannable.toString(); @@ -202,21 +226,25 @@ public class ReturnYouTubeDislike { SpannableStringBuilder builder = new SpannableStringBuilder(); final boolean compactLayout = SettingsEnum.RYD_COMPACT_LAYOUT.getBoolean(); - final int separatorColor = ThemeHelper.isDarkTheme() - ? 0x29AAAAAA // transparent dark gray - : 0xFFD9D9D9; // light gray if (!compactLayout) { - // left separator String leftSeparatorString = ReVancedUtils.isRightToLeftTextLayout() - ? "\u200F " // u200F = right to left character - : "\u200E "; // u200E = left to right character - Spannable leftSeparatorSpan = new SpannableString(leftSeparatorString); - ShapeDrawable shapeDrawable = new ShapeDrawable(new RectShape()); - shapeDrawable.getPaint().setColor(separatorColor); - shapeDrawable.setBounds(leftSeparatorBounds); - leftSeparatorSpan.setSpan(new VerticallyCenteredImageSpan(shapeDrawable), 1, 2, - Spannable.SPAN_INCLUSIVE_EXCLUSIVE); // drawable cannot overwrite RTL or LTR character + ? "\u200F" // u200F = right to left character + : "\u200E"; // u200E = left to right character + final Spannable leftSeparatorSpan; + if (isRollingNumber) { + leftSeparatorSpan = new SpannableString(leftSeparatorString); + } else { + leftSeparatorString += " "; + leftSeparatorSpan = new SpannableString(leftSeparatorString); + // Styling spans cannot overwrite RTL or LTR character. + leftSeparatorSpan.setSpan( + new VerticallyCenteredImageSpan(getLeftSeparatorDrawable(), false), + 1, 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + leftSeparatorSpan.setSpan( + new FixedWidthEmptySpan(leftSeparatorShapePaddingPixels), + 2, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + } builder.append(leftSeparatorSpan); } @@ -230,21 +258,41 @@ public class ReturnYouTubeDislike { final int shapeInsertionIndex = middleSeparatorString.length() / 2; Spannable middleSeparatorSpan = new SpannableString(middleSeparatorString); ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape()); - shapeDrawable.getPaint().setColor(separatorColor); + shapeDrawable.getPaint().setColor(getSeparatorColor()); shapeDrawable.setBounds(middleSeparatorBounds); - middleSeparatorSpan.setSpan(new VerticallyCenteredImageSpan(shapeDrawable), shapeInsertionIndex, shapeInsertionIndex + 1, - Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + // Use original text width if using compact layout with Rolling Number, + // as there is no empty padding to allow any layout width differences. + middleSeparatorSpan.setSpan( + new VerticallyCenteredImageSpan(shapeDrawable, isRollingNumber && compactLayout), + shapeInsertionIndex, shapeInsertionIndex + 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); builder.append(middleSeparatorSpan); // dislikes builder.append(newSpannableWithDislikes(oldSpannable, voteData)); + // Add some padding for Rolling Number segmented span. + // Use an empty width span, as the layout uses the measured text width and not the + // actual span width. So adding padding and then removing it while drawing gives some + // extra wiggle room for the left separator drawable (which is not included in layout width). + if (isRollingNumber && !compactLayout) { + // To test this, set the device system font to the smallest available. + // If text clipping still occurs, then increase the number of padding spaces below. + // Any extra width will be padded around the like/dislike string + // as it's set to center text alignment. + Spannable rightPaddingString = new SpannableString(" "); + rightPaddingString.setSpan(new FixedWidthEmptySpan(0), 0, + rightPaddingString.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + builder.append(rightPaddingString); + } + return new SpannableString(builder); } - // Alternatively, this could check if the span contains one of the custom created spans, but this is simple and quick. - private static boolean isPreviouslyCreatedSegmentedSpan(@NonNull Spanned span) { - return span.toString().indexOf(MIDDLE_SEPARATOR_CHARACTER) != -1; + /** + * @return If the text is likely for a previously created likes/dislikes segmented span. + */ + public static boolean isPreviouslyCreatedSegmentedSpan(@NonNull String text) { + return text.indexOf(MIDDLE_SEPARATOR_CHARACTER) >= 0; } /** @@ -429,8 +477,10 @@ public class ReturnYouTubeDislike { * @return the replacement span containing dislikes, or the original span if RYD is not available. */ @NonNull - public synchronized Spanned getDislikesSpanForRegularVideo(@NonNull Spanned original, boolean isSegmentedButton) { - return waitForFetchAndUpdateReplacementSpan(original, isSegmentedButton, false); + public synchronized Spanned getDislikesSpanForRegularVideo(@NonNull Spanned original, + boolean isSegmentedButton, + boolean isRollingNumber) { + return waitForFetchAndUpdateReplacementSpan(original, isSegmentedButton, isRollingNumber,false); } /** @@ -438,12 +488,13 @@ public class ReturnYouTubeDislike { */ @NonNull public synchronized Spanned getDislikeSpanForShort(@NonNull Spanned original) { - return waitForFetchAndUpdateReplacementSpan(original, false, true); + return waitForFetchAndUpdateReplacementSpan(original, false, false, true); } @NonNull private Spanned waitForFetchAndUpdateReplacementSpan(@NonNull Spanned original, boolean isSegmentedButton, + boolean isRollingNumber, boolean spanIsForShort) { try { RYDVoteData votingData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH); @@ -481,7 +532,7 @@ public class ReturnYouTubeDislike { return replacementLikeDislikeSpan; } } - if (isSegmentedButton && isPreviouslyCreatedSegmentedSpan(original)) { + if (isSegmentedButton && isPreviouslyCreatedSegmentedSpan(original.toString())) { // need to recreate using original, as original has prior outdated dislike values if (originalDislikeSpan == null) { // Should never happen. @@ -497,7 +548,7 @@ public class ReturnYouTubeDislike { votingData.updateUsingVote(userVote); } originalDislikeSpan = original; - replacementLikeDislikeSpan = createDislikeSpan(original, isSegmentedButton, votingData); + replacementLikeDislikeSpan = createDislikeSpan(original, isSegmentedButton, isRollingNumber, votingData); LogHelper.printDebug(() -> "Replaced: '" + originalDislikeSpan + "' with: '" + replacementLikeDislikeSpan + "'" + " using video: " + videoId); @@ -567,9 +618,44 @@ public class ReturnYouTubeDislike { } } +/** + * Styles a Spannable with an empty fixed width. + */ +class FixedWidthEmptySpan extends ReplacementSpan { + final int fixedWidth; + /** + * @param fixedWith Fixed width in screen pixels. + */ + FixedWidthEmptySpan(int fixedWith) { + this.fixedWidth = fixedWith; + if (fixedWith < 0) throw new IllegalArgumentException(); + } + @Override + public int getSize(@NonNull Paint paint, @NonNull CharSequence text, + int start, int end, @Nullable Paint.FontMetricsInt fontMetrics) { + return fixedWidth; + } + @Override + public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, + float x, int top, int y, int bottom, @NonNull Paint paint) { + // Nothing to draw. + } +} + +/** + * Vertically centers a Spanned Drawable. + */ class VerticallyCenteredImageSpan extends ImageSpan { - public VerticallyCenteredImageSpan(Drawable drawable) { + final boolean useOriginalWidth; + + /** + * @param useOriginalWidth Use the original layout width of the text this span is applied to, + * and not the bounds of the Drawable. Drawable is always displayed using it's own bounds, + * and this setting only affects the layout width of the entire span. + */ + public VerticallyCenteredImageSpan(Drawable drawable, boolean useOriginalWidth) { super(drawable); + this.useOriginalWidth = useOriginalWidth; } @Override @@ -581,13 +667,17 @@ class VerticallyCenteredImageSpan extends ImageSpan { Paint.FontMetricsInt paintMetrics = paint.getFontMetricsInt(); final int fontHeight = paintMetrics.descent - paintMetrics.ascent; final int drawHeight = bounds.bottom - bounds.top; + final int halfDrawHeight = drawHeight / 2; final int yCenter = paintMetrics.ascent + fontHeight / 2; - fontMetrics.ascent = yCenter - drawHeight / 2; + fontMetrics.ascent = yCenter - halfDrawHeight; fontMetrics.top = fontMetrics.ascent; - fontMetrics.bottom = yCenter + drawHeight / 2; + fontMetrics.bottom = yCenter + halfDrawHeight; fontMetrics.descent = fontMetrics.bottom; } + if (useOriginalWidth) { + return (int) paint.measureText(text, start, end); + } return bounds.right; } @@ -600,8 +690,13 @@ class VerticallyCenteredImageSpan extends ImageSpan { final int fontHeight = paintMetrics.descent - paintMetrics.ascent; final int yCenter = y + paintMetrics.descent - fontHeight / 2; final Rect drawBounds = drawable.getBounds(); + float translateX = x; + if (useOriginalWidth) { + // Horizontally center the drawable in the same space as the original text. + translateX += (paint.measureText(text, start, end) - (drawBounds.right - drawBounds.left)) / 2; + } final int translateY = yCenter - (drawBounds.bottom - drawBounds.top) / 2; - canvas.translate(x, translateY); + canvas.translate(translateX, translateY); drawable.draw(canvas); canvas.restore(); } diff --git a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java index 9403ee0c..8daa3805 100644 --- a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java +++ b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java @@ -38,7 +38,7 @@ public class ReturnYouTubeDislikeApi { * {@link #fetchVotes(String)} HTTP read timeout. * To locally debug and force timeouts, change this to a very small number (ie: 100) */ - private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 5 * 1000; // 5 Seconds. + private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 4 * 1000; // 4 Seconds. /** * Default connection and response timeout for voting and registration. diff --git a/app/src/main/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java b/app/src/main/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java index 45fffc2c..e269c932 100644 --- a/app/src/main/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java +++ b/app/src/main/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java @@ -13,6 +13,7 @@ import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import app.revanced.integrations.patches.ReturnYouTubeDislikePatch; +import app.revanced.integrations.patches.spoof.SpoofAppVersionPatch; import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeApi; import app.revanced.integrations.settings.SettingsEnum; @@ -21,8 +22,7 @@ import app.revanced.integrations.settings.SharedPrefCategory; public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment { private static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER = - SettingsEnum.SPOOF_APP_VERSION.getBoolean() - && SettingsEnum.SPOOF_APP_VERSION_TARGET.getString().compareTo("18.33.40") <= 0; + SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("18.33.40"); /** * If dislikes are shown on Shorts. diff --git a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java index 918d55b7..6b94bbd9 100644 --- a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java +++ b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java @@ -92,7 +92,7 @@ public class ReVancedUtils { * All tasks run at max thread priority. */ private static final ThreadPoolExecutor backgroundThreadPool = new ThreadPoolExecutor( - 2, // 2 threads always ready to go + 3, // 3 threads always ready to go Integer.MAX_VALUE, 10, // For any threads over the minimum, keep them alive 10 seconds after they go idle TimeUnit.SECONDS, From 0978e6465552d553347ac96c623fa403ebaacd85 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 17 Nov 2023 23:53:38 +0000 Subject: [PATCH 19/21] chore(release): 0.122.0-dev.3 [skip ci] # [0.122.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.2...v0.122.0-dev.3) (2023-11-17) ### Features * **YouTube - Return YouTube Dislike:** Support version `18.43.45` and `18.44.41` ([#514](https://github.com/ReVanced/revanced-integrations/issues/514)) ([a5245b8](https://github.com/ReVanced/revanced-integrations/commit/a5245b85a829a86b535cf305cac49d14b709708d)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be08a5e0..46fe2918 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.122.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.2...v0.122.0-dev.3) (2023-11-17) + + +### Features + +* **YouTube - Return YouTube Dislike:** Support version `18.43.45` and `18.44.41` ([#514](https://github.com/ReVanced/revanced-integrations/issues/514)) ([a5245b8](https://github.com/ReVanced/revanced-integrations/commit/a5245b85a829a86b535cf305cac49d14b709708d)) + # [0.122.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.1...v0.122.0-dev.2) (2023-11-17) diff --git a/gradle.properties b/gradle.properties index d65fd68e..c54702b1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.122.0-dev.2 +version = 0.122.0-dev.3 From 726a2510a5b28da3afb77c7f5fdda87a3bd2c809 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 18 Nov 2023 04:34:16 +0100 Subject: [PATCH 20/21] feat(YouTube - Hide layout components): Hide description components --- .../DescriptionComponentsFilter.java | 69 +++++++++++++++++++ .../components/LayoutComponentsFilter.java | 9 +-- .../integrations/settings/SettingsEnum.java | 8 ++- 3 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/app/revanced/integrations/patches/components/DescriptionComponentsFilter.java diff --git a/app/src/main/java/app/revanced/integrations/patches/components/DescriptionComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/DescriptionComponentsFilter.java new file mode 100644 index 00000000..ccdd3210 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/components/DescriptionComponentsFilter.java @@ -0,0 +1,69 @@ +package app.revanced.integrations.patches.components; + +import androidx.annotation.Nullable; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.StringTrieSearch; + +final class DescriptionComponentsFilter extends Filter { + + private final StringTrieSearch exceptions = new StringTrieSearch(); + + public DescriptionComponentsFilter() { + exceptions.addPatterns( + "compact_channel", + "description", + "grid_video", + "inline_expander", + "metadata" + ); + + final StringFilterGroup chapterSection = new StringFilterGroup( + SettingsEnum.HIDE_CHAPTERS, + "macro_markers_carousel" + ); + + final StringFilterGroup infoCardsSection = new StringFilterGroup( + SettingsEnum.HIDE_INFO_CARDS_SECTION, + "infocards_section" + ); + + final StringFilterGroup gameSection = new StringFilterGroup( + SettingsEnum.HIDE_GAME_SECTION, + "gaming_section" + ); + + final StringFilterGroup musicSection = new StringFilterGroup( + SettingsEnum.HIDE_MUSIC_SECTION, + "music_section", + "video_attributes_section" + ); + + final StringFilterGroup podcastSection = new StringFilterGroup( + SettingsEnum.HIDE_PODCAST_SECTION, + "playlist_section" + ); + + final StringFilterGroup transcriptSection = new StringFilterGroup( + SettingsEnum.HIDE_TRANSCIPT_SECTION, + "transcript_section" + ); + + pathFilterGroupList.addAll( + chapterSection, + infoCardsSection, + gameSection, + musicSection, + podcastSection, + transcriptSection + ); + } + + + @Override + boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) { + if (exceptions.matches(path)) return false; + + return super.isFiltered(path, identifier, protobufBufferArray, matchedList, matchedGroup, matchedIndex); + } +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 6589976a..7603bc68 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -136,11 +136,6 @@ public final class LayoutComponentsFilter extends Filter { "quality_sheet_footer" ); - final var chapters = new StringFilterGroup( - SettingsEnum.HIDE_CHAPTERS, - "macro_markers_carousel" - ); - final var channelBar = new StringFilterGroup( SettingsEnum.HIDE_CHANNEL_BAR, "channel_bar" @@ -226,8 +221,7 @@ public final class LayoutComponentsFilter extends Filter { this.identifierFilterGroupList.addAll( graySeparator, - chipsShelf, - chapters + chipsShelf ); } @@ -249,7 +243,6 @@ public final class LayoutComponentsFilter extends Filter { return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex); } - /** * Injection point. * Called from a different place then the other filters. diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index d830d06b..fe011e47 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -72,7 +72,6 @@ public enum SettingsEnum { HIDE_CAST_BUTTON("revanced_hide_cast_button", BOOLEAN, TRUE, true), HIDE_CHANNEL_BAR("revanced_hide_channel_bar", BOOLEAN, FALSE), HIDE_CHANNEL_MEMBER_SHELF("revanced_hide_channel_member_shelf", BOOLEAN, TRUE), - HIDE_CHAPTERS("revanced_hide_chapters", BOOLEAN, TRUE), HIDE_CHIPS_SHELF("revanced_hide_chips_shelf", BOOLEAN, TRUE), HIDE_COMMENTS_SECTION("revanced_hide_comments_section", BOOLEAN, FALSE, true), HIDE_COMMUNITY_GUIDELINES("revanced_hide_community_guidelines", BOOLEAN, TRUE), @@ -123,6 +122,13 @@ public enum SettingsEnum { TABLET_LAYOUT("revanced_tablet_layout", BOOLEAN, FALSE, true, "revanced_tablet_layout_user_dialog_message"), USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true), WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true), + // Description + HIDE_CHAPTERS("revanced_hide_chapters", BOOLEAN, TRUE), + HIDE_INFO_CARDS_SECTION("revanced_hide_info_cards_section", BOOLEAN, TRUE), + HIDE_GAME_SECTION("revanced_hide_game_section", BOOLEAN, TRUE), + HIDE_MUSIC_SECTION("revanced_hide_music_section", BOOLEAN, TRUE), + HIDE_PODCAST_SECTION("revanced_hide_podcast_section", BOOLEAN, TRUE), + HIDE_TRANSCIPT_SECTION("revanced_hide_transcript_section", BOOLEAN, TRUE), // Shorts HIDE_SHORTS("revanced_hide_shorts", BOOLEAN, FALSE, true), From 25dc754ff5286e86156c95dc7b38f279cbd556cf Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 18 Nov 2023 04:08:29 +0000 Subject: [PATCH 21/21] chore(release): 0.122.0-dev.4 [skip ci] # [0.122.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.3...v0.122.0-dev.4) (2023-11-18) ### Features * **YouTube - Hide layout components:** Hide description components ([726a251](https://github.com/ReVanced/revanced-integrations/commit/726a2510a5b28da3afb77c7f5fdda87a3bd2c809)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46fe2918..9619f98d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.122.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.3...v0.122.0-dev.4) (2023-11-18) + + +### Features + +* **YouTube - Hide layout components:** Hide description components ([726a251](https://github.com/ReVanced/revanced-integrations/commit/726a2510a5b28da3afb77c7f5fdda87a3bd2c809)) + # [0.122.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.122.0-dev.2...v0.122.0-dev.3) (2023-11-17) diff --git a/gradle.properties b/gradle.properties index c54702b1..b6ce6493 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.122.0-dev.3 +version = 0.122.0-dev.4