diff --git a/integrations/java/app/revanced/integrations/patches/AutoRepeatPatch.java b/integrations/java/app/revanced/integrations/patches/AutoRepeatPatch.java index 52c29aea2..28cf5372f 100644 --- a/integrations/java/app/revanced/integrations/patches/AutoRepeatPatch.java +++ b/integrations/java/app/revanced/integrations/patches/AutoRepeatPatch.java @@ -5,6 +5,6 @@ import app.revanced.integrations.settings.SettingsEnum; public class AutoRepeatPatch { //Used by app.revanced.patches.youtube.layout.autorepeat.patch.AutoRepeatPatch public static boolean shouldAutoRepeat() { - return SettingsEnum.PREFERRED_AUTO_REPEAT.getBoolean(); + return SettingsEnum.AUTO_REPEAT.getBoolean(); } } diff --git a/integrations/java/app/revanced/integrations/patches/DisableAutoCaptionsPatch.java b/integrations/java/app/revanced/integrations/patches/DisableAutoCaptionsPatch.java index e3d83a6e9..0e61b2612 100644 --- a/integrations/java/app/revanced/integrations/patches/DisableAutoCaptionsPatch.java +++ b/integrations/java/app/revanced/integrations/patches/DisableAutoCaptionsPatch.java @@ -4,10 +4,13 @@ import app.revanced.integrations.settings.SettingsEnum; public class DisableAutoCaptionsPatch { + /** + * Used by injected code. Do not delete. + */ public static boolean captionsButtonDisabled; public static boolean autoCaptionsEnabled() { - return SettingsEnum.CAPTIONS_ENABLED.getBoolean(); + return SettingsEnum.AUTO_CAPTIONS.getBoolean(); } } diff --git a/integrations/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java b/integrations/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java index d0ee7d93a..aa8c4cf38 100644 --- a/integrations/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java +++ b/integrations/java/app/revanced/integrations/patches/DisableStartupShortsPlayerPatch.java @@ -5,6 +5,6 @@ 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_STARTUP_SHORTS_PLAYER.getBoolean(); + return SettingsEnum.DISABLE_RESUMING_SHORTS_PLAYER.getBoolean(); } } diff --git a/integrations/java/app/revanced/integrations/patches/GeneralAdsPatch.java b/integrations/java/app/revanced/integrations/patches/GeneralAdsPatch.java index f02e60f87..3b3d06767 100644 --- a/integrations/java/app/revanced/integrations/patches/GeneralAdsPatch.java +++ b/integrations/java/app/revanced/integrations/patches/GeneralAdsPatch.java @@ -15,37 +15,37 @@ public final class GeneralAdsPatch extends Filter { }; private final BlockRule custom = new CustomBlockRule( - SettingsEnum.ADREMOVER_CUSTOM_ENABLED, - SettingsEnum.ADREMOVER_CUSTOM_REMOVAL + SettingsEnum.CUSTOM_FILTER, + SettingsEnum.CUSTOM_FILTER_STRINGS ); public GeneralAdsPatch() { - var communityPosts = new BlockRule(SettingsEnum.ADREMOVER_COMMUNITY_POSTS_REMOVAL, "post_base_wrapper"); - var communityGuidelines = new BlockRule(SettingsEnum.ADREMOVER_COMMUNITY_GUIDELINES_REMOVAL, "community_guidelines"); - var subscribersCommunityGuidelines = new BlockRule(SettingsEnum.ADREMOVER_SUBSCRIBERS_COMMUNITY_GUIDELINES_REMOVAL, "sponsorships_comments_upsell"); - var channelMemberShelf = new BlockRule(SettingsEnum.ADREMOVER_CHANNEL_MEMBER_SHELF_REMOVAL, "member_recognition_shelf"); - var compactBanner = new BlockRule(SettingsEnum.ADREMOVER_COMPACT_BANNER_REMOVAL, "compact_banner"); - var inFeedSurvey = new BlockRule(SettingsEnum.ADREMOVER_FEED_SURVEY_REMOVAL, "in_feed_survey", "slimline_survey"); - var medicalPanel = new BlockRule(SettingsEnum.ADREMOVER_MEDICAL_PANEL_REMOVAL, "medical_panel"); - var paidContent = new BlockRule(SettingsEnum.ADREMOVER_PAID_CONTENT_REMOVAL, "paid_content_overlay"); - var merchandise = new BlockRule(SettingsEnum.ADREMOVER_MERCHANDISE_REMOVAL, "product_carousel"); - var infoPanel = new BlockRule(SettingsEnum.ADREMOVER_INFO_PANEL_REMOVAL, "publisher_transparency_panel", "single_item_information_panel"); - var latestPosts = new BlockRule(SettingsEnum.ADREMOVER_HIDE_LATEST_POSTS, "post_shelf"); - var channelGuidelines = new BlockRule(SettingsEnum.ADREMOVER_HIDE_CHANNEL_GUIDELINES, "channel_guidelines_entry_banner"); + var communityPosts = new BlockRule(SettingsEnum.HIDE_COMMUNITY_POSTS, "post_base_wrapper"); + var communityGuidelines = new BlockRule(SettingsEnum.HIDE_COMMUNITY_GUIDELINES, "community_guidelines"); + var subscribersCommunityGuidelines = new BlockRule(SettingsEnum.HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES, "sponsorships_comments_upsell"); + var channelMemberShelf = new BlockRule(SettingsEnum.HIDE_CHANNEL_MEMBER_SHELF, "member_recognition_shelf"); + var compactBanner = new BlockRule(SettingsEnum.HIDE_COMPACT_BANNER, "compact_banner"); + var inFeedSurvey = new BlockRule(SettingsEnum.HIDE_FEED_SURVEY, "in_feed_survey", "slimline_survey"); + var medicalPanel = new BlockRule(SettingsEnum.HIDE_MEDICAL_PANELS, "medical_panel"); + var merchandise = new BlockRule(SettingsEnum.HIDE_MERCHANDISE_BANNERS, "product_carousel"); + var infoPanel = new BlockRule(SettingsEnum.HIDE_HIDE_INFO_PANELS, "publisher_transparency_panel", "single_item_information_panel"); + var channelGuidelines = new BlockRule(SettingsEnum.HIDE_HIDE_CHANNEL_GUIDELINES, "channel_guidelines_entry_banner"); var audioTrackButton = new BlockRule(SettingsEnum.HIDE_AUDIO_TRACK_BUTTON, "multi_feed_icon_button"); var artistCard = new BlockRule(SettingsEnum.HIDE_ARTIST_CARDS, "official_card"); - var selfSponsor = new BlockRule(SettingsEnum.ADREMOVER_SELF_SPONSOR_REMOVAL, "cta_shelf_card"); - var chapterTeaser = new BlockRule(SettingsEnum.ADREMOVER_CHAPTER_TEASER_REMOVAL, "expandable_metadata", "macro_markers_carousel"); - var viewProducts = new BlockRule(SettingsEnum.ADREMOVER_VIEW_PRODUCTS, "product_item", "products_in_video"); - var webLinkPanel = new BlockRule(SettingsEnum.ADREMOVER_WEB_SEARCH_RESULTS, "web_link_panel"); - var channelBar = new BlockRule(SettingsEnum.ADREMOVER_CHANNEL_BAR, "channel_bar"); - var relatedVideos = new BlockRule(SettingsEnum.ADREMOVER_RELATED_VIDEOS, "fullscreen_related_videos"); - var quickActions = new BlockRule(SettingsEnum.ADREMOVER_QUICK_ACTIONS, "quick_actions"); - var imageShelf = new BlockRule(SettingsEnum.ADREMOVER_IMAGE_SHELF, "image_shelf"); - var graySeparator = new BlockRule(SettingsEnum.ADREMOVER_GRAY_SEPARATOR, + var chapterTeaser = new BlockRule(SettingsEnum.HIDE_CHAPTER_TEASER, "expandable_metadata", "macro_markers_carousel"); + var viewProducts = new BlockRule(SettingsEnum.HIDE_PRODUCTS_BANNER, "product_item", "products_in_video"); + var webLinkPanel = new BlockRule(SettingsEnum.HIDE_WEB_SEARCH_RESULTS, "web_link_panel"); + var channelBar = new BlockRule(SettingsEnum.HIDE_CHANNEL_BAR, "channel_bar"); + var relatedVideos = new BlockRule(SettingsEnum.HIDE_RELATED_VIDEOS, "fullscreen_related_videos"); + var quickActions = new BlockRule(SettingsEnum.HIDE_QUICK_ACTIONS, "quick_actions"); + var imageShelf = new BlockRule(SettingsEnum.HIDE_IMAGE_SHELF, "image_shelf"); + var graySeparator = new BlockRule(SettingsEnum.HIDE_GRAY_SEPARATOR, "cell_divider" // layout residue (gray line above the buttoned ad), ); - var buttonedAd = new BlockRule(SettingsEnum.ADREMOVER_BUTTONED_REMOVAL, + var paidContent = new BlockRule(SettingsEnum.HIDE_PAID_CONTENT, "paid_content_overlay"); + var latestPosts = new BlockRule(SettingsEnum.HIDE_HIDE_LATEST_POSTS, "post_shelf"); + var selfSponsor = new BlockRule(SettingsEnum.HIDE_SELF_SPONSOR, "cta_shelf_card"); + var buttonedAd = new BlockRule(SettingsEnum.HIDE_BUTTONED_ADS, "_buttoned_layout", "full_width_square_image_layout", "_ad_with", @@ -53,7 +53,7 @@ public final class GeneralAdsPatch extends Filter { "landscape_image_wide_button_layout" ); var generalAds = new BlockRule( - SettingsEnum.ADREMOVER_GENERAL_ADS_REMOVAL, + SettingsEnum.HIDE_GENERAL_ADS, "ads_video_with_context", "banner_text_icon", "square_image_layout", @@ -69,7 +69,7 @@ public final class GeneralAdsPatch extends Filter { "brand_video_shelf" ); var movieAds = new BlockRule( - SettingsEnum.ADREMOVER_MOVIE_REMOVAL, + SettingsEnum.HIDE_MOVIES_SECTION, "browsy_bar", "compact_movie", "horizontal_movie_shelf", @@ -106,10 +106,10 @@ public final class GeneralAdsPatch extends Filter { channelMemberShelf ); - var carouselAd = new BlockRule(SettingsEnum.ADREMOVER_GENERAL_ADS_REMOVAL, + var carouselAd = new BlockRule(SettingsEnum.HIDE_GENERAL_ADS, "carousel_ad" ); - var shorts = new BlockRule(SettingsEnum.ADREMOVER_SHORTS_REMOVAL, + var shorts = new BlockRule(SettingsEnum.HIDE_SHORTS, "shorts_shelf", "inline_shorts", "shorts_grid" @@ -174,7 +174,7 @@ public final class GeneralAdsPatch extends Filter { * @param view The view, which shows ads. */ public static void hideAdAttributionView(View view) { - hideView(SettingsEnum.ADREMOVER_GENERAL_ADS_REMOVAL, view); + hideView(SettingsEnum.HIDE_GENERAL_ADS, view); } /** @@ -183,7 +183,7 @@ public final class GeneralAdsPatch extends Filter { * @param view The view, which shows reels. */ public static void hideReelView(View view) { - hideView(SettingsEnum.ADREMOVER_SHORTS_REMOVAL, view); + hideView(SettingsEnum.HIDE_SHORTS, view); } } diff --git a/integrations/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java b/integrations/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java index 330b3cfd3..86271d5d0 100644 --- a/integrations/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java +++ b/integrations/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java @@ -21,7 +21,7 @@ public class HDRAutoBrightnessPatch { */ public static float getHDRBrightness(float original) { // do nothing if disabled - if (!SettingsEnum.USE_HDR_AUTO_BRIGHTNESS.getBoolean()) { + if (!SettingsEnum.HDR_AUTO_BRIGHTNESS.getBoolean()) { return original; } diff --git a/integrations/java/app/revanced/integrations/patches/OpenLinksExternallyPatch.java b/integrations/java/app/revanced/integrations/patches/OpenLinksExternallyPatch.java index 4f5ce40b2..1640c7bf8 100644 --- a/integrations/java/app/revanced/integrations/patches/OpenLinksExternallyPatch.java +++ b/integrations/java/app/revanced/integrations/patches/OpenLinksExternallyPatch.java @@ -13,7 +13,7 @@ public class OpenLinksExternallyPatch { * @return The new, default service to open links with or the original service. */ public static String enableExternalBrowser(String original) { - if (SettingsEnum.ENABLE_EXTERNAL_BROWSER.getBoolean()) original = ""; + if (SettingsEnum.EXTERNAL_BROWSER.getBoolean()) original = ""; return original; } } diff --git a/integrations/java/app/revanced/integrations/patches/SeekbarTappingPatch.java b/integrations/java/app/revanced/integrations/patches/SeekbarTappingPatch.java index 062cfd11a..6739b0a11 100644 --- a/integrations/java/app/revanced/integrations/patches/SeekbarTappingPatch.java +++ b/integrations/java/app/revanced/integrations/patches/SeekbarTappingPatch.java @@ -6,7 +6,7 @@ public class SeekbarTappingPatch { //Used by app.revanced.patches.youtube.interaction.seekbar.patch.EnableSeekbarTappingPatch public static boolean isTapSeekingEnabled() { - return SettingsEnum.TAP_SEEKING_ENABLED.getBoolean(); + return SettingsEnum.TAP_SEEKING.getBoolean(); } } diff --git a/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java b/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java index 95b948d52..874781f59 100644 --- a/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java +++ b/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java @@ -60,7 +60,7 @@ public class SpoofSignatureVerificationPatch { */ public static String overrideProtobufParameter(String originalValue) { try { - if (!SettingsEnum.SIGNATURE_SPOOFING.getBoolean()) { + if (!SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { return originalValue; } @@ -101,11 +101,11 @@ public class SpoofSignatureVerificationPatch { } LogHelper.printDebug(() -> "YouTube HTTP status code: " + responseCode); - if (SettingsEnum.SIGNATURE_SPOOFING.getBoolean()) { + if (SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { return; // already enabled } - SettingsEnum.SIGNATURE_SPOOFING.saveValue(true); + SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.saveValue(true); ReVancedUtils.showToastLong("Spoofing app signature to prevent playback issues"); // it would be great if the video could be forcefully reloaded, but currently there is no code to do this @@ -130,7 +130,7 @@ public class SpoofSignatureVerificationPatch { * @param sd function is not entirely clear */ public static int[] getSubtitleWindowSettingsOverride(int ap, int ah, int av, boolean vs, boolean sd) { - final boolean signatureSpoofing = SettingsEnum.SIGNATURE_SPOOFING.getBoolean(); + final boolean signatureSpoofing = SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean(); if (SettingsEnum.DEBUG.getBoolean()) { if (ap != lastAp || ah != lastAh || av != lastAv || vs != lastVs || sd != lastSd) { LogHelper.printDebug(() -> "video: " + VideoInformation.getVideoId() + " spoof: " + signatureSpoofing diff --git a/integrations/java/app/revanced/integrations/patches/VideoAdsPatch.java b/integrations/java/app/revanced/integrations/patches/VideoAdsPatch.java index 076fcae7e..487817fdf 100644 --- a/integrations/java/app/revanced/integrations/patches/VideoAdsPatch.java +++ b/integrations/java/app/revanced/integrations/patches/VideoAdsPatch.java @@ -7,8 +7,7 @@ public class VideoAdsPatch { // Used by app.revanced.patches.youtube.ad.general.video.patch.VideoAdsPatch // depends on Whitelist patch (still needs to be written) public static boolean shouldShowAds() { - return !SettingsEnum.VIDEO_ADS_REMOVAL.getBoolean(); // TODO && Whitelist.shouldShowAds(); - + return !SettingsEnum.HIDE_VIDEO_ADS.getBoolean(); // TODO && Whitelist.shouldShowAds(); } } diff --git a/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java b/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java index 670cde2f9..71899a7a1 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch.java @@ -10,7 +10,7 @@ import app.revanced.integrations.utils.LogHelper; public class OldQualityLayoutPatch { public static void showOldQualityMenu(ListView listView) { - if (!SettingsEnum.OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS.getBoolean()) return; + if (!SettingsEnum.SHOW_OLD_VIDEO_MENU.getBoolean()) return; listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { @Override 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 4406e5a2d..d1ef08eb5 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch.java @@ -22,7 +22,7 @@ public class RememberVideoQualityPatch { /** * If the user selected a new quality from the flyout menu, - * and {@link SettingsEnum#VIDEO_QUALITY_REMEMBER_LAST_SELECTED} is enabled. + * and {@link SettingsEnum#REMEMBER_VIDEO_QUALITY_LAST_SELECTED} is enabled. */ private static boolean userChangedDefaultQuality; @@ -142,7 +142,7 @@ public class RememberVideoQualityPatch { * Injection point. */ public static void userChangedQuality(int selectedQuality) { - if (!SettingsEnum.VIDEO_QUALITY_REMEMBER_LAST_SELECTED.getBoolean()) return; + if (!SettingsEnum.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.getBoolean()) return; userSelectedQualityIndex = selectedQuality; userChangedDefaultQuality = true; 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 95450b46e..df80c1f54 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java @@ -42,12 +42,12 @@ public class CustomVideoSpeedPatch { private static void resetCustomSpeeds(@NonNull String toastMessage) { ReVancedUtils.showToastLong(toastMessage); - SettingsEnum.PLAYBACK_SPEED_AVAILABLE.saveValue(SettingsEnum.PLAYBACK_SPEED_AVAILABLE.defaultValue); + SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.saveValue(SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.defaultValue); } private static void loadSpeeds() { try { - String[] speedStrings = SettingsEnum.PLAYBACK_SPEED_AVAILABLE.getString().split("\\s+"); + String[] speedStrings = SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.getString().split("\\s+"); Arrays.sort(speedStrings); if (speedStrings.length == 0) { throw new IllegalArgumentException(); diff --git a/integrations/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java b/integrations/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java index 4cb9a3a23..f557f1a63 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java @@ -22,7 +22,7 @@ public final class RememberPlaybackSpeedPatch { * @param playbackSpeed The playback speed the user selected */ public static void userSelectedPlaybackSpeed(float playbackSpeed) { - if (SettingsEnum.PLAYBACK_SPEED_REMEMBER_LAST_SELECTED.getBoolean()) { + if (SettingsEnum.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.getBoolean()) { SettingsEnum.PLAYBACK_SPEED_DEFAULT.saveValue(playbackSpeed); ReVancedUtils.showToastLong("Changed default speed to: " + playbackSpeed + "x"); } diff --git a/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java b/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java index 2e10d803f..741b9a642 100644 --- a/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java @@ -494,7 +494,7 @@ public class ReturnYouTubeDislike { } SpannableStringBuilder builder = new SpannableStringBuilder(); - final boolean compactLayout = SettingsEnum.RYD_USE_COMPACT_LAYOUT.getBoolean(); + final boolean compactLayout = SettingsEnum.RYD_COMPACT_LAYOUT.getBoolean(); final int separatorColor = ThemeHelper.isDarkTheme() ? 0x29AAAAAA // transparent dark gray : 0xFFD9D9D9; // light gray @@ -578,7 +578,7 @@ public class ReturnYouTubeDislike { private static SpannableString newSpannableWithDislikes(@NonNull Spanned sourceStyling, @NonNull RYDVoteData voteData) { return newSpanUsingStylingOfAnotherSpan(sourceStyling, - SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean() + SettingsEnum.RYD_DISLIKE_PERCENTAGE.getBoolean() ? formatDislikePercentage(voteData.getDislikePercentage()) : formatDislikeCount(voteData.getDislikeCount())); } diff --git a/integrations/java/app/revanced/integrations/settings/SettingsEnum.java b/integrations/java/app/revanced/integrations/settings/SettingsEnum.java index 533aa74b7..4b5bc40a9 100644 --- a/integrations/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/integrations/java/app/revanced/integrations/settings/SettingsEnum.java @@ -1,70 +1,90 @@ package app.revanced.integrations.settings; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; +import static app.revanced.integrations.settings.SettingsEnum.ReturnType.BOOLEAN; +import static app.revanced.integrations.settings.SettingsEnum.ReturnType.FLOAT; +import static app.revanced.integrations.settings.SettingsEnum.ReturnType.INTEGER; +import static app.revanced.integrations.settings.SettingsEnum.ReturnType.LONG; +import static app.revanced.integrations.settings.SettingsEnum.ReturnType.STRING; +import static app.revanced.integrations.settings.SharedPrefCategory.RETURN_YOUTUBE_DISLIKE; +import static app.revanced.integrations.settings.SharedPrefCategory.SPONSOR_BLOCK; +import static app.revanced.integrations.utils.StringRef.str; + +import android.content.Context; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.revanced.integrations.utils.StringRef; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -import static app.revanced.integrations.settings.SettingsEnum.ReturnType.*; -import static app.revanced.integrations.settings.SharedPrefCategory.RETURN_YOUTUBE_DISLIKE; -import static app.revanced.integrations.settings.SharedPrefCategory.SPONSOR_BLOCK; -import static java.lang.Boolean.FALSE; -import static java.lang.Boolean.TRUE; +import app.revanced.integrations.sponsorblock.SponsorBlockSettings; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; +import app.revanced.integrations.utils.StringRef; public enum SettingsEnum { - //Download Settings - DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE), - DOWNLOADS_PACKAGE_NAME("revanced_downloads_package_name", STRING, "org.schabi.newpipe" /* NewPipe */, parents(DOWNLOADS_BUTTON_SHOWN)), + // External downloader + EXTERNAL_DOWNLOADER("revanced_external_downloader", BOOLEAN, TRUE), + EXTERNAL_DOWNLOADER_PACKAGE_NAME("revanced_external_downloader_name", STRING, + "org.schabi.newpipe" /* NewPipe */, parents(EXTERNAL_DOWNLOADER)), - // Copy video URL settings - COPY_VIDEO_URL_BUTTON_SHOWN("revanced_copy_video_url_enabled", BOOLEAN, TRUE), - COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE), + // Copy video URL + COPY_VIDEO_URL("revanced_copy_video_url", BOOLEAN, TRUE), + COPY_VIDEO_URL_TIMESTAMP("revanced_copy_video_url_timestamp", BOOLEAN, TRUE), - // Video settings - OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS("revanced_use_old_style_quality_settings", BOOLEAN, TRUE), - VIDEO_QUALITY_REMEMBER_LAST_SELECTED("revanced_remember_video_quality_last_selected", BOOLEAN, TRUE), - VIDEO_QUALITY_DEFAULT_WIFI("revanced_default_video_quality_wifi", INTEGER, -2), - VIDEO_QUALITY_DEFAULT_MOBILE("revanced_default_video_quality_mobile", INTEGER, -2), - PLAYBACK_SPEED_REMEMBER_LAST_SELECTED("revanced_remember_playback_speed_last_selected", BOOLEAN, TRUE), - PLAYBACK_SPEED_DEFAULT("revanced_default_playback_speed", FLOAT, 1.0f), - PLAYBACK_SPEED_AVAILABLE("revanced_custom_video_speeds", STRING, + // Video + HDR_AUTO_BRIGHTNESS("revanced_hdr_auto_brightness", BOOLEAN, TRUE), + SHOW_OLD_VIDEO_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), + REMEMBER_PLAYBACK_SPEED_LAST_SELECTED("revanced_remember_playback_speed_last_selected", BOOLEAN, TRUE), + PLAYBACK_SPEED_DEFAULT("revanced_playback_speed_default", FLOAT, 1.0f), + 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), - // TODO: Unused currently - // Whitelist settings - //ENABLE_WHITELIST("revanced_whitelist_ads_enabled", BOOLEAN, FALSE), + // Whitelist + //WHITELIST("revanced_whitelist_ads", BOOLEAN, FALSE), // TODO: Unused currently - // Ad settings - ADREMOVER_BUTTONED_REMOVAL("revanced_adremover_buttoned", BOOLEAN, TRUE), - ADREMOVER_CHANNEL_BAR("revanced_hide_channel_bar", BOOLEAN, FALSE), - ADREMOVER_CHANNEL_MEMBER_SHELF_REMOVAL("revanced_adremover_channel_member_shelf_removal", BOOLEAN, TRUE), - ADREMOVER_CHAPTER_TEASER_REMOVAL("revanced_adremover_chapter_teaser", BOOLEAN, TRUE), - ADREMOVER_COMMUNITY_GUIDELINES_REMOVAL("revanced_adremover_community_guidelines", BOOLEAN, TRUE), - ADREMOVER_COMMUNITY_POSTS_REMOVAL("revanced_adremover_community_posts_removal", BOOLEAN, FALSE), - ADREMOVER_COMPACT_BANNER_REMOVAL("revanced_adremover_compact_banner_removal", BOOLEAN, TRUE), - ADREMOVER_CUSTOM_ENABLED("revanced_adremover_custom_enabled", BOOLEAN, FALSE), - ADREMOVER_CUSTOM_REMOVAL("revanced_adremover_custom_strings", STRING, "", true, parents(ADREMOVER_CUSTOM_ENABLED)), - ADREMOVER_EMERGENCY_BOX_REMOVAL("revanced_adremover_emergency_box_removal", BOOLEAN, TRUE), - ADREMOVER_FEED_SURVEY_REMOVAL("revanced_adremover_feed_survey", BOOLEAN, TRUE), - ADREMOVER_GENERAL_ADS_REMOVAL("revanced_adremover_ad_removal", BOOLEAN, TRUE), - ADREMOVER_GRAY_SEPARATOR("revanced_adremover_separator", BOOLEAN, TRUE), - ADREMOVER_HIDE_CHANNEL_GUIDELINES("revanced_adremover_hide_channel_guidelines", BOOLEAN, TRUE), - ADREMOVER_HIDE_LATEST_POSTS("revanced_adremover_hide_latest_posts", BOOLEAN, TRUE), - ADREMOVER_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE), - ADREMOVER_INFO_PANEL_REMOVAL("revanced_adremover_info_panel", BOOLEAN, TRUE), - ADREMOVER_MEDICAL_PANEL_REMOVAL("revanced_adremover_medical_panel", BOOLEAN, TRUE), - ADREMOVER_MERCHANDISE_REMOVAL("revanced_adremover_merchandise", BOOLEAN, TRUE), - ADREMOVER_MOVIE_REMOVAL("revanced_adremover_movie", BOOLEAN, TRUE), - ADREMOVER_PAID_CONTENT_REMOVAL("revanced_adremover_paid_content", BOOLEAN, TRUE), - ADREMOVER_QUICK_ACTIONS("revanced_hide_quick_actions", BOOLEAN, FALSE), - ADREMOVER_RELATED_VIDEOS("revanced_hide_related_videos", BOOLEAN, FALSE), - ADREMOVER_SELF_SPONSOR_REMOVAL("revanced_adremover_self_sponsor", BOOLEAN, TRUE), - ADREMOVER_SHORTS_REMOVAL("revanced_adremover_shorts", BOOLEAN, TRUE, true), - ADREMOVER_SUBSCRIBERS_COMMUNITY_GUIDELINES_REMOVAL("revanced_adremover_subscribers_community_guidelines_removal", BOOLEAN, TRUE), - ADREMOVER_VIEW_PRODUCTS("revanced_adremover_view_products", BOOLEAN, TRUE), - ADREMOVER_WEB_SEARCH_RESULTS("revanced_adremover_web_search_result", BOOLEAN, TRUE), - VIDEO_ADS_REMOVAL("revanced_video_ads_removal", BOOLEAN, TRUE, true), + // Ads + HIDE_BUTTONED_ADS("revanced_hide_buttoned_ads", BOOLEAN, TRUE), + HIDE_GENERAL_ADS("revanced_hide_general_ads", BOOLEAN, TRUE), + HIDE_HIDE_LATEST_POSTS("revanced_hide_latest_posts_ads", BOOLEAN, TRUE), + HIDE_PAID_CONTENT("revanced_hide_paid_content_ads", 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)), + + // Layout + HIDE_CHANNEL_BAR("revanced_hide_channel_bar", BOOLEAN, FALSE), + HIDE_CHANNEL_MEMBER_SHELF("revanced_hide_channel_member_shelf", BOOLEAN, TRUE), + HIDE_CHAPTER_TEASER("revanced_hide_chapter_teaser", BOOLEAN, 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_EMERGENCY_BOX("revanced_hide_emergency_box", BOOLEAN, TRUE), + HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE), + HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", 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_MEDICAL_PANELS("revanced_hide_medical_panels", BOOLEAN, TRUE), + HIDE_MERCHANDISE_BANNERS("revanced_hide_merchandise_banners", 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_SHORTS("revanced_hide_shorts", BOOLEAN, TRUE, true), + HIDE_QUICK_ACTIONS("revanced_hide_quick_actions", BOOLEAN, FALSE), + HIDE_RELATED_VIDEOS("revanced_hide_related_videos", BOOLEAN, FALSE), // Action buttons HIDE_LIKE_DISLIKE_BUTTON("revanced_hide_like_dislike_button", BOOLEAN, FALSE), @@ -73,8 +93,8 @@ public enum SettingsEnum { HIDE_CLIP_BUTTON("revanced_hide_clip_button", BOOLEAN, FALSE, "revanced_hide_clip_button_user_dialog_message"), HIDE_ACTION_BUTTONS("revanced_hide_action_buttons", BOOLEAN, FALSE), - // Layout settings - DISABLE_STARTUP_SHORTS_PLAYER("revanced_startup_shorts_player_enabled", BOOLEAN, FALSE), + // Layout + 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_AUDIO_TRACK_BUTTON("revanced_hide_audio_track_button", BOOLEAN, FALSE), @@ -84,14 +104,13 @@ public enum SettingsEnum { 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), - SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON("revanced_switch_create_with_notifications_button", BOOLEAN, TRUE, 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), HIDE_GET_PREMIUM("revanced_hide_get_premium", BOOLEAN, TRUE), - HIDE_INFO_CARDS("revanced_hide_infocards", 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_PLAYER_OVERLAY("revanced_hide_player_overlay", BOOLEAN, FALSE, true), @@ -104,7 +123,8 @@ public enum SettingsEnum { HIDE_TIMESTAMP("revanced_hide_timestamp", BOOLEAN, FALSE), HIDE_VIDEO_WATERMARK("revanced_hide_video_watermark", BOOLEAN, TRUE), HIDE_WATCH_IN_VR("revanced_hide_watch_in_vr", BOOLEAN, FALSE, true), - PLAYER_POPUP_PANELS("revanced_player_popup_panels_enabled", BOOLEAN, FALSE), + 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.30.35", true, parents(SPOOF_APP_VERSION)), USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true), @@ -114,61 +134,212 @@ public enum SettingsEnum { 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), - // Misc. Settings - SIGNATURE_SPOOFING("revanced_spoof_signature_verification", BOOLEAN, TRUE, "revanced_spoof_signature_verification_user_dialog_message"), - CAPTIONS_ENABLED("revanced_autocaptions_enabled", BOOLEAN, FALSE), + // Misc + AUTO_CAPTIONS("revanced_auto_captions", BOOLEAN, FALSE), DISABLE_ZOOM_HAPTICS("revanced_disable_zoom_haptics", BOOLEAN, TRUE), - ENABLE_EXTERNAL_BROWSER("revanced_enable_external_browser", BOOLEAN, TRUE, true), - PREFERRED_AUTO_REPEAT("revanced_pref_auto_repeat", BOOLEAN, FALSE), - TAP_SEEKING_ENABLED("revanced_enable_tap_seeking", BOOLEAN, TRUE), - USE_HDR_AUTO_BRIGHTNESS("revanced_pref_hdr_autobrightness", BOOLEAN, TRUE), + EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true), + AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE), + TAP_SEEKING("revanced_tap_seeking", BOOLEAN, TRUE), + SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, "revanced_spoof_signature_verification_user_dialog_message"), // Swipe controls - ENABLE_SWIPE_BRIGHTNESS("revanced_enable_swipe_brightness", BOOLEAN, TRUE), - ENABLE_SWIPE_VOLUME("revanced_enable_swipe_volume", BOOLEAN, TRUE), - ENABLE_PRESS_TO_SWIPE("revanced_enable_press_to_swipe", BOOLEAN, FALSE, true, - parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)), - ENABLE_SWIPE_HAPTIC_FEEDBACK("revanced_enable_swipe_haptic_feedback", BOOLEAN, TRUE, - parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)), - SWIPE_MAGNITUDE_THRESHOLD("revanced_swipe_magnitude_threshold", FLOAT, 30f, // edit: why is this a float and not an Integer? - parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)), + SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE), + SWIPE_VOLUME("revanced_swipe_volume", BOOLEAN, TRUE), + SWIPE_PRESS_TO_ENGAGE("revanced_swipe_press_to_engage", BOOLEAN, FALSE, true, + parents(SWIPE_BRIGHTNESS, SWIPE_VOLUME)), + SWIPE_HAPTIC_FEEDBACK("revanced_swipe_haptic_feedback", BOOLEAN, TRUE, + parents(SWIPE_BRIGHTNESS, SWIPE_VOLUME)), + SWIPE_MAGNITUDE_THRESHOLD("revanced_swipe_threshold", INTEGER, 30, + parents(SWIPE_BRIGHTNESS, SWIPE_VOLUME)), SWIPE_OVERLAY_BACKGROUND_ALPHA("revanced_swipe_overlay_background_alpha", INTEGER, 127, - parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)), - SWIPE_OVERLAY_TEXT_SIZE("revanced_swipe_overlay_text_size", FLOAT, 22f, // edit: why is this a float and not an Integer? - parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)), + parents(SWIPE_BRIGHTNESS, SWIPE_VOLUME)), + SWIPE_OVERLAY_TEXT_SIZE("revanced_swipe_text_overlay_size", INTEGER, 22, + parents(SWIPE_BRIGHTNESS, SWIPE_VOLUME)), SWIPE_OVERLAY_TIMEOUT("revanced_swipe_overlay_timeout", LONG, 500L, - parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)), + parents(SWIPE_BRIGHTNESS, SWIPE_VOLUME)), - // Debug settings - DEBUG("revanced_debug_enabled", BOOLEAN, FALSE), - DEBUG_STACKTRACE("revanced_debug_stacktrace_enabled", BOOLEAN, FALSE, parents(DEBUG)), - DEBUG_SHOW_TOAST_ON_ERROR("revanced_debug_toast_on_error_enabled", BOOLEAN, TRUE, "revanced_debug_toast_on_error_user_dialog_message"), + // Debugging + DEBUG("revanced_debug", BOOLEAN, FALSE), + DEBUG_STACKTRACE("revanced_debug_stacktrace", BOOLEAN, FALSE, parents(DEBUG)), + DEBUG_TOAST_ON_ERROR("revanced_debug_toast_on_error", BOOLEAN, TRUE, "revanced_debug_toast_on_error_user_dialog_message"), - // ReturnYoutubeDislike settings + // ReturnYoutubeDislike RYD_ENABLED("ryd_enabled", BOOLEAN, TRUE, RETURN_YOUTUBE_DISLIKE), - RYD_USER_ID("ryd_userId", STRING, "", RETURN_YOUTUBE_DISLIKE), - RYD_SHOW_DISLIKE_PERCENTAGE("ryd_show_dislike_percentage", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)), + RYD_USER_ID("ryd_user_id", STRING, "", RETURN_YOUTUBE_DISLIKE), RYD_SHORTS("ryd_shorts", BOOLEAN, TRUE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)), - RYD_USE_COMPACT_LAYOUT("ryd_use_compact_layout", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)), + RYD_DISLIKE_PERCENTAGE("ryd_dislike_percentage", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)), + RYD_COMPACT_LAYOUT("ryd_compact_layout", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)), - // SponsorBlock settings - SB_ENABLED("sb-enabled", BOOLEAN, TRUE, SPONSOR_BLOCK), - SB_VOTING_ENABLED("sb-voting-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_CREATE_NEW_SEGMENT_ENABLED("sb-new-segment-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_USE_COMPACT_SKIP_BUTTON("sb-use-compact-skip-button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_AUTO_HIDE_SKIP_BUTTON("sb-auto-hide-skip-segment-button", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_SHOW_TOAST_ON_SKIP("show-toast", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_TRACK_SKIP_COUNT("count-skips", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_UUID("uuid", STRING, "", SPONSOR_BLOCK), - SB_ADJUST_NEW_SEGMENT_STEP("new-segment-step-accuracy", INTEGER, 150, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_MIN_DURATION("sb-min-duration", FLOAT, 0F, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_SEEN_GUIDELINES("sb-seen-gl", BOOLEAN, FALSE, SPONSOR_BLOCK), - SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED("sb-skipped-segments", INTEGER, 0, SPONSOR_BLOCK), - SB_SKIPPED_SEGMENTS_TIME_SAVED("sb-skipped-segments-time", LONG, 0L, SPONSOR_BLOCK), - SB_SHOW_TIME_WITHOUT_SEGMENTS("sb-length-without-segments", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), - SB_IS_VIP("sb-is-vip", BOOLEAN, FALSE, SPONSOR_BLOCK), - SB_LAST_VIP_CHECK("sb-last-vip-check", LONG, 0L, SPONSOR_BLOCK), - SB_API_URL("sb-api-host-url", STRING, "https://sponsor.ajay.app", SPONSOR_BLOCK); + // SponsorBlock + SB_ENABLED("sb_enabled", BOOLEAN, TRUE, SPONSOR_BLOCK), + SB_PRIVATE_USER_ID("sb_private_user_id_Do_Not_Share", STRING, "", SPONSOR_BLOCK), /** Do not use directly, instead use {@link SponsorBlockSettings} */ + DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING("uuid", STRING, "", SPONSOR_BLOCK), // Delete sometime in 2024 + SB_CREATE_NEW_SEGMENT_STEP("sb_create_new_segment_step", INTEGER, 150, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_VOTING_BUTTON("sb_voting_button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_CREATE_NEW_SEGMENT("sb_create_new_segment", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_COMPACT_SKIP_BUTTON("sb_compact_skip_button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_AUTO_HIDE_SKIP_BUTTON("sb_auto_hide_skip_button", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_TOAST_ON_SKIP("sb_toast_on_skip", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_TRACK_SKIP_COUNT("sb_track_skip_count", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_SEGMENT_MIN_DURATION("sb_min_segment_duration", FLOAT, 0F, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_VIDEO_LENGTH_WITHOUT_SEGMENTS("sb_video_length_without_segments", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)), + SB_API_URL("sb_api_url", STRING, "https://sponsor.ajay.app", SPONSOR_BLOCK), + SB_USER_IS_VIP("sb_user_is_vip", BOOLEAN, FALSE, SPONSOR_BLOCK), + // SB settings not exported + SB_LAST_VIP_CHECK("sb_last_vip_check", LONG, 0L, SPONSOR_BLOCK), + 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 + // private static SettingsEnum[] parents(SettingsEnum ... parents) { return parents; @@ -280,22 +451,126 @@ public enum SettingsEnum { } } + private static final Map pathToSetting = new HashMap<>(2* values().length); + static { loadAllSettings(); + + for (SettingsEnum setting : values()) { + pathToSetting.put(setting.path, setting); + } } @Nullable public static SettingsEnum settingFromPath(@NonNull String str) { - for (SettingsEnum setting : values()) { - if (setting.path.equals(str)) return setting; - } - return null; + return pathToSetting.get(str); } private static void loadAllSettings() { for (SettingsEnum setting : values()) { setting.load(); } + + // + // TODO: eventually delete this + // renamed settings with new path names, but otherwise the new and old settings are identical + // + 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}, + + // TODO: delete the rest of these migration settings. When to delete? Anytime. + {DEPRECATED_ADREMOVER_BUTTONED_REMOVAL, HIDE_BUTTONED_ADS}, + {DEPRECATED_ADREMOVER_GENERAL_ADS_REMOVAL, HIDE_GENERAL_ADS}, + {DEPRECATED_ADREMOVER_HIDE_LATEST_POSTS, HIDE_HIDE_LATEST_POSTS}, + {DEPRECATED_ADREMOVER_PAID_CONTENT, HIDE_PAID_CONTENT}, + {DEPRECATED_ADREMOVER_SELF_SPONSOR, HIDE_SELF_SPONSOR}, + {DEPRECATED_REMOVE_VIDEO_ADS, HIDE_VIDEO_ADS}, + {DEPRECATED_ADREMOVER_CUSTOM_ENABLED, CUSTOM_FILTER}, + {DEPRECATED_ADREMOVER_CUSTOM_REMOVAL, CUSTOM_FILTER_STRINGS}, + + {DEPRECATED_HIDE_CHANNEL_MEMBER_SHELF, HIDE_CHANNEL_MEMBER_SHELF}, + {DEPRECATED_HIDE_CHAPTER_TEASER, HIDE_CHAPTER_TEASER}, + {DEPRECATED_HIDE_COMMUNITY_GUIDELINES, HIDE_COMMUNITY_GUIDELINES}, + {DEPRECATED_HIDE_COMMUNITY_POSTS, HIDE_COMMUNITY_POSTS}, + {DEPRECATED_HIDE_COMPACT_BANNER, HIDE_COMPACT_BANNER}, + {DEPRECATED_HIDE_EMERGENCY_BOX, HIDE_EMERGENCY_BOX}, + {DEPRECATED_HIDE_FEED_SURVEY_REMOVAL, HIDE_FEED_SURVEY}, + {DEPRECATED_HIDE_GRAY_SEPARATOR, HIDE_GRAY_SEPARATOR}, + {DEPRECATED_HIDE_HIDE_CHANNEL_GUIDELINES, HIDE_HIDE_CHANNEL_GUIDELINES}, + {DEPRECATED_HIDE_INFO_PANEL_REMOVAL, HIDE_HIDE_INFO_PANELS}, + {DEPRECATED_HIDE_MEDICAL_PANEL_REMOVAL, HIDE_MEDICAL_PANELS}, + {DEPRECATED_HIDE_MERCHANDISE_REMOVAL, HIDE_MERCHANDISE_BANNERS}, + {DEPRECATED_HIDE_MOVIE_REMOVAL, HIDE_MOVIES_SECTION}, + {DEPRECATED_HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES_REMOVAL, HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES}, + {DEPRECATED_HIDE_VIEW_PRODUCTS, HIDE_PRODUCTS_BANNER}, + {DEPRECATED_HIDE_WEB_SEARCH_RESULTS, HIDE_WEB_SEARCH_RESULTS}, + {DEPRECATED_HIDE_SHORTS, HIDE_SHORTS}, + {DEPRECATED_DISABLE_RESUMING_SHORTS_PLAYER, DISABLE_RESUMING_SHORTS_PLAYER}, + {DEPRECATED_HIDE_INFO_CARDS, HIDE_INFO_CARDS}, + + {DEPRECATED_ETERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER}, + {DEPRECATED_EXTERNAL_DOWNLOADER_PACKAGE_NAME, EXTERNAL_DOWNLOADER_PACKAGE_NAME}, + {DEPRECATED_COPY_VIDEO_URL, COPY_VIDEO_URL}, + {DEPRECATED_COPY_VIDEO_URL_TIMESTAMP, COPY_VIDEO_URL_TIMESTAMP}, + + {DEPRECATED_SHOW_OLD_VIDEO_MENU, SHOW_OLD_VIDEO_MENU}, + {DEPRECATED_VIDEO_QUALITY_DEFAULT_WIFI, VIDEO_QUALITY_DEFAULT_WIFI}, + {DEPRECATED_VIDEO_QUALITY_DEFAULT_MOBILE, VIDEO_QUALITY_DEFAULT_MOBILE}, + {DEPRECATED_PLAYBACK_SPEED_DEFAULT, PLAYBACK_SPEED_DEFAULT}, + + {DEPRECATED_AUTO_CAPTIONS, AUTO_CAPTIONS}, + {DEPRECATED_PLAYER_POPUP_PANELS, PLAYER_POPUP_PANELS}, + {DEPRECATED_SWIPE_BRIGHTNESS, SWIPE_BRIGHTNESS}, + {DEPRECATED_SWIPE_VOLUME, SWIPE_VOLUME}, + {DEPRECATED_PRESS_TO_SWIPE, SWIPE_PRESS_TO_ENGAGE}, + {DEPRECATED_SWIPE_HAPTIC_FEEDBACK, SWIPE_HAPTIC_FEEDBACK}, + + {DEPRECATED_DEBUG, DEBUG}, + {DEPRECATED_DEBUG_STACKTRACE, DEBUG_STACKTRACE}, + {DEPRECATED_DEBUG_TOAST_ON_ERROR, DEBUG_TOAST_ON_ERROR}, + + {DEPRECATED_EXTERNAL_BROWSER, EXTERNAL_BROWSER}, + {DEPRECATED_AUTO_REPEAT, AUTO_REPEAT}, + {DEPRECATED_TAP_SEEKING, TAP_SEEKING}, + {DEPRECATED_HDR_AUTO_BRIGHTNESS, HDR_AUTO_BRIGHTNESS}, + + {DEPRECATED_RYD_USER_ID, RYD_USER_ID}, + {DEPRECATED_RYD_DISLIKE_PERCENTAGE, RYD_DISLIKE_PERCENTAGE}, + {DEPRECATED_RYD_COMPACT_LAYOUT, RYD_COMPACT_LAYOUT}, + + {DEPRECATED_SB_ENABLED, SB_ENABLED}, + {DEPRECATED_SB_VOTING_BUTTON, SB_VOTING_BUTTON}, + {DEPRECATED_SB_CREATE_NEW_SEGMENT, SB_CREATE_NEW_SEGMENT}, + {DEPRECATED_SB_COMPACT_SKIP_BUTTON, SB_COMPACT_SKIP_BUTTON}, + {DEPRECATED_SB_MIN_DURATION, SB_SEGMENT_MIN_DURATION}, + {DEPRECATED_SB_VIDEO_LENGTH_WITHOUT_SEGMENTS, SB_VIDEO_LENGTH_WITHOUT_SEGMENTS}, + {DEPRECATED_SB_API_URL, SB_API_URL}, + {DEPRECATED_SB_TOAST_ON_SKIP, SB_TOAST_ON_SKIP}, + {DEPRECATED_SB_AUTO_HIDE_SKIP_BUTTON, SB_AUTO_HIDE_SKIP_BUTTON}, + {DEPRECATED_SB_TRACK_SKIP_COUNT, SB_TRACK_SKIP_COUNT}, + {DEPRECATED_SB_ADJUST_NEW_SEGMENT_STEP, SB_CREATE_NEW_SEGMENT_STEP}, + {DEPRECATED_SB_LAST_VIP_CHECK, SB_LAST_VIP_CHECK}, + {DEPRECATED_SB_IS_VIP, SB_USER_IS_VIP}, + {DEPRECATED_SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS, SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS}, + {DEPRECATED_SB_LOCAL_TIME_SAVED_MILLISECONDS, SB_LOCAL_TIME_SAVED_MILLISECONDS}, + }; + 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 end + // } private void load() { @@ -354,7 +629,7 @@ public enum SettingsEnum { * This method is only to be used by the Settings preference code. */ public static void setValue(@NonNull SettingsEnum setting, @NonNull Boolean newValue) { - Objects.requireNonNull(newValue); + setting.returnType.validate(newValue); setting.value = newValue; } @@ -362,7 +637,8 @@ public enum SettingsEnum { * Sets the value, and persistently saves it. */ public void saveValue(@NonNull Object newValue) { - Objects.requireNonNull(newValue); + returnType.validate(newValue); + value = newValue; // Must set before saving to preferences (otherwise importing fails to update UI correctly). switch (returnType) { case BOOLEAN: sharedPref.saveBoolean(path, (boolean) newValue); @@ -382,7 +658,6 @@ public enum SettingsEnum { default: throw new IllegalStateException(name()); } - value = newValue; } /** @@ -400,6 +675,13 @@ public enum SettingsEnum { return false; } + /** + * @return if the currently set value is the same as {@link #defaultValue} + */ + public boolean isSetToDefault() { + return value.equals(defaultValue); + } + public boolean getBoolean() { return (Boolean) value; } @@ -429,11 +711,174 @@ public enum SettingsEnum { return value; } + /** + * This could be yet another field, + * for now use a simple switch statement since this method is not used outside this class. + */ + private boolean includeWithImportExport() { + switch (this) { + case RYD_USER_ID: // Not useful to export, no reason to include it. + case SB_LAST_VIP_CHECK: + case SB_HIDE_EXPORT_WARNING: + case SB_SEEN_GUIDELINES: + case SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS: + case SB_LOCAL_TIME_SAVED_MILLISECONDS: + return false; + } + return true; + } + + // Begin import / export + + /** + * If a setting path has this prefix, then remove it before importing/exporting. + */ + private static final String OPTIONAL_REVANCED_SETTINGS_PREFIX = "revanced_"; + + /** + * The path, minus any 'revanced' prefix to keep json concise. + */ + private String getImportExportKey() { + if (path.startsWith(OPTIONAL_REVANCED_SETTINGS_PREFIX)) { + return path.substring(OPTIONAL_REVANCED_SETTINGS_PREFIX.length()); + } + return path; + } + + private static SettingsEnum[] valuesSortedForExport() { + SettingsEnum[] sorted = values(); + Arrays.sort(sorted, (SettingsEnum o1, SettingsEnum o2) -> { + // Organize SponsorBlock settings last. + final boolean o1IsSb = o1.sharedPref == SPONSOR_BLOCK; + final boolean o2IsSb = o2.sharedPref == SPONSOR_BLOCK; + if (o1IsSb != o2IsSb) { + return o1IsSb ? 1 : -1; + } + return o1.path.compareTo(o2.path); + }); + return sorted; + } + + @NonNull + public static String exportJSON(@Nullable Context alertDialogContext) { + try { + JSONObject json = new JSONObject(); + for (SettingsEnum setting : valuesSortedForExport()) { + String importExportKey = setting.getImportExportKey(); + if (json.has(importExportKey)) { + throw new IllegalArgumentException("duplicate key found: " + importExportKey); + } + final boolean exportDefaultValues = false; // Enable to see what all settings looks like in the UI. + if (setting.includeWithImportExport() && (!setting.isSetToDefault() | exportDefaultValues)) { + json.put(importExportKey, setting.getObjectValue()); + } + } + SponsorBlockSettings.exportCategoriesToFlatJson(alertDialogContext, json); + + if (json.length() == 0) { + return ""; + } + String export = json.toString(0); + // Remove the outer JSON braces to make the output more compact, + // and leave less chance of the user forgetting to copy it + return export.substring(2, export.length() - 2); + } catch (JSONException e) { + LogHelper.printException(() -> "Export failure", e); // should never happen + return ""; + } + } + + /** + * @return if any settings that require a reboot were changed. + */ + public static boolean importJSON(@NonNull String settingsJsonString) { + try { + if (!settingsJsonString.matches("[\\s\\S]*\\{")) { + settingsJsonString = '{' + settingsJsonString + '}'; // Restore outer JSON braces + } + JSONObject json = new JSONObject(settingsJsonString); + + boolean rebootSettingChanged = false; + int numberOfSettingsImported = 0; + for (SettingsEnum setting : values()) { + String key = setting.getImportExportKey(); + if (json.has(key)) { + Object value; + switch (setting.returnType) { + case BOOLEAN: + value = json.getBoolean(key); + break; + case INTEGER: + value = json.getInt(key); + break; + case LONG: + value = json.getLong(key); + break; + case FLOAT: + value = (float) json.getDouble(key); + break; + case STRING: + value = json.getString(key); + break; + default: + throw new IllegalStateException(); + } + if (!setting.getObjectValue().equals(value)) { + rebootSettingChanged |= setting.rebootApp; + setting.saveValue(value); + } + numberOfSettingsImported++; + } else if (setting.includeWithImportExport() && !setting.isSetToDefault()) { + LogHelper.printDebug(() -> "Resetting to default: " + setting); + rebootSettingChanged |= setting.rebootApp; + setting.saveValue(setting.defaultValue); + } + } + numberOfSettingsImported += SponsorBlockSettings.importCategoriesFromFlatJson(json); + + ReVancedUtils.showToastLong(numberOfSettingsImported == 0 + ? str("revanced_settings_import_reset") + : str("revanced_settings_import_success", numberOfSettingsImported)); + + return rebootSettingChanged; + } catch (JSONException | IllegalArgumentException ex) { + ReVancedUtils.showToastLong(str("revanced_settings_import_failure_parse", ex.getMessage())); + LogHelper.printInfo(() -> "", ex); + } catch (Exception ex) { + LogHelper.printException(() -> "Import failure: " + ex.getMessage(), ex); // should never happen + } + return false; + } + + // End import / export + public enum ReturnType { BOOLEAN, INTEGER, - STRING, LONG, FLOAT, + STRING; + + public void validate(@Nullable Object obj) throws IllegalArgumentException { + if (!matches(obj)) { + throw new IllegalArgumentException("'" + obj + "' does not match:" + this); + } + } + + public boolean matches(@Nullable Object obj) { + switch (this) { + case BOOLEAN: + return obj instanceof Boolean; + case INTEGER: + return obj instanceof Integer; + case LONG: + return obj instanceof Long; + case FLOAT: + return obj instanceof Float; + case STRING: + return obj instanceof String; + } + return false; + } } } diff --git a/integrations/java/app/revanced/integrations/settingsmenu/ImportExportPreference.java b/integrations/java/app/revanced/integrations/settingsmenu/ImportExportPreference.java new file mode 100644 index 000000000..ff6397e89 --- /dev/null +++ b/integrations/java/app/revanced/integrations/settingsmenu/ImportExportPreference.java @@ -0,0 +1,97 @@ +package app.revanced.integrations.settingsmenu; + +import static app.revanced.integrations.utils.StringRef.str; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Build; +import android.preference.EditTextPreference; +import android.preference.Preference; +import android.text.InputType; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.EditText; + +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; + +public class ImportExportPreference extends EditTextPreference implements Preference.OnPreferenceClickListener { + + private String existingSettings; + + private void init() { + setSelectable(true); + + EditText editText = getEditText(); + editText.setTextIsSelectable(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + editText.setAutofillHints((String) null); + } + editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 7); // Use a smaller font to reduce text wrap. + + setOnPreferenceClickListener(this); + } + + public ImportExportPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + public ImportExportPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + public ImportExportPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + public ImportExportPreference(Context context) { + super(context); + init(); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + try { + // Must set text before preparing dialog, otherwise text is non selectable if this preference is later reopened. + existingSettings = SettingsEnum.exportJSON(getContext()); + getEditText().setText(existingSettings); + } catch (Exception ex) { + LogHelper.printException(() -> "showDialog failure", ex); + } + return true; + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + try { + // Show the user the settings in JSON format. + builder.setNeutralButton(str("revanced_settings_import_copy"), (dialog, which) -> { + ReVancedUtils.setClipboard(getEditText().getText().toString()); + }).setPositiveButton(str("revanced_settings_import"), (dialog, which) -> { + importSettings(getEditText().getText().toString()); + }); + } catch (Exception ex) { + LogHelper.printException(() -> "onPrepareDialogBuilder failure", ex); + } + } + + private void importSettings(String replacementSettings) { + try { + if (replacementSettings.equals(existingSettings)) { + return; + } + ReVancedSettingsFragment.settingImportInProgress = true; + final boolean rebootNeeded = SettingsEnum.importJSON(replacementSettings); + if (rebootNeeded) { + ReVancedSettingsFragment.showRebootDialog(getContext()); + } + } catch (Exception ex) { + LogHelper.printException(() -> "importSettings failure", ex); + } finally { + ReVancedSettingsFragment.settingImportInProgress = false; + } + } + +} \ No newline at end of file diff --git a/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java b/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java index d57ccc6f0..9bbc83870 100644 --- a/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java +++ b/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java @@ -31,6 +31,33 @@ import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; public class ReVancedSettingsFragment extends PreferenceFragment { + /** + * Indicates that if a preference changes, + * to apply the change from the Setting to the UI component. + */ + static boolean settingImportInProgress; + + private static void reboot(@NonNull Context activity) { + final int intentFlags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE; + PendingIntent intent = PendingIntent.getActivity(activity, 0, + new Intent(activity, Shell_HomeActivity.class), intentFlags); + AlarmManager systemService = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE); + systemService.setExact(AlarmManager.ELAPSED_REALTIME, 1500L, intent); + Process.killProcess(Process.myPid()); + } + + static void showRebootDialog(@NonNull Context activity) { + String positiveButton = str("in_app_update_restart_button"); + String negativeButton = str("sign_in_cancel"); + new AlertDialog.Builder(activity).setMessage(str("pref_refresh_config")) + .setPositiveButton(positiveButton, (dialog, id) -> { + reboot(activity); + }) + .setNegativeButton(negativeButton, null) + .setCancelable(false) + .show(); + } + /** * Used to prevent showing reboot dialog, if user cancels a setting user dialog. */ @@ -42,33 +69,53 @@ public class ReVancedSettingsFragment extends PreferenceFragment { if (setting == null) { return; } - Preference pref = this.findPreference(str); - LogHelper.printDebug(() -> "Setting " + setting.name() + " was changed. Preference " + str + ": " + pref); + Preference pref = findPreference(str); + LogHelper.printDebug(() -> setting.name() + ": " + " setting value:" + setting.getObjectValue() + " pref:" + pref); + if (pref == null) { + return; + } if (pref instanceof SwitchPreference) { SwitchPreference switchPref = (SwitchPreference) pref; - SettingsEnum.setValue(setting, switchPref.isChecked()); + if (settingImportInProgress) { + switchPref.setChecked(setting.getBoolean()); + } else { + SettingsEnum.setValue(setting, switchPref.isChecked()); + } } else if (pref instanceof EditTextPreference) { - String editText = ((EditTextPreference) pref).getText(); - SettingsEnum.setValue(setting, editText); + EditTextPreference editPreference = (EditTextPreference) pref; + if (settingImportInProgress) { + editPreference.getEditText().setText(setting.getObjectValue().toString()); + } else { + SettingsEnum.setValue(setting, editPreference.getText()); + } } else if (pref instanceof ListPreference) { ListPreference listPref = (ListPreference) pref; - SettingsEnum.setValue(setting, listPref.getValue()); + if (settingImportInProgress) { + listPref.setValue(setting.getObjectValue().toString()); + } else { + SettingsEnum.setValue(setting, listPref.getValue()); + } updateListPreferenceSummary((ListPreference) pref, setting); } else { LogHelper.printException(() -> "Setting cannot be handled: " + pref.getClass() + " " + pref); return; } + enableDisablePreferences(); + + if (settingImportInProgress) { + return; + } + if (!showingUserDialogMessage) { if (setting.userDialogMessage != null && ((SwitchPreference) pref).isChecked() != (Boolean) setting.defaultValue) { showSettingUserDialogConfirmation(getActivity(), (SwitchPreference) pref, setting); } else if (setting.rebootApp) { - rebootDialog(getActivity()); + showRebootDialog(getActivity()); } } - enableDisablePreferences(); } catch (Exception ex) { LogHelper.printException(() -> "OnSharedPreferenceChangeListener failure", ex); } @@ -91,17 +138,21 @@ public class ReVancedSettingsFragment extends PreferenceFragment { CustomVideoSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); } - // set the summary text for any ListPreferences + // Set current value from SettingsEnum for (SettingsEnum setting : SettingsEnum.values()) { Preference preference = findPreference(setting.path); - if (preference instanceof ListPreference) { + if (preference instanceof SwitchPreference) { + ((SwitchPreference) preference).setChecked(setting.getBoolean()); + } else if (preference instanceof EditTextPreference) { + ((EditTextPreference) preference).setText(setting.getObjectValue().toString()); + } else if (preference instanceof ListPreference) { updateListPreferenceSummary((ListPreference) preference, setting); } } preferenceManager.getSharedPreferences().registerOnSharedPreferenceChangeListener(listener); } catch (Exception ex) { - LogHelper.printException(() -> "onActivityCreated() error", ex); + LogHelper.printException(() -> "onActivityCreated() failure", ex); } } @@ -124,33 +175,14 @@ public class ReVancedSettingsFragment extends PreferenceFragment { * Sets summary text to the currently selected list option. */ private void updateListPreferenceSummary(ListPreference listPreference, SettingsEnum setting) { - final int entryIndex = listPreference.findIndexOfValue(setting.getObjectValue().toString()); + String objectStringValue = setting.getObjectValue().toString(); + final int entryIndex = listPreference.findIndexOfValue(objectStringValue); if (entryIndex >= 0) { listPreference.setSummary(listPreference.getEntries()[entryIndex]); + listPreference.setValue(objectStringValue); } } - private void reboot(@NonNull Activity activity) { - final int intentFlags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE; - PendingIntent intent = PendingIntent.getActivity(activity, 0, - new Intent(activity, Shell_HomeActivity.class), intentFlags); - AlarmManager systemService = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE); - systemService.setExact(AlarmManager.ELAPSED_REALTIME, 1500L, intent); - Process.killProcess(Process.myPid()); - } - - private void rebootDialog(@NonNull Activity activity) { - String positiveButton = str("in_app_update_restart_button"); - String negativeButton = str("sign_in_cancel"); - new AlertDialog.Builder(activity).setMessage(str("pref_refresh_config")) - .setPositiveButton(positiveButton, (dialog, id) -> { - reboot(activity); - }) - .setNegativeButton(negativeButton, null) - .setCancelable(false) - .show(); - } - private void showSettingUserDialogConfirmation(@NonNull Activity activity, SwitchPreference switchPref, SettingsEnum setting) { showingUserDialogMessage = true; new AlertDialog.Builder(activity) @@ -158,7 +190,7 @@ public class ReVancedSettingsFragment extends PreferenceFragment { .setMessage(setting.userDialogMessage.toString()) .setPositiveButton(android.R.string.ok, (dialog, id) -> { if (setting.rebootApp) { - rebootDialog(activity); + showRebootDialog(activity); } }) .setNegativeButton(android.R.string.cancel, (dialog, id) -> { diff --git a/integrations/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java b/integrations/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java index 4fe380f81..4005ad7ed 100644 --- a/integrations/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java +++ b/integrations/java/app/revanced/integrations/settingsmenu/ReturnYouTubeDislikeSettingsFragment.java @@ -36,8 +36,8 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment { private void updateUIState() { shortsPreference.setEnabled(SettingsEnum.RYD_SHORTS.isAvailable()); - percentagePreference.setEnabled(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.isAvailable()); - compactLayoutPreference.setEnabled(SettingsEnum.RYD_USE_COMPACT_LAYOUT.isAvailable()); + percentagePreference.setEnabled(SettingsEnum.RYD_DISLIKE_PERCENTAGE.isAvailable()); + compactLayoutPreference.setEnabled(SettingsEnum.RYD_COMPACT_LAYOUT.isAvailable()); } @Override @@ -77,12 +77,12 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment { preferenceScreen.addPreference(shortsPreference); percentagePreference = new SwitchPreference(context); - percentagePreference.setChecked(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean()); + percentagePreference.setChecked(SettingsEnum.RYD_DISLIKE_PERCENTAGE.getBoolean()); percentagePreference.setTitle(str("revanced_ryd_dislike_percentage_title")); percentagePreference.setSummaryOn(str("revanced_ryd_dislike_percentage_summary_on")); percentagePreference.setSummaryOff(str("revanced_ryd_dislike_percentage_summary_off")); percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> { - SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.saveValue(newValue); + SettingsEnum.RYD_DISLIKE_PERCENTAGE.saveValue(newValue); ReturnYouTubeDislike.clearCache(); updateUIState(); return true; @@ -90,12 +90,12 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment { preferenceScreen.addPreference(percentagePreference); compactLayoutPreference = new SwitchPreference(context); - compactLayoutPreference.setChecked(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getBoolean()); + compactLayoutPreference.setChecked(SettingsEnum.RYD_COMPACT_LAYOUT.getBoolean()); compactLayoutPreference.setTitle(str("revanced_ryd_compact_layout_title")); compactLayoutPreference.setSummaryOn(str("revanced_ryd_compact_layout_summary_on")); compactLayoutPreference.setSummaryOff(str("revanced_ryd_compact_layout_summary_off")); compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> { - SettingsEnum.RYD_USE_COMPACT_LAYOUT.saveValue(newValue); + SettingsEnum.RYD_COMPACT_LAYOUT.saveValue(newValue); ReturnYouTubeDislike.clearCache(); updateUIState(); return true; diff --git a/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java b/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java index 9a9e01412..a46a7254c 100644 --- a/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java +++ b/integrations/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java @@ -20,6 +20,7 @@ import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import android.text.Html; import android.text.InputType; +import android.util.TypedValue; import android.widget.EditText; import androidx.annotation.NonNull; @@ -67,41 +68,41 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { if (!enabled) { SponsorBlockViewController.hideAll(); SegmentPlaybackController.setCurrentVideoId(null); - } else if (!SettingsEnum.SB_CREATE_NEW_SEGMENT_ENABLED.getBoolean()) { + } else if (!SettingsEnum.SB_CREATE_NEW_SEGMENT.getBoolean()) { SponsorBlockViewController.hideNewSegmentLayout(); } // voting and add new segment buttons automatically shows/hides themselves sbEnabled.setChecked(enabled); - addNewSegment.setChecked(SettingsEnum.SB_CREATE_NEW_SEGMENT_ENABLED.getBoolean()); + addNewSegment.setChecked(SettingsEnum.SB_CREATE_NEW_SEGMENT.getBoolean()); addNewSegment.setEnabled(enabled); - votingEnabled.setChecked(SettingsEnum.SB_VOTING_ENABLED.getBoolean()); + votingEnabled.setChecked(SettingsEnum.SB_VOTING_BUTTON.getBoolean()); votingEnabled.setEnabled(enabled); - compactSkipButton.setChecked(SettingsEnum.SB_USE_COMPACT_SKIP_BUTTON.getBoolean()); + compactSkipButton.setChecked(SettingsEnum.SB_COMPACT_SKIP_BUTTON.getBoolean()); compactSkipButton.setEnabled(enabled); autoHideSkipSegmentButton.setChecked(SettingsEnum.SB_AUTO_HIDE_SKIP_BUTTON.getBoolean()); autoHideSkipSegmentButton.setEnabled(enabled); - showSkipToast.setChecked(SettingsEnum.SB_SHOW_TOAST_ON_SKIP.getBoolean()); + showSkipToast.setChecked(SettingsEnum.SB_TOAST_ON_SKIP.getBoolean()); showSkipToast.setEnabled(enabled); trackSkips.setChecked(SettingsEnum.SB_TRACK_SKIP_COUNT.getBoolean()); trackSkips.setEnabled(enabled); - showTimeWithoutSegments.setChecked(SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean()); + showTimeWithoutSegments.setChecked(SettingsEnum.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.getBoolean()); showTimeWithoutSegments.setEnabled(enabled); - newSegmentStep.setText(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getObjectValue().toString()); + newSegmentStep.setText(SettingsEnum.SB_CREATE_NEW_SEGMENT_STEP.getObjectValue().toString()); newSegmentStep.setEnabled(enabled); - minSegmentDuration.setText(SettingsEnum.SB_MIN_DURATION.getObjectValue().toString()); + minSegmentDuration.setText(SettingsEnum.SB_SEGMENT_MIN_DURATION.getObjectValue().toString()); minSegmentDuration.setEnabled(enabled); - privateUserId.setText(SettingsEnum.SB_UUID.getString()); + privateUserId.setText(SettingsEnum.SB_PRIVATE_USER_ID.getString()); privateUserId.setEnabled(enabled); apiUrl.setEnabled(enabled); @@ -171,7 +172,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { votingEnabled.setSummaryOff(str("sb_enable_voting_sum_off")); category.addPreference(votingEnabled); votingEnabled.setOnPreferenceChangeListener((preference1, newValue) -> { - SettingsEnum.SB_VOTING_ENABLED.saveValue(newValue); + SettingsEnum.SB_VOTING_BUTTON.saveValue(newValue); updateUI(); return true; }); @@ -182,7 +183,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { compactSkipButton.setSummaryOff(str("sb_enable_compact_skip_button_sum_off")); category.addPreference(compactSkipButton); compactSkipButton.setOnPreferenceChangeListener((preference1, newValue) -> { - SettingsEnum.SB_USE_COMPACT_SKIP_BUTTON.saveValue(newValue); + SettingsEnum.SB_COMPACT_SKIP_BUTTON.saveValue(newValue); updateUI(); return true; }); @@ -207,7 +208,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { return false; }); showSkipToast.setOnPreferenceChangeListener((preference1, newValue) -> { - SettingsEnum.SB_SHOW_TOAST_ON_SKIP.saveValue(newValue); + SettingsEnum.SB_TOAST_ON_SKIP.saveValue(newValue); updateUI(); return true; }); @@ -218,7 +219,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { showTimeWithoutSegments.setSummaryOn(str("sb_general_time_without_sum_on")); showTimeWithoutSegments.setSummaryOff(str("sb_general_time_without_sum_off")); showTimeWithoutSegments.setOnPreferenceChangeListener((preference1, newValue) -> { - SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.saveValue(newValue); + SettingsEnum.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.saveValue(newValue); updateUI(); return true; }); @@ -247,7 +248,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { .setCancelable(false) .show(); } - SettingsEnum.SB_CREATE_NEW_SEGMENT_ENABLED.saveValue(newValue); + SettingsEnum.SB_CREATE_NEW_SEGMENT.saveValue(newValue); updateUI(); return true; }); @@ -262,7 +263,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { ReVancedUtils.showToastLong(str("sb_general_adjusting_invalid")); return false; } - SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.saveValue(newAdjustmentValue); + SettingsEnum.SB_CREATE_NEW_SEGMENT_STEP.saveValue(newAdjustmentValue); return true; }); category.addPreference(newSegmentStep); @@ -298,7 +299,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { minSegmentDuration.setSummary(str("sb_general_min_duration_sum")); minSegmentDuration.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); minSegmentDuration.setOnPreferenceChangeListener((preference1, newValue) -> { - SettingsEnum.SB_MIN_DURATION.saveValue(Float.valueOf(newValue.toString())); + SettingsEnum.SB_SEGMENT_MIN_DURATION.saveValue(Float.valueOf(newValue.toString())); return true; }); category.addPreference(minSegmentDuration); @@ -312,7 +313,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { ReVancedUtils.showToastLong(str("sb_general_uuid_invalid")); return false; } - SettingsEnum.SB_UUID.saveValue(newUUID); + SettingsEnum.SB_PRIVATE_USER_ID.saveValue(newUUID); fetchAndDisplayStats(); return true; }); @@ -351,9 +352,22 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { }); category.addPreference(apiUrl); - importExport = new EditTextPreference(context); + importExport = new EditTextPreference(context) { + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + builder.setNeutralButton(str("sb_settings_copy"), (dialog, which) -> { + ReVancedUtils.setClipboard(getEditText().getText().toString()); + }); + } + }; importExport.setTitle(str("sb_settings_ie")); importExport.setSummary(str("sb_settings_ie_sum")); + importExport.getEditText().setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_FLAG_MULTI_LINE + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + importExport.getEditText().setAutofillHints((String) null); + } + importExport.getEditText().setTextSize(TypedValue.COMPLEX_UNIT_PT, 8); importExport.setOnPreferenceClickListener(preference1 -> { importExport.getEditText().setText(SponsorBlockSettings.exportSettings()); return true; @@ -419,6 +433,12 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { private void fetchAndDisplayStats() { try { statsCategory.removeAll(); + if (!SponsorBlockSettings.userHasSBPrivateId()) { + // User has never voted or created any segments. No stats to show. + addLocalUserStats(); + return; + } + Preference loadingPlaceholderPreference = new Preference(this.getActivity()); loadingPlaceholderPreference.setEnabled(false); statsCategory.addPreference(loadingPlaceholderPreference); @@ -428,6 +448,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { UserStats stats = SBRequester.retrieveUserStats(); ReVancedUtils.runOnMainThread(() -> { // get back on main thread to modify UI elements addUserStats(loadingPlaceholderPreference, stats); + addLocalUserStats(); }); }); } else { @@ -450,7 +471,8 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { statsCategory.removeAll(); Context context = statsCategory.getContext(); - { + if (stats.totalSegmentCountIncludingIgnored > 0) { + // If user has not created any segments, there's no reason to set a username. EditTextPreference preference = new EditTextPreference(context); statsCategory.addPreference(preference); String userName = stats.userName; @@ -482,7 +504,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { statsCategory.addPreference(preference); String formatted = statsNumberOfSegmentsSkippedFormatter.format(stats.segmentCount); preference.setTitle(fromHtml(str("sb_stats_submissions", formatted))); - if (stats.segmentCount == 0) { + if (stats.totalSegmentCountIncludingIgnored == 0) { preference.setSelectable(false); } else { preference.setOnPreferenceClickListener(preference1 -> { @@ -512,7 +534,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { String stats_saved; String stats_saved_sum; - if (stats.segmentCount == 0) { + if (stats.totalSegmentCountIncludingIgnored == 0) { stats_saved = str("sb_stats_saved_zero"); stats_saved_sum = str("sb_stats_saved_sum_zero"); } else { @@ -528,34 +550,34 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment { return false; }); } - - { - // time the user saved by using SB - Preference preference = new Preference(context); - statsCategory.addPreference(preference); - - Runnable updateStatsSelfSaved = () -> { - String formatted = statsNumberOfSegmentsSkippedFormatter.format(SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.getInt()); - preference.setTitle(fromHtml(str("sb_stats_self_saved", formatted))); - String formattedSaved = SponsorBlockUtils.getTimeSavedString(SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.getLong() / 1000); - preference.setSummary(fromHtml(str("sb_stats_self_saved_sum", formattedSaved))); - }; - updateStatsSelfSaved.run(); - preference.setOnPreferenceClickListener(preference1 -> { - new AlertDialog.Builder(preference1.getContext()) - .setTitle(str("sb_stats_self_saved_reset_title")) - .setPositiveButton(android.R.string.yes, (dialog, whichButton) -> { - SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.saveValue(SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.defaultValue); - SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.saveValue(SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.defaultValue); - updateStatsSelfSaved.run(); - }) - .setNegativeButton(android.R.string.no, null).show(); - return true; - }); - } } catch (Exception ex) { - LogHelper.printException(() -> "fetchAndDisplayStats failure", ex); + LogHelper.printException(() -> "addUserStats failure", ex); } } + private void addLocalUserStats() { + // time the user saved by using SB + Preference preference = new Preference(statsCategory.getContext()); + statsCategory.addPreference(preference); + + Runnable updateStatsSelfSaved = () -> { + String formatted = statsNumberOfSegmentsSkippedFormatter.format(SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.getInt()); + preference.setTitle(fromHtml(str("sb_stats_self_saved", formatted))); + String formattedSaved = SponsorBlockUtils.getTimeSavedString(SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.getLong() / 1000); + preference.setSummary(fromHtml(str("sb_stats_self_saved_sum", formattedSaved))); + }; + updateStatsSelfSaved.run(); + preference.setOnPreferenceClickListener(preference1 -> { + new AlertDialog.Builder(preference1.getContext()) + .setTitle(str("sb_stats_self_saved_reset_title")) + .setPositiveButton(android.R.string.yes, (dialog, whichButton) -> { + SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.saveValue(SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.defaultValue); + SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.saveValue(SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.defaultValue); + updateStatsSelfSaved.run(); + }) + .setNegativeButton(android.R.string.no, null).show(); + return true; + }); + } + } diff --git a/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java b/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java index eac791f9e..57252b4bd 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java @@ -38,12 +38,12 @@ public class SegmentPlaybackController { * Length of time to show a skip button for a highlight segment, * or a regular segment if {@link SettingsEnum#SB_AUTO_HIDE_SKIP_BUTTON} is enabled. * - * Because Effectively, this value is rounded up to the next second. + * Effectively this value is rounded up to the next second. */ private static final long DURATION_TO_SHOW_SKIP_BUTTON = 3800; /* - * Highlight segments have zero length, as they are a point in time. + * Highlight segments have zero length as they are a point in time. * Draw them on screen using a fixed width bar. * Value is independent of device dpi. */ @@ -524,7 +524,7 @@ public class SegmentPlaybackController { if (!userManuallySkipped) { // check for any smaller embedded segments, and count those as autoskipped - final boolean showSkipToast = SettingsEnum.SB_SHOW_TOAST_ON_SKIP.getBoolean(); + final boolean showSkipToast = SettingsEnum.SB_TOAST_ON_SKIP.getBoolean(); for (final SponsorSegment otherSegment : Objects.requireNonNull(segments)) { if (segmentToSkip.end < otherSegment.start) { break; // no other segments can be contained @@ -651,7 +651,7 @@ public class SegmentPlaybackController { */ public static String appendTimeWithoutSegments(String totalTime) { try { - if (SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean() + if (SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.getBoolean() && !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)) { // Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages return "\u202D" + totalTime + timeWithoutSegments; // u202D = left to right override @@ -665,7 +665,7 @@ public class SegmentPlaybackController { private static void calculateTimeWithoutSegments() { final long currentVideoLength = VideoInformation.getVideoLength(); - if (!SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean() || currentVideoLength <= 0 + if (!SettingsEnum.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.getBoolean() || currentVideoLength <= 0 || segments == null || segments.length == 0) { timeWithoutSegments = null; return; diff --git a/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockSettings.java b/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockSettings.java index 5565ac5b6..595a037ee 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockSettings.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockSettings.java @@ -2,10 +2,13 @@ package app.revanced.integrations.sponsorblock; import static app.revanced.integrations.utils.StringRef.str; +import android.app.AlertDialog; +import android.content.Context; import android.content.SharedPreferences; import android.util.Patterns; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.json.JSONArray; import org.json.JSONException; @@ -21,6 +24,10 @@ import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; public class SponsorBlockSettings { + /** + * Minimum length a SB user id must be, as set by SB API. + */ + private static final int SB_PRIVATE_USER_ID_MINIMUM_LENGTH = 30; public static void importSettings(@NonNull String json) { ReVancedUtils.verifyOnMainThread(); @@ -66,43 +73,43 @@ public class SponsorBlockSettings { } editor.apply(); - String userID = settingsJson.getString("userID"); - if (!isValidSBUserId(userID)) { - throw new IllegalArgumentException("userId is blank"); + if (settingsJson.has("userID")) { + // User id does not exist if user never voted or created any segments. + String userID = settingsJson.getString("userID"); + if (isValidSBUserId(userID)) { + SettingsEnum.SB_PRIVATE_USER_ID.saveValue(userID); + } } - SettingsEnum.SB_UUID.saveValue(userID); - - SettingsEnum.SB_IS_VIP.saveValue(settingsJson.getBoolean("isVip")); - SettingsEnum.SB_SHOW_TOAST_ON_SKIP.saveValue(!settingsJson.getBoolean("dontShowNotice")); + SettingsEnum.SB_USER_IS_VIP.saveValue(settingsJson.getBoolean("isVip")); + SettingsEnum.SB_TOAST_ON_SKIP.saveValue(!settingsJson.getBoolean("dontShowNotice")); SettingsEnum.SB_TRACK_SKIP_COUNT.saveValue(settingsJson.getBoolean("trackViewCount")); + SettingsEnum.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.saveValue(settingsJson.getBoolean("showTimeWithSkips")); String serverAddress = settingsJson.getString("serverAddress"); - if (!isValidSBServerAddress(serverAddress)) { - throw new IllegalArgumentException(str("sb_api_url_invalid")); + if (isValidSBServerAddress(serverAddress)) { // Old versions of ReVanced exported wrong url format + SettingsEnum.SB_API_URL.saveValue(serverAddress); } - SettingsEnum.SB_API_URL.saveValue(serverAddress); - SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.saveValue(settingsJson.getBoolean("showTimeWithSkips")); - final float minDuration = (float)settingsJson.getDouble("minDuration"); + final float minDuration = (float) settingsJson.getDouble("minDuration"); if (minDuration < 0) { throw new IllegalArgumentException("invalid minDuration: " + minDuration); } - SettingsEnum.SB_MIN_DURATION.saveValue(minDuration); + SettingsEnum.SB_SEGMENT_MIN_DURATION.saveValue(minDuration); - try { + if (settingsJson.has("skipCount")) { // Value not exported in old versions of ReVanced int skipCount = settingsJson.getInt("skipCount"); if (skipCount < 0) { throw new IllegalArgumentException("invalid skipCount: " + skipCount); } - SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.saveValue(skipCount); + SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.saveValue(skipCount); + } + if (settingsJson.has("minutesSaved")) { final double minutesSaved = settingsJson.getDouble("minutesSaved"); if (minutesSaved < 0) { throw new IllegalArgumentException("invalid minutesSaved: " + minutesSaved); } - SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.saveValue((long)(minutesSaved * 60 * 1000)); - } catch (JSONException ex) { - // ignore. values were not exported in prior versions of ReVanced + SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.saveValue((long) (minutesSaved * 60 * 1000)); } ReVancedUtils.showToastLong(str("sb_settings_import_successful")); @@ -136,15 +143,17 @@ public class SponsorBlockSettings { categorySelectionsArray.put(behaviorObject); } } - json.put("userID", SettingsEnum.SB_UUID.getString()); - json.put("isVip", SettingsEnum.SB_IS_VIP.getBoolean()); + if (SponsorBlockSettings.userHasSBPrivateId()) { + json.put("userID", SettingsEnum.SB_PRIVATE_USER_ID.getString()); + } + json.put("isVip", SettingsEnum.SB_USER_IS_VIP.getBoolean()); json.put("serverAddress", SettingsEnum.SB_API_URL.getString()); - json.put("dontShowNotice", !SettingsEnum.SB_SHOW_TOAST_ON_SKIP.getBoolean()); - json.put("showTimeWithSkips", SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean()); - json.put("minDuration", SettingsEnum.SB_MIN_DURATION.getFloat()); + json.put("dontShowNotice", !SettingsEnum.SB_TOAST_ON_SKIP.getBoolean()); + json.put("showTimeWithSkips", SettingsEnum.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.getBoolean()); + json.put("minDuration", SettingsEnum.SB_SEGMENT_MIN_DURATION.getFloat()); json.put("trackViewCount", SettingsEnum.SB_TRACK_SKIP_COUNT.getBoolean()); - json.put("skipCount", SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.getInt()); - json.put("minutesSaved", SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.getLong() / (60f * 1000)); + json.put("skipCount", SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.getInt()); + json.put("minutesSaved", SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.getLong() / (60f * 1000)); json.put("categorySelections", categorySelectionsArray); json.put("barTypes", barTypesObject); @@ -152,13 +161,59 @@ public class SponsorBlockSettings { return json.toString(2); } catch (Exception ex) { LogHelper.printInfo(() -> "failed to export settings", ex); // use info level, as we are showing our own toast - ReVancedUtils.showToastLong(str("sb_settings_export_failed")); + ReVancedUtils.showToastLong(str("sb_settings_export_failed", ex)); return ""; } } + /** + * Export the categories using flatten json (no embedded dictionaries or arrays). + */ + public static void exportCategoriesToFlatJson(@Nullable Context dialogContext, + @NonNull JSONObject json) throws JSONException { + ReVancedUtils.verifyOnMainThread(); + initialize(); + + // If user has a SponsorBlock user id then show a warning. + if (dialogContext != null && SponsorBlockSettings.userHasSBPrivateId() + && !SettingsEnum.SB_HIDE_EXPORT_WARNING.getBoolean()) { + new AlertDialog.Builder(dialogContext) + .setMessage(str("sb_settings_revanced_export_user_id_warning")) + .setNeutralButton(str("sb_settings_revanced_export_user_id_warning_dismiss"), + (dialog, which) -> SettingsEnum.SB_HIDE_EXPORT_WARNING.saveValue(true)) + .setPositiveButton(android.R.string.ok, null) + .setCancelable(false) + .show(); + } + + for (SegmentCategory category : SegmentCategory.categoriesWithoutUnsubmitted()) { + category.exportToFlatJSON(json); + } + } + + /** + * Import the categories using flatten json (no embedded dictionaries or arrays). + * + * @return the number of settings imported + */ + public static int importCategoriesFromFlatJson(JSONObject json) throws JSONException { + ReVancedUtils.verifyOnMainThread(); + initialize(); + + int numberOfImportedSettings = 0; + SharedPreferences.Editor editor = SharedPrefCategory.SPONSOR_BLOCK.preferences.edit(); + for (SegmentCategory category : SegmentCategory.categoriesWithoutUnsubmitted()) { + numberOfImportedSettings += category.importFromFlatJSON(json, editor); + } + editor.apply(); + + SegmentCategory.updateEnabledCategories(); + + return numberOfImportedSettings; + } + public static boolean isValidSBUserId(@NonNull String userId) { - return !userId.isEmpty(); + return !userId.isEmpty() && userId.length() >= SB_PRIVATE_USER_ID_MINIMUM_LENGTH; } /** @@ -180,6 +235,29 @@ public class SponsorBlockSettings { return true; } + /** + * @return if the user has ever voted, created a segment, or imported existing SB settings. + */ + public static boolean userHasSBPrivateId() { + return !SettingsEnum.SB_PRIVATE_USER_ID.getString().isEmpty(); + } + + /** + * Use this only if a user id is required (creating segments, voting). + */ + @NonNull + public static String getSBPrivateUserID() { + String uuid = SettingsEnum.SB_PRIVATE_USER_ID.getString(); + if (uuid.isEmpty()) { + uuid = (UUID.randomUUID().toString() + + UUID.randomUUID().toString() + + UUID.randomUUID().toString()) + .replace("-", ""); + SettingsEnum.SB_PRIVATE_USER_ID.saveValue(uuid); + } + return uuid; + } + private static boolean initialized; public static void initialize() { @@ -188,15 +266,6 @@ public class SponsorBlockSettings { } initialized = true; - String uuid = SettingsEnum.SB_UUID.getString(); - if (uuid.isEmpty()) { - uuid = (UUID.randomUUID().toString() + - UUID.randomUUID().toString() + - UUID.randomUUID().toString()) - .replace("-", ""); - SettingsEnum.SB_UUID.saveValue(uuid); - } - SegmentCategory.loadFromPreferences(); } } diff --git a/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockUtils.java b/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockUtils.java index 6f4115862..37020fce5 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockUtils.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/SponsorBlockUtils.java @@ -172,7 +172,7 @@ public class SponsorBlockUtils { for (int i = 0; i < voteOptions.length; i++) { SegmentVote voteOption = voteOptions[i]; String title = voteOption.title.toString(); - if (SettingsEnum.SB_IS_VIP.getBoolean() && segment.isLocked && voteOption.shouldHighlight) { + if (SettingsEnum.SB_USER_IS_VIP.getBoolean() && segment.isLocked && voteOption.shouldHighlight) { items[i] = Html.fromHtml(String.format("%s", LOCKED_COLOR, title)); } else { items[i] = title; @@ -214,20 +214,18 @@ public class SponsorBlockUtils { private static void submitNewSegment() { try { ReVancedUtils.verifyOnMainThread(); - final String uuid = SettingsEnum.SB_UUID.getString(); final long start = newSponsorSegmentStartMillis; final long end = newSponsorSegmentEndMillis; final String videoId = VideoInformation.getVideoId(); final long videoLength = VideoInformation.getVideoLength(); final SegmentCategory segmentCategory = newUserCreatedSegmentCategory; - if (start < 0 || end < 0 || start >= end || videoLength <= 0 || videoId.isEmpty() - || segmentCategory == null || uuid.isEmpty()) { + if (start < 0 || end < 0 || start >= end || videoLength <= 0 || videoId.isEmpty() || segmentCategory == null) { LogHelper.printException(() -> "invalid parameters"); return; } clearUnsubmittedSegmentTimes(); ReVancedUtils.runOnBackgroundThread(() -> { - SBRequester.submitSegments(uuid, videoId, segmentCategory.key, start, end, videoLength); + SBRequester.submitSegments(videoId, segmentCategory.key, start, end, videoLength); SegmentPlaybackController.executeDownloadSegments(videoId); }); } catch (Exception e) { @@ -380,9 +378,9 @@ public class SponsorBlockUtils { return; } segment.recordedAsSkipped = true; - final long totalTimeSkipped = SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.getLong() + segment.length(); - SettingsEnum.SB_SKIPPED_SEGMENTS_TIME_SAVED.saveValue(totalTimeSkipped); - SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.saveValue(SettingsEnum.SB_SKIPPED_SEGMENTS_NUMBER_SKIPPED.getInt() + 1); + final long totalTimeSkipped = SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.getLong() + segment.length(); + SettingsEnum.SB_LOCAL_TIME_SAVED_MILLISECONDS.saveValue(totalTimeSkipped); + SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.saveValue(SettingsEnum.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.getInt() + 1); if (SettingsEnum.SB_TRACK_SKIP_COUNT.getBoolean()) { ReVancedUtils.runOnBackgroundThread(() -> SBRequester.sendSegmentSkippedViewedRequest(segment)); diff --git a/integrations/java/app/revanced/integrations/sponsorblock/objects/SegmentCategory.java b/integrations/java/app/revanced/integrations/sponsorblock/objects/SegmentCategory.java index 6ed56fce9..ed34bf10d 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/objects/SegmentCategory.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/objects/SegmentCategory.java @@ -16,6 +16,9 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -59,6 +62,11 @@ public enum SegmentCategory { private static final StringRef skipSponsorTextCompact = sf("sb_skip_button_compact"); private static final StringRef skipSponsorTextCompactHighlight = sf("sb_skip_button_compact_highlight"); + /** + * Prefix to use when serializing to flat JSON layout used with ReVanced import/export. + */ + private static final String FLAT_JSON_IMPORT_EXPORT_PREFIX = "sb_"; + private static final SegmentCategory[] categoriesWithoutHighlights = new SegmentCategory[]{ SPONSOR, SELF_PROMO, @@ -189,6 +197,8 @@ public enum SegmentCategory { */ @NonNull public CategoryBehaviour behaviour; + @NonNull + public final CategoryBehaviour defaultBehaviour; SegmentCategory(String key, StringRef title, StringRef description, StringRef skipButtonText, @@ -213,7 +223,7 @@ public enum SegmentCategory { this.skippedToastBeginning = Objects.requireNonNull(skippedToastBeginning); this.skippedToastMiddle = Objects.requireNonNull(skippedToastMiddle); this.skippedToastEnd = Objects.requireNonNull(skippedToastEnd); - this.behaviour = Objects.requireNonNull(defaultBehavior); + this.behaviour = this.defaultBehaviour = Objects.requireNonNull(defaultBehavior); this.color = this.defaultColor = defaultColor; this.paint = new Paint(); setColor(defaultColor); @@ -231,10 +241,13 @@ public enum SegmentCategory { } String behaviorString = preferences.getString(key, null); - if (behaviorString != null) { + if (behaviorString == null) { + behaviour = defaultBehaviour; + } else { CategoryBehaviour preferenceBehavior = CategoryBehaviour.byStringKey(behaviorString); if (preferenceBehavior == null) { LogHelper.printException(() -> "Unknown behavior: " + behaviorString); // should never happen + behaviour = defaultBehaviour; } else { behaviour = preferenceBehavior; } @@ -253,6 +266,50 @@ public enum SegmentCategory { editor.putString(key, behaviour.key); } + private String getFlatJsonBehaviorKey() { + return FLAT_JSON_IMPORT_EXPORT_PREFIX + key; + } + private String getFlatJsonColorKey() { + return FLAT_JSON_IMPORT_EXPORT_PREFIX + key + COLOR_PREFERENCE_KEY_SUFFIX; + } + + public void exportToFlatJSON(JSONObject json) throws JSONException { + if (behaviour != defaultBehaviour) { + json.put(getFlatJsonBehaviorKey(), behaviour.key); + } + if (color != defaultColor) { + json.put(getFlatJsonColorKey(), colorString()); + } + } + + /** + * Calling code is responsible for calling {@link #updateEnabledCategories()} and {@link SharedPreferences.Editor#apply()} + */ + public int importFromFlatJSON(JSONObject json, SharedPreferences.Editor editor) throws JSONException { + int numberOfSettingsImported = 0; + String behaviorKey = getFlatJsonBehaviorKey(); + if (json.has(behaviorKey)) { + String behaviorString = json.getString(behaviorKey); + CategoryBehaviour importedBehavior = CategoryBehaviour.byStringKey(behaviorString); + if (importedBehavior == null) { + throw new IllegalArgumentException("unknown behavior: " + behaviorString); + } + behaviour = importedBehavior; + numberOfSettingsImported++; + } else { + behaviour = defaultBehaviour; + } + String colorKey = getFlatJsonColorKey(); + if (json.has(colorKey)) { + setColor(json.getString(colorKey)); + numberOfSettingsImported++; + } else { + color = defaultColor; + } + save(editor); + return numberOfSettingsImported; + } + /** * @return HTML color format string */ @@ -300,7 +357,7 @@ public enum SegmentCategory { */ @NonNull StringRef getSkipButtonText(long segmentStartTime, long videoLength) { - if (SettingsEnum.SB_USE_COMPACT_SKIP_BUTTON.getBoolean()) { + if (SettingsEnum.SB_COMPACT_SKIP_BUTTON.getBoolean()) { return (this == SegmentCategory.HIGHLIGHT) ? skipSponsorTextCompactHighlight : skipSponsorTextCompact; diff --git a/integrations/java/app/revanced/integrations/sponsorblock/objects/UserStats.java b/integrations/java/app/revanced/integrations/sponsorblock/objects/UserStats.java index 663fc6aeb..ae5bdbc4f 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/objects/UserStats.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/objects/UserStats.java @@ -17,7 +17,12 @@ public class UserStats { * "User reputation". Unclear how SB determines this value. */ public final float reputation; + /** + * {@link #segmentCount} plus {@link #ignoredSegmentCount} + */ + public final int totalSegmentCountIncludingIgnored; public final int segmentCount; + public final int ignoredSegmentCount; public final int viewCount; public final double minutesSaved; @@ -26,6 +31,8 @@ public class UserStats { userName = json.getString("userName"); reputation = (float)json.getDouble("reputation"); segmentCount = json.getInt("segmentCount"); + ignoredSegmentCount = json.getInt("ignoredSegmentCount"); + totalSegmentCountIncludingIgnored = segmentCount + ignoredSegmentCount; viewCount = json.getInt("viewCount"); minutesSaved = json.getDouble("minutesSaved"); } @@ -38,6 +45,7 @@ public class UserStats { + ", userName='" + userName + '\'' + ", reputation=" + reputation + ", segmentCount=" + segmentCount + + ", ignoredSegmentCount=" + ignoredSegmentCount + ", viewCount=" + viewCount + ", minutesSaved=" + minutesSaved + '}'; diff --git a/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRequester.java b/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRequester.java index a2985f4dd..7c19444eb 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRequester.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRequester.java @@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit; import app.revanced.integrations.requests.Requester; import app.revanced.integrations.requests.Route; import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.sponsorblock.objects.CategoryBehaviour; +import app.revanced.integrations.sponsorblock.SponsorBlockSettings; import app.revanced.integrations.sponsorblock.objects.SegmentCategory; import app.revanced.integrations.sponsorblock.objects.SponsorSegment; import app.revanced.integrations.sponsorblock.objects.SponsorSegment.SegmentVote; @@ -59,7 +59,7 @@ public class SBRequester { if (responseCode == HTTP_STATUS_CODE_SUCCESS) { JSONArray responseArray = Requester.parseJSONArray(connection); - final long minSegmentDuration = (long) (SettingsEnum.SB_MIN_DURATION.getFloat() * 1000); + final long minSegmentDuration = (long) (SettingsEnum.SB_SEGMENT_MIN_DURATION.getFloat() * 1000); for (int i = 0, length = responseArray.length(); i < length; i++) { JSONObject obj = (JSONObject) responseArray.get(i); JSONArray segment = obj.getJSONArray("segment"); @@ -127,15 +127,16 @@ public class SBRequester { return segments.toArray(new SponsorSegment[0]); } - public static void submitSegments(@NonNull String userPrivateId, @NonNull String videoId, @NonNull String category, + public static void submitSegments(@NonNull String videoId, @NonNull String category, long startTime, long endTime, long videoLength) { ReVancedUtils.verifyOffMainThread(); try { + String privateUserId = SponsorBlockSettings.getSBPrivateUserID(); String start = String.format(Locale.US, TIME_TEMPLATE, startTime / 1000f); String end = String.format(Locale.US, TIME_TEMPLATE, endTime / 1000f); String duration = String.format(Locale.US, TIME_TEMPLATE, videoLength / 1000f); - HttpURLConnection connection = getConnectionFromRoute(SBRoutes.SUBMIT_SEGMENTS, userPrivateId, videoId, category, start, end, duration); + HttpURLConnection connection = getConnectionFromRoute(SBRoutes.SUBMIT_SEGMENTS, privateUserId, videoId, category, start, end, duration); final int responseCode = connection.getResponseCode(); final String messageToToast; @@ -196,7 +197,7 @@ public class SBRequester { ReVancedUtils.runOnBackgroundThread(() -> { try { String segmentUuid = segment.UUID; - String uuid = SettingsEnum.SB_UUID.getString(); + String uuid = SponsorBlockSettings.getSBPrivateUserID(); HttpURLConnection connection = (voteOption == SegmentVote.CATEGORY_CHANGE) ? getConnectionFromRoute(SBRoutes.VOTE_ON_SEGMENT_CATEGORY, uuid, segmentUuid, categoryToVoteFor.key) : getConnectionFromRoute(SBRoutes.VOTE_ON_SEGMENT_QUALITY, uuid, segmentUuid, String.valueOf(voteOption.apiVoteType)); @@ -230,7 +231,7 @@ public class SBRequester { public static UserStats retrieveUserStats() { ReVancedUtils.verifyOffMainThread(); try { - UserStats stats = new UserStats(getJSONObject(SBRoutes.GET_USER_STATS, SettingsEnum.SB_UUID.getString())); + UserStats stats = new UserStats(getJSONObject(SBRoutes.GET_USER_STATS, SponsorBlockSettings.getSBPrivateUserID())); LogHelper.printDebug(() -> "user stats: " + stats); return stats; } catch (IOException ex) { @@ -248,7 +249,7 @@ public class SBRequester { public static String setUsername(@NonNull String username) { ReVancedUtils.verifyOffMainThread(); try { - HttpURLConnection connection = getConnectionFromRoute(SBRoutes.CHANGE_USERNAME, SettingsEnum.SB_UUID.getString(), username); + HttpURLConnection connection = getConnectionFromRoute(SBRoutes.CHANGE_USERNAME, SponsorBlockSettings.getSBPrivateUserID(), username); final int responseCode = connection.getResponseCode(); String responseMessage = connection.getResponseMessage(); if (responseCode == HTTP_STATUS_CODE_SUCCESS) { @@ -262,15 +263,18 @@ public class SBRequester { } public static void runVipCheckInBackgroundIfNeeded() { + if (!SponsorBlockSettings.userHasSBPrivateId()) { + return; // User cannot be a VIP. User has never voted, created any segments, and has not import any SB settings. + } long now = System.currentTimeMillis(); if (now < (SettingsEnum.SB_LAST_VIP_CHECK.getLong() + TimeUnit.DAYS.toMillis(3))) { return; } ReVancedUtils.runOnBackgroundThread(() -> { try { - JSONObject json = getJSONObject(SBRoutes.IS_USER_VIP, SettingsEnum.SB_UUID.getString()); + JSONObject json = getJSONObject(SBRoutes.IS_USER_VIP, SponsorBlockSettings.getSBPrivateUserID()); boolean vip = json.getBoolean("vip"); - SettingsEnum.SB_IS_VIP.saveValue(vip); + SettingsEnum.SB_USER_IS_VIP.saveValue(vip); SettingsEnum.SB_LAST_VIP_CHECK.saveValue(now); } catch (IOException ex) { LogHelper.printInfo(() -> "Failed to check VIP (network error)", ex); // info, so no error toast is shown diff --git a/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRoutes.java b/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRoutes.java index 6bf90a940..5fbe688a3 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRoutes.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/requests/SBRoutes.java @@ -9,7 +9,7 @@ class SBRoutes { static final Route IS_USER_VIP = new Route(GET, "/api/isUserVIP?userID={user_id}"); static final Route GET_SEGMENTS = new Route(GET, "/api/skipSegments?videoID={video_id}&categories={categories}"); static final Route VIEWED_SEGMENT = new Route(POST, "/api/viewedVideoSponsorTime?UUID={segment_id}"); - static final Route GET_USER_STATS = new Route(GET, "/api/userInfo?userID={user_id}&values=[\"userID\",\"userName\",\"reputation\",\"segmentCount\",\"viewCount\",\"minutesSaved\"]"); + static final Route GET_USER_STATS = new Route(GET, "/api/userInfo?userID={user_id}&values=[\"userID\",\"userName\",\"reputation\",\"segmentCount\",\"ignoredSegmentCount\",\"viewCount\",\"minutesSaved\"]"); static final Route CHANGE_USERNAME = new Route(POST, "/api/setUsername?userID={user_id}&username={username}"); static final Route SUBMIT_SEGMENTS = new Route(POST, "/api/skipSegments?userID={user_id}&videoID={video_id}&category={category}&startTime={start_time}&endTime={end_time}&videoDuration={duration}"); static final Route VOTE_ON_SEGMENT_QUALITY = new Route(POST, "/api/voteOnSponsorTime?userID={user_id}&UUID={segment_id}&type={type}"); diff --git a/integrations/java/app/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController.java b/integrations/java/app/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController.java index 57c5b91bf..83528d091 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController.java @@ -88,7 +88,7 @@ public class CreateSegmentButtonController { } private static boolean shouldBeShown() { - return SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_CREATE_NEW_SEGMENT_ENABLED.getBoolean() + return SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_CREATE_NEW_SEGMENT.getBoolean() && !VideoInformation.isAtEndOfVideo(); } diff --git a/integrations/java/app/revanced/integrations/sponsorblock/ui/NewSegmentLayout.java b/integrations/java/app/revanced/integrations/sponsorblock/ui/NewSegmentLayout.java index e1e091826..970462afe 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/ui/NewSegmentLayout.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/ui/NewSegmentLayout.java @@ -53,14 +53,14 @@ public final class NewSegmentLayout extends FrameLayout { initializeButton( context, "sb_new_segment_rewind", - () -> VideoInformation.seekToRelative(-SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt()), + () -> VideoInformation.seekToRelative(-SettingsEnum.SB_CREATE_NEW_SEGMENT_STEP.getInt()), "Rewind button clicked" ); initializeButton( context, "sb_new_segment_forward", - () -> VideoInformation.seekToRelative(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt()), + () -> VideoInformation.seekToRelative(SettingsEnum.SB_CREATE_NEW_SEGMENT_STEP.getInt()), "Forward button clicked" ); diff --git a/integrations/java/app/revanced/integrations/sponsorblock/ui/SponsorBlockViewController.java b/integrations/java/app/revanced/integrations/sponsorblock/ui/SponsorBlockViewController.java index 046d71294..ac3a39098 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/ui/SponsorBlockViewController.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/ui/SponsorBlockViewController.java @@ -213,7 +213,7 @@ public class SponsorBlockViewController { // the buttons automatically set themselves to visible when appropriate, // but if buttons are showing when the end of the video is reached then they need // to be forcefully hidden - if (!SettingsEnum.PREFERRED_AUTO_REPEAT.getBoolean()) { + if (!SettingsEnum.AUTO_REPEAT.getBoolean()) { CreateSegmentButtonController.hide(); VotingButtonController.hide(); } diff --git a/integrations/java/app/revanced/integrations/sponsorblock/ui/VotingButtonController.java b/integrations/java/app/revanced/integrations/sponsorblock/ui/VotingButtonController.java index 6e9fe8284..e0e4d555f 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/ui/VotingButtonController.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/ui/VotingButtonController.java @@ -90,7 +90,7 @@ public class VotingButtonController { } private static boolean shouldBeShown() { - return SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_VOTING_ENABLED.getBoolean() + return SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_VOTING_BUTTON.getBoolean() && SegmentPlaybackController.videoHasSegments() && !VideoInformation.isAtEndOfVideo(); } diff --git a/integrations/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt b/integrations/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt index 5f9fc9160..ebb1fe59d 100644 --- a/integrations/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt +++ b/integrations/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt @@ -24,13 +24,13 @@ class SwipeControlsConfigurationProvider( * should swipe controls for volume be enabled? */ val enableVolumeControls: Boolean - get() = SettingsEnum.ENABLE_SWIPE_VOLUME.boolean + get() = SettingsEnum.SWIPE_VOLUME.boolean /** * should swipe controls for volume be enabled? */ val enableBrightnessControl: Boolean - get() = SettingsEnum.ENABLE_SWIPE_BRIGHTNESS.boolean + get() = SettingsEnum.SWIPE_BRIGHTNESS.boolean /** * is the video player currently in fullscreen mode? @@ -52,14 +52,14 @@ class SwipeControlsConfigurationProvider( * should press-to-swipe be enabled? */ val shouldEnablePressToSwipe: Boolean - get() = SettingsEnum.ENABLE_PRESS_TO_SWIPE.boolean + get() = SettingsEnum.SWIPE_PRESS_TO_ENGAGE.boolean /** * threshold for swipe detection * this may be called rapidly in onScroll, so we have to load it once and then leave it constant */ - val swipeMagnitudeThreshold: Float - get() = SettingsEnum.SWIPE_MAGNITUDE_THRESHOLD.float + val swipeMagnitudeThreshold: Int + get() = SettingsEnum.SWIPE_MAGNITUDE_THRESHOLD.int //endregion //region overlay adjustments @@ -68,7 +68,7 @@ class SwipeControlsConfigurationProvider( * should the overlay enable haptic feedback? */ val shouldEnableHapticFeedback: Boolean - get() = SettingsEnum.ENABLE_SWIPE_HAPTIC_FEEDBACK.boolean + get() = SettingsEnum.SWIPE_HAPTIC_FEEDBACK.boolean /** * how long the overlay should be shown on changes @@ -79,8 +79,8 @@ class SwipeControlsConfigurationProvider( /** * text size for the overlay, in sp */ - val overlayTextSize: Float - get() = SettingsEnum.SWIPE_OVERLAY_TEXT_SIZE.float + val overlayTextSize: Int + get() = SettingsEnum.SWIPE_OVERLAY_TEXT_SIZE.int /** * get the background color for text on the overlay, as a color int diff --git a/integrations/java/app/revanced/integrations/swipecontrols/views/SwipeControlsOverlayLayout.kt b/integrations/java/app/revanced/integrations/swipecontrols/views/SwipeControlsOverlayLayout.kt index b80ed822a..9127c1305 100644 --- a/integrations/java/app/revanced/integrations/swipecontrols/views/SwipeControlsOverlayLayout.kt +++ b/integrations/java/app/revanced/integrations/swipecontrols/views/SwipeControlsOverlayLayout.kt @@ -74,7 +74,7 @@ class SwipeControlsOverlayLayout( setColor(config.overlayTextBackgroundColor) } setTextColor(config.overlayForegroundColor) - setTextSize(TypedValue.COMPLEX_UNIT_SP, config.overlayTextSize) + setTextSize(TypedValue.COMPLEX_UNIT_SP, config.overlayTextSize.toFloat()) compoundDrawablePadding = compoundIconPadding visibility = GONE } diff --git a/integrations/java/app/revanced/integrations/utils/LogHelper.java b/integrations/java/app/revanced/integrations/utils/LogHelper.java index 19e3c127b..b0f96635b 100644 --- a/integrations/java/app/revanced/integrations/utils/LogHelper.java +++ b/integrations/java/app/revanced/integrations/utils/LogHelper.java @@ -125,7 +125,7 @@ public class LogHelper { } else { Log.e(logMessage, messageString, ex); } - if (SettingsEnum.DEBUG_SHOW_TOAST_ON_ERROR.getBoolean()) { + if (SettingsEnum.DEBUG_TOAST_ON_ERROR.getBoolean()) { String toastMessageToDisplay = (userToastMessage != null) ? userToastMessage : outerClassSimpleName + ": " + messageString; diff --git a/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlButton.java b/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlButton.java index 23bcd151a..f1834c5ad 100644 --- a/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlButton.java +++ b/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlButton.java @@ -16,7 +16,7 @@ public class CopyVideoUrlButton extends BottomControlButton { super( viewGroup, "copy_video_url_button", - SettingsEnum.COPY_VIDEO_URL_BUTTON_SHOWN, + SettingsEnum.COPY_VIDEO_URL, view -> CopyVideoUrlPatch.copyUrl(false) ); } diff --git a/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlTimestampButton.java b/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlTimestampButton.java index 3a94344d3..cfd514d7c 100644 --- a/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlTimestampButton.java +++ b/integrations/java/app/revanced/integrations/videoplayer/CopyVideoUrlTimestampButton.java @@ -16,7 +16,7 @@ public class CopyVideoUrlTimestampButton extends BottomControlButton { super( bottomControlsViewGroup, "copy_video_url_timestamp_button", - SettingsEnum.COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN, + SettingsEnum.COPY_VIDEO_URL_TIMESTAMP, view -> CopyVideoUrlPatch.copyUrl(true) ); } diff --git a/integrations/java/app/revanced/integrations/videoplayer/DownloadButton.java b/integrations/java/app/revanced/integrations/videoplayer/DownloadButton.java index dcb581a2f..66e82e37c 100644 --- a/integrations/java/app/revanced/integrations/videoplayer/DownloadButton.java +++ b/integrations/java/app/revanced/integrations/videoplayer/DownloadButton.java @@ -21,7 +21,7 @@ public class DownloadButton extends BottomControlButton { super( viewGroup, "download_button", - SettingsEnum.DOWNLOADS_BUTTON_SHOWN, + SettingsEnum.EXTERNAL_DOWNLOADER, DownloadButton::onDownloadClick ); } @@ -48,7 +48,7 @@ public class DownloadButton extends BottomControlButton { LogHelper.printDebug(() -> "Download button clicked"); final var context = view.getContext(); - var downloaderPackageName = SettingsEnum.DOWNLOADS_PACKAGE_NAME.getString(); + var downloaderPackageName = SettingsEnum.EXTERNAL_DOWNLOADER_PACKAGE_NAME.getString(); boolean packageEnabled = false; try { diff --git a/integrations/java/app/revanced/twitch/settings/SettingsEnum.java b/integrations/java/app/revanced/twitch/settings/SettingsEnum.java index 5dcecea10..6e1833873 100644 --- a/integrations/java/app/revanced/twitch/settings/SettingsEnum.java +++ b/integrations/java/app/revanced/twitch/settings/SettingsEnum.java @@ -154,6 +154,14 @@ public enum SettingsEnum { return (String) value; } + /** + * @return the value of this setting as as generic object type. + */ + @NonNull + public Object getObjectValue() { + return value; + } + public enum ReturnType { BOOLEAN, INTEGER, diff --git a/integrations/java/app/revanced/twitch/settingsmenu/ReVancedSettingsFragment.java b/integrations/java/app/revanced/twitch/settingsmenu/ReVancedSettingsFragment.java index 1da3eacd1..ed76480b9 100644 --- a/integrations/java/app/revanced/twitch/settingsmenu/ReVancedSettingsFragment.java +++ b/integrations/java/app/revanced/twitch/settingsmenu/ReVancedSettingsFragment.java @@ -88,7 +88,23 @@ public class ReVancedSettingsFragment extends PreferenceFragment { ) ); - // Sync all preferences with UI + // TODO: for a developer that uses Twitch: remove duplicated settings data + // 1. remove all default values from the Patches Setting preferences (SwitchPreference, TextPreference, ListPreference) + // 2. enable this code and verify the default is applied + if (false) { + for (SettingsEnum setting : SettingsEnum.values()) { + Preference pref = this.findPreference(setting.path); + if (pref instanceof SwitchPreference) { + ((SwitchPreference) pref).setChecked(setting.getBoolean()); + } else if (pref instanceof EditTextPreference) { + ((EditTextPreference) pref).setText(setting.getObjectValue().toString()); + } else if (pref instanceof ListPreference) { + ((ListPreference) pref).setValue(setting.getObjectValue().toString()); + } + } + } + // TODO: remove this line. On load the UI should apply the values from Settings using the code above. + // It should not apply the UI values to the Settings here syncPreference(null); this.registered = true;