diff --git a/integrations/java/app/revanced/integrations/patches/GeneralAdsPatch.java b/integrations/java/app/revanced/integrations/patches/GeneralAdsPatch.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integrations/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/integrations/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 92a65a2c29..711370848b 100644 --- a/integrations/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/integrations/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -2,22 +2,21 @@ import android.os.Build; -import android.view.View; import androidx.annotation.RequiresApi; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.ReVancedUtils; +@RequiresApi(api = Build.VERSION_CODES.N) public final class LayoutComponentsFilter extends Filter { private final String[] exceptions; private final CustomFilterGroup custom; - // region Mix playlists - private final ByteArrayAsStringFilterGroup mixPlaylists; - private final ByteArrayAsStringFilterGroup imageHosting; - - // endregion + private static final ByteArrayAsStringFilterGroup mixPlaylists = new ByteArrayAsStringFilterGroup( + SettingsEnum.HIDE_MIX_PLAYLISTS, + "&list=" + ); @RequiresApi(api = Build.VERSION_CODES.N) public LayoutComponentsFilter() { @@ -137,21 +136,6 @@ public LayoutComponentsFilter() { "cell_divider" // layout residue (gray line above the buttoned ad), ); - // region Mix playlists - - mixPlaylists = new ByteArrayAsStringFilterGroup( - SettingsEnum.HIDE_MIX_PLAYLISTS, - "&list=", - "YouTube Music" - ); - - imageHosting = new ByteArrayAsStringFilterGroup( - SettingsEnum.HIDE_MIX_PLAYLISTS, // Unused - "ggpht.com" - ); - - // endregion - this.pathFilterGroups.addAll( channelBar, communityPosts, @@ -174,27 +158,7 @@ public LayoutComponentsFilter() { channelMemberShelf ); - final var carouselAd = new StringFilterGroup( - SettingsEnum.HIDE_GENERAL_ADS, - "carousel_ad" - ); - - this.identifierFilterGroups.addAll( - graySeparator, - carouselAd - ); - } - - private boolean isMixPlaylistFiltered(final byte[] _protobufBufferArray) { - if (!mixPlaylists.isEnabled()) return false; - - // Two checks are required to prevent false positives. - - // First check if the current buffer potentially contains a mix playlist. - if (!mixPlaylists.check(_protobufBufferArray).isFiltered()) return false; - - // Ensure that the buffer actually contains a mix playlist. - return imageHosting.check(_protobufBufferArray).isFiltered(); + this.identifierFilterGroups.addAll(graySeparator); } @Override @@ -205,18 +169,12 @@ public boolean isFiltered(final String path, final String identifier, final byte if (ReVancedUtils.containsAny(path, exceptions)) return false; // Exceptions are not filtered. - if (super.isFiltered(path, identifier, _protobufBufferArray)) - return true; - - return isMixPlaylistFiltered(_protobufBufferArray); + return super.isFiltered(path, identifier, _protobufBufferArray); } - /** - * Hide the view, which shows ads in the homepage. - * - * @param view The view, which shows ads. - */ - public static void hideAdAttributionView(View view) { - ReVancedUtils.hideViewBy1dpUnderCondition(SettingsEnum.HIDE_GENERAL_ADS, view); + + // Called from a different place then the other filters. + public static boolean filterMixPlaylists(final byte[] bytes) { + return mixPlaylists.isEnabled() && mixPlaylists.check(bytes).isFiltered(); } } diff --git a/integrations/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/integrations/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index 95c68b410b..8e10eea916 100644 --- a/integrations/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/integrations/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -1,11 +1,9 @@ package app.revanced.integrations.patches.components; import android.os.Build; + import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -14,6 +12,10 @@ import java.util.Spliterator; import java.util.function.Consumer; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; + abstract class FilterGroup { final static class FilterGroupResult { private final boolean filtered; @@ -49,7 +51,7 @@ public FilterGroup(final SettingsEnum setting, final T... filters) { } public boolean isEnabled() { - return setting.getBoolean(); + return setting == null || setting.getBoolean(); } public abstract FilterGroupResult check(final T stack); @@ -208,7 +210,7 @@ abstract class Filter { /** * Check if the given path, identifier or protobuf buffer is filtered by any - * {@link FilterGroup}. + * {@link FilterGroup}. Method is called off the main thread. * * @return True if filtered, false otherwise. */ @@ -239,9 +241,12 @@ public final class LithoFilterPatch { new DummyFilter() // Replaced by patch. }; + /** + * Injection point. Called off the main thread. + */ @SuppressWarnings("unused") public static boolean filter(final StringBuilder pathBuilder, final String identifier, - final ByteBuffer protobufBuffer) { + final ByteBuffer protobufBuffer) { // TODO: Maybe this can be moved to the Filter class, to prevent unnecessary // string creation // because some filters might not need the path. diff --git a/integrations/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java b/integrations/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java new file mode 100644 index 0000000000..a500c7baab --- /dev/null +++ b/integrations/java/app/revanced/integrations/patches/components/VideoQualityMenuFilterPatch.java @@ -0,0 +1,23 @@ +package app.revanced.integrations.patches.components; + +import app.revanced.integrations.settings.SettingsEnum; + +// Abuse LithoFilter for OldVideoQualityMenuPatch. +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() { + pathFilterGroups.addAll(new StringFilterGroup( + SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU, + "quick_quality_sheet_content.eml-js" + )); + } + + @Override + boolean isFiltered(final String path, final String identifier, final byte[] protobufBufferArray) { + isVideoQualityMenuVisible = super.isFiltered(path, identifier, protobufBufferArray); + + return false; + } +} diff --git a/integrations/java/app/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch.java b/integrations/java/app/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch.java new file mode 100644 index 0000000000..f01d30d152 --- /dev/null +++ b/integrations/java/app/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch.java @@ -0,0 +1,21 @@ +package app.revanced.integrations.patches.components; + +// Abuse LithoFilter for CustomVideoSpeedPatch. +public final class VideoSpeedMenuFilterPatch 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 isVideoSpeedMenuVisible; + + public VideoSpeedMenuFilterPatch() { + pathFilterGroups.addAll(new StringFilterGroup( + null, + "playback_speed_sheet_content.eml-js" + )); + } + + @Override + boolean isFiltered(final String path, final String identifier, final byte[] protobufBufferArray) { + isVideoSpeedMenuVisible = super.isFiltered(path, identifier, protobufBufferArray); + + return false; + } +} diff --git a/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java b/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java deleted file mode 100644 index 71899a7a1b..0000000000 --- a/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java +++ /dev/null @@ -1,35 +0,0 @@ -package app.revanced.integrations.patches.playback.quality; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; - -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.utils.LogHelper; - -public class OldQualityLayoutPatch { - public static void showOldQualityMenu(ListView listView) - { - if (!SettingsEnum.SHOW_OLD_VIDEO_MENU.getBoolean()) return; - - listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { - @Override - public void onChildViewAdded(View parent, View child) { - LogHelper.printDebug(() -> "Added: " + child); - - parent.setVisibility(View.GONE); - - final var indexOfAdvancedQualityMenuItem = 4; - if (listView.indexOfChild(child) != indexOfAdvancedQualityMenuItem) return; - - LogHelper.printDebug(() -> "Found advanced menu: " + child); - - final var qualityItemMenuPosition = 4; - listView.performItemClick(null, qualityItemMenuPosition, 0); - } - - @Override - public void onChildViewRemoved(View parent, View child) {} - }); - } -} diff --git a/integrations/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java b/integrations/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java new file mode 100644 index 0000000000..97582040a0 --- /dev/null +++ b/integrations/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java @@ -0,0 +1,94 @@ +package app.revanced.integrations.patches.playback.quality; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.LinearLayout; +import android.widget.ListView; + +import androidx.annotation.NonNull; + +import app.revanced.integrations.patches.components.VideoQualityMenuFilterPatch; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import com.facebook.litho.ComponentHost; +import kotlin.Deprecated; + +// This patch contains the logic to show the old video quality menu. +// 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 { + + public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { + if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; + + // The quality menu is a RecyclerView with 3 children. The third child is the "Advanced" quality menu. + addRecyclerListener(linearLayout, 3, 2, recyclerView -> { + // Check if the current view is the quality menu. + if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) {// Hide the video quality menu. + linearLayout.setVisibility(View.GONE); + + // Click the "Advanced" quality menu to show the "old" quality menu. + ((ComponentHost) recyclerView.getChildAt(0)).getChildAt(3).performClick(); + LogHelper.printDebug(() -> "Advanced quality menu in new type of quality menu clicked"); + } + }); + } + + public static void addRecyclerListener(@NonNull LinearLayout linearLayout, + int expectedLayoutChildCount, int recyclerViewIndex, + @NonNull RecyclerViewGlobalLayoutListener listener) { + if (linearLayout.getChildCount() != expectedLayoutChildCount) return; + + var layoutChild = linearLayout.getChildAt(recyclerViewIndex); + if (!(layoutChild instanceof RecyclerView)) return; + final var recyclerView = (RecyclerView) layoutChild; + + recyclerView.getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + try { + listener.recyclerOnGlobalLayout(recyclerView); + } catch (Exception ex) { + LogHelper.printException(() -> "addRecyclerListener failure", ex); + } finally { + // Remove the listener because it will be added again. + recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + } + } + ); + } + + public interface RecyclerViewGlobalLayoutListener { + void recyclerOnGlobalLayout(@NonNull RecyclerView recyclerView); + } + + @Deprecated(message = "This patch is deprecated because the quality menu is not a ListView anymore") + public static void showOldVideoQualityMenu(final ListView listView) { + if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; + + listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { + @Override + public void onChildViewAdded(View parent, View child) { + LogHelper.printDebug(() -> "Added listener to old type of quality menu"); + + parent.setVisibility(View.GONE); + + final var indexOfAdvancedQualityMenuItem = 4; + if (listView.indexOfChild(child) != indexOfAdvancedQualityMenuItem) return; + + LogHelper.printDebug(() -> "Found advanced menu item in old type of quality menu"); + + final var qualityItemMenuPosition = 4; + listView.performItemClick(null, qualityItemMenuPosition, 0); + } + + @Override + public void onChildViewRemoved(View parent, View child) { + } + }); + } +} diff --git a/integrations/java/app/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch.java b/integrations/java/app/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch.java index d1ef08eb5a..04c19f7762 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch.java @@ -38,13 +38,8 @@ public class RememberVideoQualityPatch { private static List videoQualities; private static void changeDefaultQuality(int defaultQuality) { - NetworkType networkType = ReVancedUtils.getNetworkType(); - if (networkType == NetworkType.NONE) { - ReVancedUtils.showToastShort("No internet connection"); - return; - } String networkTypeMessage; - if (networkType == NetworkType.MOBILE) { + if (ReVancedUtils.getNetworkType() == NetworkType.MOBILE) { mobileQualitySetting.saveValue(defaultQuality); networkTypeMessage = "mobile"; } else { @@ -139,15 +134,24 @@ public static int setVideoQuality(Object[] qualities, final int originalQualityI } /** - * Injection point. + * Injection point. Old quality menu. */ - public static void userChangedQuality(int selectedQuality) { + public static void userChangedQuality(int selectedQualityIndex) { if (!SettingsEnum.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.getBoolean()) return; - userSelectedQualityIndex = selectedQuality; + userSelectedQualityIndex = selectedQualityIndex; userChangedDefaultQuality = true; } + /** + * Injection point. New quality menu. + */ + public static void userChangedQualityInNewFlyout(int selectedQuality) { + if (!SettingsEnum.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.getBoolean()) return; + + changeDefaultQuality(selectedQuality); // Quality is human readable resolution (ie: 1080). + } + /** * Injection point. */ diff --git a/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java b/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java index df80c1f547..a8e2e60359 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java @@ -1,11 +1,19 @@ package app.revanced.integrations.patches.playback.speed; +import static app.revanced.integrations.patches.playback.quality.OldVideoQualityMenuPatch.addRecyclerListener; + import android.preference.ListPreference; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; import androidx.annotation.NonNull; +import com.facebook.litho.ComponentHost; + import java.util.Arrays; +import app.revanced.integrations.patches.components.VideoSpeedMenuFilterPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; @@ -37,7 +45,7 @@ public class CustomVideoSpeedPatch { private static String[] preferenceListEntries, preferenceListEntryValues; static { - loadSpeeds(); + loadCustomSpeeds(); } private static void resetCustomSpeeds(@NonNull String toastMessage) { @@ -45,7 +53,7 @@ private static void resetCustomSpeeds(@NonNull String toastMessage) { SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.saveValue(SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.defaultValue); } - private static void loadSpeeds() { + private static void loadCustomSpeeds() { try { String[] speedStrings = SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.getString().split("\\s+"); Arrays.sort(speedStrings); @@ -61,7 +69,7 @@ private static void loadSpeeds() { if (speed >= MAXIMUM_PLAYBACK_SPEED) { resetCustomSpeeds("Custom speeds must be less than " + MAXIMUM_PLAYBACK_SPEED + ". Using default values."); - loadSpeeds(); + loadCustomSpeeds(); return; } minVideoSpeed = Math.min(minVideoSpeed, speed); @@ -71,7 +79,7 @@ private static void loadSpeeds() { } catch (Exception ex) { LogHelper.printInfo(() -> "parse error", ex); resetCustomSpeeds("Invalid custom video speeds. Using default values."); - loadSpeeds(); + loadCustomSpeeds(); } } @@ -100,4 +108,32 @@ public static void initializeListPreference(ListPreference preference) { preference.setEntries(preferenceListEntries); preference.setEntryValues(preferenceListEntryValues); } + + /* + * To reduce copy paste between two similar code paths. + */ + public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { + // The playback rate menu is a RecyclerView with 2 children. The third child is the "Advanced" quality menu. + addRecyclerListener(linearLayout, 2, 1, recyclerView -> { + if (VideoSpeedMenuFilterPatch.isVideoSpeedMenuVisible && + recyclerView.getChildCount() == 1 && + recyclerView.getChildAt(0) instanceof ComponentHost + ) { + linearLayout.setVisibility(View.GONE); + + // Close the new video speed menu and instead show the old one. + showOldVideoSpeedMenu(); + + // DismissView [R.id.touch_outside] is the 1st ChildView of the 3rd ParentView. + ((ViewGroup) linearLayout.getParent().getParent().getParent()) + .getChildAt(0).performClick(); + } + }); + } + + public static void showOldVideoSpeedMenu() { + LogHelper.printDebug(() -> "Old video quality menu shown"); + + // Rest of the implementation added by patch. + } } diff --git a/integrations/java/app/revanced/integrations/settings/SettingsEnum.java b/integrations/java/app/revanced/integrations/settings/SettingsEnum.java index 471a70a669..10fb1ea586 100644 --- a/integrations/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/integrations/java/app/revanced/integrations/settings/SettingsEnum.java @@ -42,7 +42,9 @@ public enum SettingsEnum { // Video HDR_AUTO_BRIGHTNESS("revanced_hdr_auto_brightness", BOOLEAN, TRUE), - SHOW_OLD_VIDEO_MENU("revanced_show_old_video_menu", BOOLEAN, TRUE), + SHOW_OLD_VIDEO_QUALITY_MENU("revanced_show_old_video_quality_menu", BOOLEAN, TRUE), + @Deprecated + DEPRECATED_SHOW_OLD_VIDEO_QUALITY_MENU("revanced_show_old_video_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), @@ -51,9 +53,6 @@ public enum SettingsEnum { CUSTOM_PLAYBACK_SPEEDS("revanced_custom_playback_speeds", STRING, "0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true), - // Whitelist - //WHITELIST("revanced_whitelist_ads", BOOLEAN, FALSE), // TODO: Unused currently - // Ads HIDE_BUTTONED_ADS("revanced_hide_buttoned_ads", BOOLEAN, TRUE), HIDE_GENERAL_ADS("revanced_hide_general_ads", BOOLEAN, TRUE), @@ -207,156 +206,7 @@ public enum SettingsEnum { SB_HIDE_EXPORT_WARNING("sb_hide_export_warning", BOOLEAN, FALSE, SPONSOR_BLOCK), SB_SEEN_GUIDELINES("sb_seen_guidelines", BOOLEAN, FALSE, SPONSOR_BLOCK), SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS("sb_local_time_saved_number_segments", INTEGER, 0, SPONSOR_BLOCK), - SB_LOCAL_TIME_SAVED_MILLISECONDS("sb_local_time_saved_milliseconds", LONG, 0L, SPONSOR_BLOCK), - - // - // TODO: eventually, delete these - // - @Deprecated - DEPRECATED_ADREMOVER_BUTTONED_REMOVAL("revanced_adremover_buttoned", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_ADREMOVER_GENERAL_ADS_REMOVAL("revanced_adremover_ad_removal", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_ADREMOVER_PAID_CONTENT("revanced_adremover_paid_content", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_ADREMOVER_HIDE_LATEST_POSTS("revanced_adremover_hide_latest_posts", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_ADREMOVER_SELF_SPONSOR("revanced_adremover_self_sponsor", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_ADREMOVER_CUSTOM_ENABLED("revanced_adremover_custom_enabled", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_ADREMOVER_CUSTOM_REMOVAL("revanced_adremover_custom_strings", STRING, "", true), - @Deprecated - DEPRECATED_REMOVE_VIDEO_ADS("revanced_video_ads_removal", BOOLEAN, TRUE, true), - - @Deprecated - DEPRECATED_HIDE_CHANNEL_MEMBER_SHELF("revanced_adremover_channel_member_shelf_removal", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_CHAPTER_TEASER("revanced_adremover_chapter_teaser", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_COMMUNITY_GUIDELINES("revanced_adremover_community_guidelines", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_COMMUNITY_POSTS("revanced_adremover_community_posts_removal", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_HIDE_COMPACT_BANNER("revanced_adremover_compact_banner_removal", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_EMERGENCY_BOX("revanced_adremover_emergency_box_removal", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_FEED_SURVEY_REMOVAL("revanced_adremover_feed_survey", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_GRAY_SEPARATOR("revanced_adremover_separator", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_HIDE_CHANNEL_GUIDELINES("revanced_adremover_hide_channel_guidelines", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_INFO_PANEL_REMOVAL("revanced_adremover_info_panel", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_MEDICAL_PANEL_REMOVAL("revanced_adremover_medical_panel", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_MERCHANDISE_REMOVAL("revanced_adremover_merchandise", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_MOVIE_REMOVAL("revanced_adremover_movie", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES_REMOVAL("revanced_adremover_subscribers_community_guidelines_removal", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_VIEW_PRODUCTS("revanced_adremover_view_products", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_WEB_SEARCH_RESULTS("revanced_adremover_web_search_result", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HIDE_SHORTS("revanced_adremover_shorts", BOOLEAN, TRUE, true), - @Deprecated - DEPRECATED_HIDE_INFO_CARDS("revanced_hide_infocards", BOOLEAN, TRUE), - - @Deprecated - DEPRECATED_DISABLE_RESUMING_SHORTS_PLAYER("revanced_disable_startup_shorts_player", BOOLEAN, FALSE), - - @Deprecated - DEPRECATED_ETERNAL_DOWNLOADER("revanced_downloads_enabled", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_EXTERNAL_DOWNLOADER_PACKAGE_NAME("revanced_downloads_package_name", STRING, "org.schabi.newpipe"), - - @Deprecated - DEPRECATED_SHOW_OLD_VIDEO_MENU("revanced_use_old_style_quality_settings", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_VIDEO_QUALITY_DEFAULT_WIFI("revanced_default_video_quality_wifi", INTEGER, -2), - @Deprecated - DEPRECATED_VIDEO_QUALITY_DEFAULT_MOBILE("revanced_default_video_quality_mobile", INTEGER, -2), - @Deprecated - DEPRECATED_PLAYBACK_SPEED_DEFAULT("revanced_default_playback_speed", FLOAT, 1.0f), - - @Deprecated - DEPRECATED_COPY_VIDEO_URL("revanced_copy_video_url_enabled", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_COPY_VIDEO_URL_TIMESTAMP("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE), - - @Deprecated - DEPRECATED_AUTO_CAPTIONS("revanced_autocaptions_enabled", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_PLAYER_POPUP_PANELS("revanced_player_popup_panels_enabled", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_SWIPE_BRIGHTNESS("revanced_enable_swipe_brightness", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_SWIPE_VOLUME("revanced_enable_swipe_volume", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_PRESS_TO_SWIPE("revanced_enable_press_to_swipe", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_SWIPE_HAPTIC_FEEDBACK("revanced_enable_swipe_haptic_feedback", BOOLEAN, TRUE), - - @Deprecated - DEPRECATED_DEBUG("revanced_debug_enabled", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_DEBUG_STACKTRACE("revanced_debug_stacktrace_enabled", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_DEBUG_TOAST_ON_ERROR("revanced_debug_toast_on_error_enabled", BOOLEAN, TRUE), - - @Deprecated - DEPRECATED_EXTERNAL_BROWSER("revanced_enable_external_browser", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_AUTO_REPEAT("revanced_pref_auto_repeat", BOOLEAN, FALSE), - @Deprecated - DEPRECATED_TAP_SEEKING("revanced_enable_tap_seeking", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_HDR_AUTO_BRIGHTNESS("revanced_pref_hdr_autobrightness", BOOLEAN, TRUE), - - @Deprecated - DEPRECATED_RYD_USER_ID("ryd_userId", STRING, "", RETURN_YOUTUBE_DISLIKE), - @Deprecated - DEPRECATED_RYD_DISLIKE_PERCENTAGE("ryd_show_dislike_percentage", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE), - @Deprecated - DEPRECATED_RYD_COMPACT_LAYOUT("ryd_use_compact_layout", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE), - - @Deprecated - DEPRECATED_SB_ENABLED("sb-enabled", BOOLEAN, TRUE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_VOTING_BUTTON("sb-voting-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_CREATE_NEW_SEGMENT("sb-new-segment-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_COMPACT_SKIP_BUTTON("sb-use-compact-skip-button", BOOLEAN, FALSE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_MIN_DURATION("sb-min-duration", FLOAT, 0F, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_VIDEO_LENGTH_WITHOUT_SEGMENTS("sb-length-without-segments", BOOLEAN, TRUE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_API_URL("sb-api-host-url", STRING, "https://sponsor.ajay.app", SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_TOAST_ON_SKIP("show-toast", BOOLEAN, TRUE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_AUTO_HIDE_SKIP_BUTTON("sb-auto-hide-skip-segment-button", BOOLEAN, TRUE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_TRACK_SKIP_COUNT("count-skips", BOOLEAN, TRUE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_ADJUST_NEW_SEGMENT_STEP("new-segment-step-accuracy", INTEGER, 150, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_LAST_VIP_CHECK("sb-last-vip-check", LONG, 0L, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_IS_VIP("sb-is-vip", BOOLEAN, FALSE, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS("sb-skipped-segments", INTEGER, 0, SPONSOR_BLOCK), - @Deprecated - DEPRECATED_SB_LOCAL_TIME_SAVED_MILLISECONDS("sb-skipped-segments-time", LONG, 0L, SPONSOR_BLOCK); - // - // TODO END - // + SB_LOCAL_TIME_SAVED_MILLISECONDS("sb_local_time_saved_milliseconds", LONG, 0L, SPONSOR_BLOCK); private static SettingsEnum[] parents(SettingsEnum... parents) { return parents; @@ -498,31 +348,31 @@ private static void loadAllSettings() { setting.load(); } - // TODO: eventually delete this. // region Migration - SettingsEnum[][] renamedSettings = { - // TODO: 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, - // and more time should be given for users who rarely upgrade. - {DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID}, - }; - - for (SettingsEnum[] oldNewSetting : renamedSettings) { - SettingsEnum oldSetting = oldNewSetting[0]; - SettingsEnum newSetting = oldNewSetting[1]; - - if (!oldSetting.isSetToDefault()) { - LogHelper.printInfo(() -> "Migrating old setting of '" + oldSetting.value - + "' from: " + oldSetting + " into replacement setting: " + newSetting); - newSetting.saveValue(oldSetting.value); - oldSetting.saveValue(oldSetting.defaultValue); // reset old value - } - } + // TODO: 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, + // and more time should be given for users who rarely upgrade. + migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID); + + // TODO: delete DEPRECATED_SHOW_OLD_VIDEO_QUALITY_MENU (When? anytime). + migrateOldSettingToNew(DEPRECATED_SHOW_OLD_VIDEO_QUALITY_MENU, SHOW_OLD_VIDEO_QUALITY_MENU); // endregion } + /** + * Migrate a setting value if the path is renamed but otherwise the old and new settings are identical. + */ + private static void migrateOldSettingToNew(SettingsEnum oldSetting, SettingsEnum newSetting) { + if (!oldSetting.isSetToDefault()) { + LogHelper.printInfo(() -> "Migrating old setting of '" + oldSetting.value + + "' from: " + oldSetting + " into replacement setting: " + newSetting); + newSetting.saveValue(oldSetting.value); + oldSetting.saveValue(oldSetting.defaultValue); // reset old value + } + } + private void load() { switch (returnType) { case BOOLEAN: diff --git a/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java b/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java index 9bbc83870e..50d4a725b0 100644 --- a/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java +++ b/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java @@ -180,6 +180,11 @@ private void updateListPreferenceSummary(ListPreference listPreference, Settings if (entryIndex >= 0) { listPreference.setSummary(listPreference.getEntries()[entryIndex]); listPreference.setValue(objectStringValue); + } else { + // Value is not an available option. + // User manually edited import data, or options changed and current selection is no longer available. + // Still show the value in the summary so it's clear that something is selected. + listPreference.setSummary(objectStringValue); } } diff --git a/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java b/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java index 85bac3ab0e..e1de088de3 100644 --- a/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java +++ b/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java @@ -427,16 +427,6 @@ private void addAboutCategory(Context context, PreferenceScreen screen) { return false; }); } - - { - Preference preference = new Preference(context); - category.addPreference(preference); - preference.setSummary(str("sb_about_made_by")); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - preference.setSingleLineTitle(false); - } - preference.setSelectable(false); - } } private void openGuidelines() { diff --git a/integrations/java/app/revanced/integrations/shared/PlayerType.kt b/integrations/java/app/revanced/integrations/shared/PlayerType.kt index 4992170f35..0fd89bfcaf 100644 --- a/integrations/java/app/revanced/integrations/shared/PlayerType.kt +++ b/integrations/java/app/revanced/integrations/shared/PlayerType.kt @@ -8,15 +8,16 @@ import app.revanced.integrations.utils.LogHelper */ enum class PlayerType { /** - * Includes Shorts and Stories playback. + * Either no video, or a Short is playing. */ NONE, /** - * A Shorts or Stories, if a regular video is minimized and a Short/Story is then opened. + * A Short is playing. Occurs if a regular video is first opened + * and then a Short is opened (without first closing the regular video). */ HIDDEN, /** - * When spoofing to an old version of YouTube, and watching a short with a regular video in the background, + * When spoofing to 16.x YouTube and watching a short with a regular video in the background, * the type will be this (and not [HIDDEN]). */ WATCH_WHILE_MINIMIZED, @@ -76,7 +77,7 @@ enum class PlayerType { * Useful to check if a short is currently playing. * * Does not include the first moment after a short is opened when a regular video is minimized on screen, - * or while watching a short with a regular video present on a spoofed old version of YouTube. + * or while watching a short with a regular video present on a spoofed 16.x version of YouTube. * To include those situations instead use [isNoneHiddenOrMinimized]. */ fun isNoneOrHidden(): Boolean { @@ -84,12 +85,13 @@ enum class PlayerType { } /** - * Check if the current player type is [NONE], [HIDDEN], [WATCH_WHILE_MINIMIZED], [WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED]. + * Check if the current player type is + * [NONE], [HIDDEN], [WATCH_WHILE_MINIMIZED], [WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED]. * * Useful to check if a Short is being played, - * although can return false positive if the player is minimized. + * although will return false positive if a regular video is opened and minimized (and no short is playing). * - * @return If nothing, a Short, a Story, + * @return If nothing, a Short, * or a regular video is minimized video or sliding off screen to a dismissed or hidden state. */ fun isNoneHiddenOrMinimized(): Boolean {