From 2d6e03ac56fc44b475026839d16a413b7d3a4a64 Mon Sep 17 00:00:00 2001 From: Aaron Veil <70171475+anddea@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:16:02 +0300 Subject: [PATCH] fix(YouTube - Settings): `Search bar in settings` can't find `RYD` and `SponsorBlock` settings --- .../integrations/shared/settings/Setting.java | 1 - .../integrations/shared/utils/Utils.java | 6 - .../utils/ReturnYouTubeDislikePatch.java | 2 +- .../ReturnYouTubeDislike.java | 2 +- .../youtube/settings/Settings.java | 4 +- .../KeywordContentAboutPreference.java | 77 --- ...ywordContentAboutWholeWordsPreference.java | 77 --- .../ReVancedPreferenceFragment.java | 47 +- .../ReVancedSettingsPreference.java | 41 +- ...eturnYouTubeDislikePreferenceFragment.java | 175 ----- .../SegmentCategoryListPreference.java | 66 +- .../SponsorBlockImportExportPreference.java | 108 +++ .../SponsorBlockPreferenceFragment.java | 641 ------------------ .../SponsorBlockSettingsPreference.java | 433 ++++++++++++ .../preference/ViewCountAboutPreference.java | 76 --- .../sponsorblock/SponsorBlockSettings.java | 2 + .../objects/CategoryBehaviour.java | 8 +- 17 files changed, 639 insertions(+), 1127 deletions(-) delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutPreference.java delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutWholeWordsPreference.java delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java rename app/src/main/java/app/revanced/integrations/youtube/{sponsorblock/objects => settings/preference}/SegmentCategoryListPreference.java (72%) create mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockImportExportPreference.java delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java create mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockSettingsPreference.java delete mode 100644 app/src/main/java/app/revanced/integrations/youtube/settings/preference/ViewCountAboutPreference.java diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java b/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java index 6092ff99dc..e27229f9bc 100644 --- a/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java +++ b/app/src/main/java/app/revanced/integrations/shared/settings/Setting.java @@ -4,7 +4,6 @@ import static app.revanced.integrations.shared.utils.Utils.isSDKAbove; import android.content.Context; -import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/app/revanced/integrations/shared/utils/Utils.java b/app/src/main/java/app/revanced/integrations/shared/utils/Utils.java index 0e235f94bf..6d66d54fc4 100644 --- a/app/src/main/java/app/revanced/integrations/shared/utils/Utils.java +++ b/app/src/main/java/app/revanced/integrations/shared/utils/Utils.java @@ -391,12 +391,6 @@ public static String getTimeStamp(long time) { } } - public static void setPreferenceIcon(Preference preference, String str) { - final int iconResourceId = ResourceUtils.getDrawableIdentifier(str); - if (iconResourceId == 0) return; - preference.setIcon(iconResourceId); - } - public static void setEditTextDialogTheme(final AlertDialog.Builder builder) { setEditTextDialogTheme(builder, false); } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/utils/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/utils/ReturnYouTubeDislikePatch.java index 9a87b6e54d..a95374c558 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/utils/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/utils/ReturnYouTubeDislikePatch.java @@ -79,7 +79,7 @@ public class ReturnYouTubeDislikePatch { @Nullable private static volatile String lastPrefetchedVideoId; - public static void onRYDStatusChange(boolean rydEnabled) { + public static void onRYDStatusChange() { ReturnYouTubeDislikeApi.resetRateLimits(); // Must remove all values to protect against using stale data // if the user enables RYD while a video is on screen. diff --git a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java index a09f64e6ae..6f2c5fd2c4 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java @@ -135,7 +135,7 @@ public class ReturnYouTubeDislike { leftSeparatorShape = new ShapeDrawable(new RectShape()); leftSeparatorShape.setBounds(leftSeparatorBounds); - locale = resources.getConfiguration().locale; + locale = resources.getConfiguration().getLocales().get(0); ReturnYouTubeDislikeApi.toastOnConnectionError = Settings.RYD_TOAST_ON_CONNECTION_ERROR.get(); } diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java index 251e01ef5b..138d02d2a4 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java @@ -509,7 +509,7 @@ public class Settings extends BaseSettings { /** * Do not use directly, instead use {@link SponsorBlockSettings} */ - public static final StringSetting SB_PRIVATE_USER_ID = new StringSetting("sb_private_user_id_Do_Not_Share", ""); + public static final StringSetting SB_PRIVATE_USER_ID = new StringSetting("sb_private_user_id_Do_Not_Share", "", parent(SB_ENABLED)); public static final IntegerSetting SB_CREATE_NEW_SEGMENT_STEP = new IntegerSetting("sb_create_new_segment_step", 150, parent(SB_ENABLED)); public static final BooleanSetting SB_VOTING_BUTTON = new BooleanSetting("sb_voting_button", FALSE, parent(SB_ENABLED)); public static final BooleanSetting SB_CREATE_NEW_SEGMENT = new BooleanSetting("sb_create_new_segment", FALSE, parent(SB_ENABLED)); @@ -520,7 +520,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting SB_TRACK_SKIP_COUNT = new BooleanSetting("sb_track_skip_count", TRUE, parent(SB_ENABLED)); public static final FloatSetting SB_SEGMENT_MIN_DURATION = new FloatSetting("sb_min_segment_duration", 0F, parent(SB_ENABLED)); public static final BooleanSetting SB_VIDEO_LENGTH_WITHOUT_SEGMENTS = new BooleanSetting("sb_video_length_without_segments", FALSE, parent(SB_ENABLED)); - public static final StringSetting SB_API_URL = new StringSetting("sb_api_url", "https://sponsor.ajay.app"); + public static final StringSetting SB_API_URL = new StringSetting("sb_api_url", "https://sponsor.ajay.app", parent(SB_ENABLED)); public static final BooleanSetting SB_USER_IS_VIP = new BooleanSetting("sb_user_is_vip", FALSE); public static final IntegerSetting SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS = new IntegerSetting("sb_local_time_saved_number_segments", 0); public static final LongSetting SB_LOCAL_TIME_SAVED_MILLISECONDS = new LongSetting("sb_local_time_saved_milliseconds", 0L); diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutPreference.java deleted file mode 100644 index 91d036849e..0000000000 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutPreference.java +++ /dev/null @@ -1,77 +0,0 @@ -package app.revanced.integrations.youtube.settings.preference; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.Preference; -import android.preference.PreferenceManager; -import android.util.AttributeSet; - -import app.revanced.integrations.shared.settings.BooleanSetting; -import app.revanced.integrations.shared.settings.Setting; -import app.revanced.integrations.shared.utils.Utils; -import app.revanced.integrations.youtube.settings.Settings; - -@SuppressWarnings({"deprecation", "unused"}) -public class KeywordContentAboutPreference extends Preference { - - private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> { - // Because this listener may run before the ReVanced settings fragment updates Settings, - // this could show the prior config and not the current. - // - // Push this call to the end of the main run queue, - // so all other listeners are done and Settings is up to date. - Utils.runOnMainThread(this::updateUI); - }; - - public KeywordContentAboutPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public KeywordContentAboutPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public KeywordContentAboutPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public KeywordContentAboutPreference(Context context) { - super(context); - } - - private void addChangeListener() { - Setting.preferences.preferences.registerOnSharedPreferenceChangeListener(listener); - } - - private void removeChangeListener() { - Setting.preferences.preferences.unregisterOnSharedPreferenceChangeListener(listener); - } - - @Override - protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { - super.onAttachedToHierarchy(preferenceManager); - updateUI(); - addChangeListener(); - } - - @Override - protected void onPrepareForRemoval() { - super.onPrepareForRemoval(); - removeChangeListener(); - } - - private void updateUI() { - boolean keywordContentEnabled = false; - - final BooleanSetting[] keywordContentSettings = { - Settings.HIDE_KEYWORD_CONTENT_HOME, - Settings.HIDE_KEYWORD_CONTENT_SEARCH, - Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS, - Settings.HIDE_KEYWORD_CONTENT_COMMENTS - }; - for (BooleanSetting s : keywordContentSettings) { - keywordContentEnabled |= s.get(); - } - setEnabled(keywordContentEnabled); - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutWholeWordsPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutWholeWordsPreference.java deleted file mode 100644 index 50ae21217f..0000000000 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/KeywordContentAboutWholeWordsPreference.java +++ /dev/null @@ -1,77 +0,0 @@ -package app.revanced.integrations.youtube.settings.preference; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.util.AttributeSet; - -import app.revanced.integrations.shared.settings.BooleanSetting; -import app.revanced.integrations.shared.settings.Setting; -import app.revanced.integrations.shared.settings.preference.HtmlPreference; -import app.revanced.integrations.shared.utils.Utils; -import app.revanced.integrations.youtube.settings.Settings; - -@SuppressWarnings({"deprecation", "unused"}) -public class KeywordContentAboutWholeWordsPreference extends HtmlPreference { - - private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> { - // Because this listener may run before the ReVanced settings fragment updates Settings, - // this could show the prior config and not the current. - // - // Push this call to the end of the main run queue, - // so all other listeners are done and Settings is up to date. - Utils.runOnMainThread(this::updateUI); - }; - - public KeywordContentAboutWholeWordsPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public KeywordContentAboutWholeWordsPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public KeywordContentAboutWholeWordsPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public KeywordContentAboutWholeWordsPreference(Context context) { - super(context); - } - - private void addChangeListener() { - Setting.preferences.preferences.registerOnSharedPreferenceChangeListener(listener); - } - - private void removeChangeListener() { - Setting.preferences.preferences.unregisterOnSharedPreferenceChangeListener(listener); - } - - @Override - protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { - super.onAttachedToHierarchy(preferenceManager); - updateUI(); - addChangeListener(); - } - - @Override - protected void onPrepareForRemoval() { - super.onPrepareForRemoval(); - removeChangeListener(); - } - - private void updateUI() { - boolean keywordContentEnabled = false; - - final BooleanSetting[] keywordContentSettings = { - Settings.HIDE_KEYWORD_CONTENT_HOME, - Settings.HIDE_KEYWORD_CONTENT_SEARCH, - Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS, - Settings.HIDE_KEYWORD_CONTENT_COMMENTS - }; - for (BooleanSetting s : keywordContentSettings) { - keywordContentEnabled |= s.get(); - } - setEnabled(keywordContentEnabled); - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java index c8b0ccf637..9c6d77a7b0 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java @@ -1,10 +1,7 @@ package app.revanced.integrations.youtube.settings.preference; -import static com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity.setSearchViewVisibility; -import static com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity.setToolbarText; import static app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment.showRestartDialog; import static app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment.updateListPreferenceSummary; -import static app.revanced.integrations.shared.utils.ResourceUtils.getIdIdentifier; import static app.revanced.integrations.shared.utils.ResourceUtils.getXmlIdentifier; import static app.revanced.integrations.shared.utils.StringRef.str; import static app.revanced.integrations.shared.utils.Utils.getChildView; @@ -15,7 +12,6 @@ import static app.revanced.integrations.youtube.settings.Settings.HIDE_PREVIEW_COMMENT_TYPE; import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -84,6 +80,10 @@ public class ReVancedPreferenceFragment extends PreferenceFragment { if (mPreference == null) return; + if (mPreference instanceof app.revanced.integrations.youtube.settings.preference.SegmentCategoryListPreference) { + return; + } + if (mPreference instanceof SwitchPreference switchPreference) { BooleanSetting boolSetting = (BooleanSetting) setting; if (settingImportInProgress) { @@ -173,40 +173,6 @@ public ReVancedPreferenceFragment() { // Required empty public constructor } - @TargetApi(26) - public void setPreferenceFragmentToolbar(final String key) { - PreferenceFragment fragment; - switch (key) { - case "revanced_preference_screen_ryd" -> - fragment = new ReturnYouTubeDislikePreferenceFragment(); - case "revanced_preference_screen_sb" -> fragment = new SponsorBlockPreferenceFragment(); - default -> { - Logger.printException(() -> "Unknown key: " + key); - return; - } - } - - final Preference mPreference = mPreferenceManager.findPreference(key); - if (mPreference == null) { - return; - } - mPreference.setOnPreferenceClickListener(pref -> { - // Set toolbar text - setToolbarText(pref.getTitle()); - - // Hide the search bar - setSearchViewVisibility(false); - - getFragmentManager() - .beginTransaction() - .replace(getIdIdentifier("revanced_settings_fragments"), fragment) - .addToBackStack(null) - .setReorderingAllowed(true) - .commitAllowingStateLoss(); - return false; - }); - } - private void putPreferenceScreenMap(SortedMap preferenceScreenMap, PreferenceGroup preferenceGroup) { if (preferenceGroup instanceof PreferenceScreen mPreferenceScreen) { preferenceScreenMap.put(mPreferenceScreen.getKey(), mPreferenceScreen); @@ -263,8 +229,6 @@ private void setPreferenceScreenToolbar() { } } - // TODO: Add ability to search for SB and RYD settings - // Map to store dependencies: key is the preference key, value is a list of dependent preferences private final Map> dependencyMap = new HashMap<>(); // Set to track already added preferences to avoid duplicates @@ -283,12 +247,11 @@ public void onCreate(Bundle bundle) { addPreferencesFromResource(getXmlIdentifier("revanced_prefs")); // Initialize toolbars and other UI elements - setPreferenceFragmentToolbar("revanced_preference_screen_ryd"); - setPreferenceFragmentToolbar("revanced_preference_screen_sb"); setPreferenceScreenToolbar(); // Initialize ReVanced settings ReVancedSettingsPreference.initializeReVancedSettings(); + SponsorBlockSettingsPreference.init(getActivity()); // Import/export setBackupRestorePreference(); diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedSettingsPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedSettingsPreference.java index aa934bc359..3df43ae014 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedSettingsPreference.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedSettingsPreference.java @@ -1,15 +1,19 @@ package app.revanced.integrations.youtube.settings.preference; +import static app.revanced.integrations.shared.utils.StringRef.str; import static app.revanced.integrations.shared.utils.Utils.isSDKAbove; import static app.revanced.integrations.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_1; import static app.revanced.integrations.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_3; import static app.revanced.integrations.youtube.utils.ExtendedUtils.isSpoofingToLessThan; import android.preference.Preference; +import android.preference.SwitchPreference; import app.revanced.integrations.shared.settings.Setting; import app.revanced.integrations.youtube.patches.general.MiniplayerPatch; import app.revanced.integrations.youtube.patches.utils.PatchStatus; +import app.revanced.integrations.youtube.patches.utils.ReturnYouTubeDislikePatch; +import app.revanced.integrations.youtube.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.youtube.utils.ExtendedUtils; @@ -47,6 +51,7 @@ public static void initializeReVancedSettings() { LayoutOverrideLinks(); MiniPlayerPreferenceLinks(); NavigationPreferenceLinks(); + RYDPreferenceLinks(); SpeedOverlayPreferenceLinks(); QuickActionsPreferenceLinks(); TabletLayoutLinks(); @@ -211,6 +216,40 @@ private static void NavigationPreferenceLinks() { ); } + /** + * Enable/Disable Preference related to RYD settings + */ + private static void RYDPreferenceLinks() { + if (!(mPreferenceManager.findPreference(Settings.RYD_ENABLED.key) instanceof SwitchPreference enabledPreference)) { + return; + } + if (!(mPreferenceManager.findPreference(Settings.RYD_SHORTS.key) instanceof SwitchPreference shortsPreference)) { + return; + } + if (!(mPreferenceManager.findPreference(Settings.RYD_DISLIKE_PERCENTAGE.key) instanceof SwitchPreference percentagePreference)) { + return; + } + if (!(mPreferenceManager.findPreference(Settings.RYD_COMPACT_LAYOUT.key) instanceof SwitchPreference compactLayoutPreference)) { + return; + } + final Preference.OnPreferenceChangeListener clearAllUICaches = (pref, newValue) -> { + ReturnYouTubeDislike.clearAllUICaches(); + + return true; + }; + enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> { + ReturnYouTubeDislikePatch.onRYDStatusChange(); + + return true; + }); + String shortsSummary = ReturnYouTubeDislikePatch.IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER + ? str("revanced_ryd_shorts_summary_on") + : str("revanced_ryd_shorts_summary_on_disclaimer"); + shortsPreference.setSummaryOn(shortsSummary); + percentagePreference.setOnPreferenceChangeListener(clearAllUICaches); + compactLayoutPreference.setOnPreferenceChangeListener(clearAllUICaches); + } + /** * Enable/Disable Preference related to Speed overlay settings */ @@ -232,4 +271,4 @@ private static void WhitelistPreferenceLinks() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java deleted file mode 100644 index 0f6a3855b8..0000000000 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java +++ /dev/null @@ -1,175 +0,0 @@ -package app.revanced.integrations.youtube.settings.preference; - -import static com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity.setSearchViewVisibility; -import static com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity.setToolbarText; -import static app.revanced.integrations.shared.utils.ResourceUtils.getLayoutIdentifier; -import static app.revanced.integrations.shared.utils.StringRef.str; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceFragment; -import android.preference.PreferenceManager; -import android.preference.PreferenceScreen; -import android.preference.SwitchPreference; - -import app.revanced.integrations.shared.settings.Setting; -import app.revanced.integrations.shared.utils.Logger; -import app.revanced.integrations.youtube.patches.utils.ReturnYouTubeDislikePatch; -import app.revanced.integrations.youtube.returnyoutubedislike.ReturnYouTubeDislike; -import app.revanced.integrations.youtube.settings.Settings; - -@SuppressWarnings("deprecation") -public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment { - - /** - * If dislikes are shown on Shorts. - */ - private SwitchPreference shortsPreference; - - /** - * If dislikes are shown as percentage. - */ - private SwitchPreference percentagePreference; - - /** - * If segmented like/dislike button uses smaller compact layout. - */ - private SwitchPreference compactLayoutPreference; - - /** - * If segmented like/dislike button uses smaller compact layout. - */ - private SwitchPreference toastOnRYDNotAvailable; - - /** - * Styles for preference category. - */ - private final int preferencesCategoryLayout = getLayoutIdentifier("revanced_settings_preferences_category"); - - private void updateUIState() { - shortsPreference.setEnabled(Settings.RYD_SHORTS.isAvailable()); - percentagePreference.setEnabled(Settings.RYD_DISLIKE_PERCENTAGE.isAvailable()); - compactLayoutPreference.setEnabled(Settings.RYD_COMPACT_LAYOUT.isAvailable()); - toastOnRYDNotAvailable.setEnabled(Settings.RYD_TOAST_ON_CONNECTION_ERROR.isAvailable()); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - Activity context = getActivity(); - PreferenceManager manager = getPreferenceManager(); - manager.setSharedPreferencesName(Setting.preferences.name); - PreferenceScreen preferenceScreen = manager.createPreferenceScreen(context); - setPreferenceScreen(preferenceScreen); - - SwitchPreference enabledPreference = new SwitchPreference(context); - enabledPreference.setChecked(Settings.RYD_ENABLED.get()); - enabledPreference.setTitle(str("revanced_ryd_enable_title")); - enabledPreference.setSummaryOn(str("revanced_ryd_enable_summary_on")); - enabledPreference.setSummaryOff(str("revanced_ryd_enable_summary_off")); - enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> { - final Boolean rydIsEnabled = (Boolean) newValue; - Settings.RYD_ENABLED.save(rydIsEnabled); - ReturnYouTubeDislikePatch.onRYDStatusChange(rydIsEnabled); - - updateUIState(); - return true; - }); - preferenceScreen.addPreference(enabledPreference); - - shortsPreference = new SwitchPreference(context); - shortsPreference.setChecked(Settings.RYD_SHORTS.get()); - shortsPreference.setTitle(str("revanced_ryd_shorts_title")); - String shortsSummary = ReturnYouTubeDislikePatch.IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER - ? str("revanced_ryd_shorts_summary_on") - : str("revanced_ryd_shorts_summary_on_disclaimer"); - shortsPreference.setSummaryOn(shortsSummary); - shortsPreference.setSummaryOff(str("revanced_ryd_shorts_summary_off")); - shortsPreference.setOnPreferenceChangeListener((pref, newValue) -> { - Settings.RYD_SHORTS.save((Boolean) newValue); - updateUIState(); - return true; - }); - preferenceScreen.addPreference(shortsPreference); - - percentagePreference = new SwitchPreference(context); - percentagePreference.setChecked(Settings.RYD_DISLIKE_PERCENTAGE.get()); - 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) -> { - Settings.RYD_DISLIKE_PERCENTAGE.save((Boolean) newValue); - ReturnYouTubeDislike.clearAllUICaches(); - updateUIState(); - return true; - }); - preferenceScreen.addPreference(percentagePreference); - - compactLayoutPreference = new SwitchPreference(context); - compactLayoutPreference.setChecked(Settings.RYD_COMPACT_LAYOUT.get()); - 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) -> { - Settings.RYD_COMPACT_LAYOUT.save((Boolean) newValue); - ReturnYouTubeDislike.clearAllUICaches(); - updateUIState(); - return true; - }); - preferenceScreen.addPreference(compactLayoutPreference); - - toastOnRYDNotAvailable = new SwitchPreference(context); - toastOnRYDNotAvailable.setChecked(Settings.RYD_TOAST_ON_CONNECTION_ERROR.get()); - toastOnRYDNotAvailable.setTitle(str("revanced_ryd_toast_on_connection_error_title")); - toastOnRYDNotAvailable.setSummaryOn(str("revanced_ryd_toast_on_connection_error_summary_on")); - toastOnRYDNotAvailable.setSummaryOff(str("revanced_ryd_toast_on_connection_error_summary_off")); - toastOnRYDNotAvailable.setOnPreferenceChangeListener((pref, newValue) -> { - Settings.RYD_TOAST_ON_CONNECTION_ERROR.save((Boolean) newValue); - updateUIState(); - return true; - }); - preferenceScreen.addPreference(toastOnRYDNotAvailable); - - updateUIState(); - - - // About category - - PreferenceCategory aboutCategory = new PreferenceCategory(context); - aboutCategory.setLayoutResource(preferencesCategoryLayout); - aboutCategory.setTitle(str("revanced_ryd_about")); - preferenceScreen.addPreference(aboutCategory); - - // ReturnYouTubeDislike Website - - Preference aboutWebsitePreference = new Preference(context); - aboutWebsitePreference.setTitle(str("revanced_ryd_attribution_title")); - aboutWebsitePreference.setSummary(str("revanced_ryd_attribution_summary")); - aboutWebsitePreference.setOnPreferenceClickListener(pref -> { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://returnyoutubedislike.com")); - pref.getContext().startActivity(i); - return false; - }); - aboutCategory.addPreference(aboutWebsitePreference); - } catch (Exception ex) { - Logger.printException(() -> "onCreate failure", ex); - } - } - - @Override - public void onDetach() { - super.onDetach(); - - // Restore toolbar text - setToolbarText(); - - // Show the search bar - setSearchViewVisibility(true); - } -} diff --git a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/SegmentCategoryListPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SegmentCategoryListPreference.java similarity index 72% rename from app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/SegmentCategoryListPreference.java rename to app/src/main/java/app/revanced/integrations/youtube/settings/preference/SegmentCategoryListPreference.java index 657bae409a..32bc43fe7f 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/SegmentCategoryListPreference.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SegmentCategoryListPreference.java @@ -1,4 +1,4 @@ -package app.revanced.integrations.youtube.sponsorblock.objects; +package app.revanced.integrations.youtube.settings.preference; import static app.revanced.integrations.shared.utils.StringRef.str; @@ -10,6 +10,7 @@ import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; +import android.util.AttributeSet; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TableLayout; @@ -20,31 +21,51 @@ import app.revanced.integrations.shared.utils.Logger; import app.revanced.integrations.shared.utils.Utils; +import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour; +import app.revanced.integrations.youtube.sponsorblock.objects.SegmentCategory; -/** - * @noinspection ALL - */ +@SuppressWarnings({"unused", "deprecation"}) public class SegmentCategoryListPreference extends ListPreference { - private final SegmentCategory category; + private SegmentCategory mCategory; private EditText mEditText; private int mClickedDialogEntryIndex; - public SegmentCategoryListPreference(Context context, SegmentCategory category) { - super(context); - final boolean isHighlightCategory = category == SegmentCategory.HIGHLIGHT; - this.category = Objects.requireNonNull(category); - setKey(category.keyValue); - setDefaultValue(category.behaviour.reVancedKeyValue); + private void init() { + final SegmentCategory segmentCategory = SegmentCategory.byCategoryKey(getKey()); + final boolean isHighlightCategory = segmentCategory == SegmentCategory.HIGHLIGHT; + mCategory = Objects.requireNonNull(segmentCategory); + setDefaultValue(segmentCategory.behaviour.reVancedKeyValue); setEntries(isHighlightCategory ? CategoryBehaviour.getBehaviorDescriptionsWithoutSkipOnce() : CategoryBehaviour.getBehaviorDescriptions()); setEntryValues(isHighlightCategory ? CategoryBehaviour.getBehaviorKeyValuesWithoutSkipOnce() : CategoryBehaviour.getBehaviorKeyValues()); - setSummary(category.description.toString()); + setSummary(segmentCategory.description.toString()); updateTitle(); } + public SegmentCategoryListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + public SegmentCategoryListPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + public SegmentCategoryListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SegmentCategoryListPreference(Context context) { + super(context); + init(); + } + @Override protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { try { @@ -63,13 +84,13 @@ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { row.addView(colorTextLabel); TextView colorDotView = new TextView(context); - colorDotView.setText(category.getCategoryColorDot()); + colorDotView.setText(mCategory.getCategoryColorDot()); colorDotView.setPadding(30, 0, 30, 0); row.addView(colorDotView); mEditText = new EditText(context); mEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS); - mEditText.setText(category.colorString()); + mEditText.setText(mCategory.colorString()); mEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -103,14 +124,12 @@ public void afterTextChanged(Editable s) { table.addView(row); builder.setView(table); - builder.setTitle(category.title.toString()); + builder.setTitle(mCategory.title.toString()); - builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { - onClick(dialog, DialogInterface.BUTTON_POSITIVE); - }); + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> onClick(dialog, DialogInterface.BUTTON_POSITIVE)); builder.setNeutralButton(str("revanced_sb_reset_color"), (dialog, which) -> { try { - category.resetColor(); + mCategory.resetColor(); updateTitle(); Utils.showToastShort(str("revanced_sb_color_reset")); } catch (Exception ex) { @@ -133,13 +152,13 @@ protected void onDialogClosed(boolean positiveResult) { String value = getEntryValues()[mClickedDialogEntryIndex].toString(); if (callChangeListener(value)) { setValue(value); - category.setBehaviour(Objects.requireNonNull(CategoryBehaviour.byReVancedKeyValue(value))); + mCategory.setBehaviour(Objects.requireNonNull(CategoryBehaviour.byReVancedKeyValue(value))); SegmentCategory.updateEnabledCategories(); } String colorString = mEditText.getText().toString(); try { - if (!colorString.equals(category.colorString())) { - category.setColor(colorString); + if (!colorString.equals(mCategory.colorString())) { + mCategory.setColor(colorString); Utils.showToastShort(str("revanced_sb_color_changed")); } } catch (IllegalArgumentException ex) { @@ -153,6 +172,7 @@ protected void onDialogClosed(boolean positiveResult) { } private void updateTitle() { - setTitle(category.getTitleWithColorDot()); + setTitle(mCategory.getTitleWithColorDot()); + setEnabled(Settings.SB_ENABLED.get()); } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockImportExportPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockImportExportPreference.java new file mode 100644 index 0000000000..80d5db0cb9 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockImportExportPreference.java @@ -0,0 +1,108 @@ +package app.revanced.integrations.youtube.settings.preference; + +import static app.revanced.integrations.shared.utils.StringRef.str; + +import android.annotation.TargetApi; +import android.app.AlertDialog; +import android.content.Context; +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.shared.utils.Logger; +import app.revanced.integrations.shared.utils.Utils; +import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings; + +@SuppressWarnings({"unused", "deprecation"}) +public class SponsorBlockImportExportPreference extends EditTextPreference implements Preference.OnPreferenceClickListener { + + private String existingSettings; + + @TargetApi(26) + private void init() { + setSelectable(true); + + EditText editText = getEditText(); + editText.setTextIsSelectable(true); + editText.setAutofillHints((String) null); + editText.setInputType(editText.getInputType() + | InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_FLAG_MULTI_LINE + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 8); // Use a smaller font to reduce text wrap. + + // If the user has a private user id, then include a subtext that mentions not to share it. + String importExportSummary = SponsorBlockSettings.userHasSBPrivateId() + ? str("revanced_sb_settings_ie_sum_warning") + : str("revanced_sb_settings_ie_sum"); + setSummary(importExportSummary); + + setOnPreferenceClickListener(this); + } + + public SponsorBlockImportExportPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + public SponsorBlockImportExportPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + public SponsorBlockImportExportPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SponsorBlockImportExportPreference(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 = SponsorBlockSettings.exportDesktopSettings(); + getEditText().setText(existingSettings); + } catch (Exception ex) { + Logger.printException(() -> "showDialog failure", ex); + } + return true; + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + try { + Utils.setEditTextDialogTheme(builder); + super.onPrepareDialogBuilder(builder); + // Show the user the settings in JSON format. + builder.setTitle(getTitle()); + builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> + Utils.setClipboard(getEditText().getText().toString(), str("revanced_sb_share_copy_settings_success"))) + .setPositiveButton(android.R.string.ok, (dialog, which) -> + importSettings(getEditText().getText().toString())); + } catch (Exception ex) { + Logger.printException(() -> "onPrepareDialogBuilder failure", ex); + } + } + + private void importSettings(String replacementSettings) { + try { + if (replacementSettings.equals(existingSettings)) { + return; + } + SponsorBlockSettings.importDesktopSettings(replacementSettings); + SponsorBlockSettingsPreference.updateSegmentCategories(); + SponsorBlockSettingsPreference.fetchAndDisplayStats(); + SponsorBlockSettingsPreference.updateUI(); + } catch (Exception ex) { + Logger.printException(() -> "importSettings failure", ex); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java deleted file mode 100644 index 23bf7540b0..0000000000 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockPreferenceFragment.java +++ /dev/null @@ -1,641 +0,0 @@ -package app.revanced.integrations.youtube.settings.preference; - -import static android.text.Html.fromHtml; -import static com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity.setSearchViewVisibility; -import static com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity.setToolbarText; -import static app.revanced.integrations.shared.utils.ResourceUtils.getLayoutIdentifier; -import static app.revanced.integrations.shared.utils.StringRef.str; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.preference.EditTextPreference; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceFragment; -import android.preference.PreferenceManager; -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; -import androidx.annotation.Nullable; - -import app.revanced.integrations.shared.settings.Setting; -import app.revanced.integrations.shared.settings.preference.ResettableEditTextPreference; -import app.revanced.integrations.shared.utils.Logger; -import app.revanced.integrations.shared.utils.Utils; -import app.revanced.integrations.youtube.settings.Settings; -import app.revanced.integrations.youtube.sponsorblock.SegmentPlaybackController; -import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings; -import app.revanced.integrations.youtube.sponsorblock.SponsorBlockUtils; -import app.revanced.integrations.youtube.sponsorblock.objects.SegmentCategory; -import app.revanced.integrations.youtube.sponsorblock.objects.SegmentCategoryListPreference; -import app.revanced.integrations.youtube.sponsorblock.objects.UserStats; -import app.revanced.integrations.youtube.sponsorblock.requests.SBRequester; -import app.revanced.integrations.youtube.sponsorblock.ui.SponsorBlockViewController; - -@SuppressWarnings("deprecation") -public class SponsorBlockPreferenceFragment extends PreferenceFragment { - - private SwitchPreference sbEnabled; - private SwitchPreference addNewSegment; - private SwitchPreference votingEnabled; - private SwitchPreference compactSkipButton; - private SwitchPreference autoHideSkipSegmentButton; - private SwitchPreference showSkipToast; - private SwitchPreference trackSkips; - private SwitchPreference showTimeWithoutSegments; - private SwitchPreference toastOnConnectionError; - - private ResettableEditTextPreference newSegmentStep; - private ResettableEditTextPreference minSegmentDuration; - private ResettableEditTextPreference privateUserId; - private EditTextPreference importExport; - private EditTextPreference apiUrl; - - private PreferenceCategory statsCategory; - private PreferenceCategory segmentCategory; - - private final int preferencesCategoryLayout = getLayoutIdentifier("revanced_settings_preferences_category"); - - private void updateUI() { - try { - final boolean enabled = Settings.SB_ENABLED.get(); - if (!enabled) { - SponsorBlockViewController.hideAll(); - SegmentPlaybackController.clearData(); - } else if (!Settings.SB_CREATE_NEW_SEGMENT.get()) { - SponsorBlockViewController.hideNewSegmentLayout(); - } - // Voting and add new segment buttons automatically shows/hide themselves. - - sbEnabled.setChecked(enabled); - - addNewSegment.setChecked(Settings.SB_CREATE_NEW_SEGMENT.get()); - addNewSegment.setEnabled(enabled); - - votingEnabled.setChecked(Settings.SB_VOTING_BUTTON.get()); - votingEnabled.setEnabled(enabled); - - compactSkipButton.setChecked(Settings.SB_COMPACT_SKIP_BUTTON.get()); - compactSkipButton.setEnabled(enabled); - - autoHideSkipSegmentButton.setChecked(Settings.SB_AUTO_HIDE_SKIP_BUTTON.get()); - autoHideSkipSegmentButton.setEnabled(enabled); - - showSkipToast.setChecked(Settings.SB_TOAST_ON_SKIP.get()); - showSkipToast.setEnabled(enabled); - - toastOnConnectionError.setChecked(Settings.SB_TOAST_ON_CONNECTION_ERROR.get()); - toastOnConnectionError.setEnabled(enabled); - - trackSkips.setChecked(Settings.SB_TRACK_SKIP_COUNT.get()); - trackSkips.setEnabled(enabled); - - showTimeWithoutSegments.setChecked(Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.get()); - showTimeWithoutSegments.setEnabled(enabled); - - newSegmentStep.setText((Settings.SB_CREATE_NEW_SEGMENT_STEP.get()).toString()); - newSegmentStep.setEnabled(enabled); - - minSegmentDuration.setText((Settings.SB_SEGMENT_MIN_DURATION.get()).toString()); - minSegmentDuration.setEnabled(enabled); - - privateUserId.setText(Settings.SB_PRIVATE_USER_ID.get()); - privateUserId.setEnabled(enabled); - - // If the user has a private user id, then include a subtext that mentions not to share it. - String importExportSummary = SponsorBlockSettings.userHasSBPrivateId() - ? str("revanced_sb_settings_ie_sum_warning") - : str("revanced_sb_settings_ie_sum"); - importExport.setSummary(importExportSummary); - - apiUrl.setEnabled(enabled); - importExport.setEnabled(enabled); - segmentCategory.setEnabled(enabled); - statsCategory.setEnabled(enabled); - } catch (Exception ex) { - Logger.printException(() -> "update settings UI failure", ex); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - Activity context = getActivity(); - PreferenceManager manager = getPreferenceManager(); - manager.setSharedPreferencesName(Setting.preferences.name); - PreferenceScreen preferenceScreen = manager.createPreferenceScreen(context); - setPreferenceScreen(preferenceScreen); - - SponsorBlockSettings.initialize(); - - sbEnabled = new SwitchPreference(context); - sbEnabled.setTitle(str("revanced_sb_enable_sb")); - sbEnabled.setSummary(str("revanced_sb_enable_sb_sum")); - preferenceScreen.addPreference(sbEnabled); - sbEnabled.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_ENABLED.save((Boolean) newValue); - updateUI(); - return true; - }); - - addCreateSegmentCategory(context, preferenceScreen); - addAppearanceCategory(context, preferenceScreen); - - segmentCategory = new PreferenceCategory(context); - segmentCategory.setTitle(str("revanced_sb_diff_segments")); - segmentCategory.setLayoutResource(preferencesCategoryLayout); - preferenceScreen.addPreference(segmentCategory); - updateSegmentCategories(); - - addGeneralCategory(context, preferenceScreen); - - statsCategory = new PreferenceCategory(context); - statsCategory.setLayoutResource(preferencesCategoryLayout); - statsCategory.setTitle(str("revanced_sb_stats")); - preferenceScreen.addPreference(statsCategory); - fetchAndDisplayStats(); - - addAboutCategory(context, preferenceScreen); - - updateUI(); - } catch (Exception ex) { - Logger.printException(() -> "onCreate failure", ex); - } - } - - @Override - public void onDetach() { - super.onDetach(); - - // Restore toolbar text - setToolbarText(); - - // Show the search bar - setSearchViewVisibility(true); - } - - private void addAppearanceCategory(Context context, PreferenceScreen screen) { - PreferenceCategory category = new PreferenceCategory(context); - screen.addPreference(category); - category.setLayoutResource(preferencesCategoryLayout); - category.setTitle(str("revanced_sb_appearance_category")); - - compactSkipButton = new SwitchPreference(context); - compactSkipButton.setTitle(str("revanced_sb_enable_compact_skip_button")); - compactSkipButton.setSummaryOn(str("revanced_sb_enable_compact_skip_button_sum_on")); - compactSkipButton.setSummaryOff(str("revanced_sb_enable_compact_skip_button_sum_off")); - category.addPreference(compactSkipButton); - compactSkipButton.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_COMPACT_SKIP_BUTTON.save((Boolean) newValue); - updateUI(); - return true; - }); - - autoHideSkipSegmentButton = new SwitchPreference(context); - autoHideSkipSegmentButton.setTitle(str("revanced_sb_enable_auto_hide_skip_segment_button")); - autoHideSkipSegmentButton.setSummaryOn(str("revanced_sb_enable_auto_hide_skip_segment_button_sum_on")); - autoHideSkipSegmentButton.setSummaryOff(str("revanced_sb_enable_auto_hide_skip_segment_button_sum_off")); - category.addPreference(autoHideSkipSegmentButton); - autoHideSkipSegmentButton.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_AUTO_HIDE_SKIP_BUTTON.save((Boolean) newValue); - updateUI(); - return true; - }); - - showSkipToast = new SwitchPreference(context); - showSkipToast.setTitle(str("revanced_sb_general_skiptoast")); - showSkipToast.setSummaryOn(str("revanced_sb_general_skiptoast_sum_on")); - showSkipToast.setSummaryOff(str("revanced_sb_general_skiptoast_sum_off")); - showSkipToast.setOnPreferenceClickListener(preference1 -> { - Utils.showToastShort(str("revanced_sb_skipped_sponsor")); - return false; - }); - showSkipToast.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_TOAST_ON_SKIP.save((Boolean) newValue); - updateUI(); - return true; - }); - category.addPreference(showSkipToast); - - showTimeWithoutSegments = new SwitchPreference(context); - showTimeWithoutSegments.setTitle(str("revanced_sb_general_time_without")); - showTimeWithoutSegments.setSummaryOn(str("revanced_sb_general_time_without_sum_on")); - showTimeWithoutSegments.setSummaryOff(str("revanced_sb_general_time_without_sum_off")); - showTimeWithoutSegments.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.save((Boolean) newValue); - updateUI(); - return true; - }); - category.addPreference(showTimeWithoutSegments); - } - - private void addCreateSegmentCategory(Context context, PreferenceScreen screen) { - PreferenceCategory category = new PreferenceCategory(context); - screen.addPreference(category); - category.setLayoutResource(preferencesCategoryLayout); - category.setTitle(str("revanced_sb_create_segment_category")); - - addNewSegment = new SwitchPreference(context); - addNewSegment.setTitle(str("revanced_sb_enable_create_segment")); - addNewSegment.setSummaryOn(str("revanced_sb_enable_create_segment_sum_on")); - addNewSegment.setSummaryOff(str("revanced_sb_enable_create_segment_sum_off")); - addNewSegment.setOnPreferenceChangeListener((preference1, o) -> { - Boolean newValue = (Boolean) o; - if (newValue && !Settings.SB_SEEN_GUIDELINES.get()) { - new AlertDialog.Builder(preference1.getContext()) - .setTitle(str("revanced_sb_guidelines_popup_title")) - .setMessage(str("revanced_sb_guidelines_popup_content")) - .setNegativeButton(str("revanced_sb_guidelines_popup_already_read"), null) - .setPositiveButton(str("revanced_sb_guidelines_popup_open"), (dialogInterface, i) -> openGuidelines()) - .setOnDismissListener(dialog -> Settings.SB_SEEN_GUIDELINES.save(true)) - .setCancelable(false) - .show(); - } - Settings.SB_CREATE_NEW_SEGMENT.save(newValue); - updateUI(); - return true; - }); - Utils.setPreferenceIcon(addNewSegment, "sb_enable_create_segment"); - category.addPreference(addNewSegment); - - newSegmentStep = new ResettableEditTextPreference(context); - newSegmentStep.setTitle(str("revanced_sb_general_adjusting")); - newSegmentStep.setSummary(str("revanced_sb_general_adjusting_sum")); - newSegmentStep.setKey(Settings.SB_CREATE_NEW_SEGMENT_STEP.key); - newSegmentStep.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER); - newSegmentStep.setOnPreferenceChangeListener((preference1, newValue) -> { - try { - final int newAdjustmentValue = Integer.parseInt(newValue.toString()); - if (newAdjustmentValue != 0) { - Settings.SB_CREATE_NEW_SEGMENT_STEP.save(newAdjustmentValue); - return true; - } - } catch (NumberFormatException ex) { - Logger.printInfo(() -> "Invalid new segment step", ex); - } - - Utils.showToastLong(str("revanced_sb_general_adjusting_invalid")); - updateUI(); - return false; - }); - Utils.setPreferenceIcon(newSegmentStep, "empty_icon"); - category.addPreference(newSegmentStep); - - Preference guidelinePreferences = new Preference(context); - guidelinePreferences.setTitle(str("revanced_sb_guidelines_preference_title")); - guidelinePreferences.setSummary(str("revanced_sb_guidelines_preference_sum")); - guidelinePreferences.setOnPreferenceClickListener(preference1 -> { - openGuidelines(); - return true; - }); - Utils.setPreferenceIcon(guidelinePreferences, "empty_icon"); - category.addPreference(guidelinePreferences); - - votingEnabled = new SwitchPreference(context); - votingEnabled.setTitle(str("revanced_sb_enable_voting")); - votingEnabled.setSummaryOn(str("revanced_sb_enable_voting_sum_on")); - votingEnabled.setSummaryOff(str("revanced_sb_enable_voting_sum_off")); - votingEnabled.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_VOTING_BUTTON.save((Boolean) newValue); - updateUI(); - return true; - }); - Utils.setPreferenceIcon(votingEnabled, "sb_enable_voting"); - category.addPreference(votingEnabled); - } - - @TargetApi(26) - private void addGeneralCategory(final Context context, PreferenceScreen screen) { - PreferenceCategory category = new PreferenceCategory(context); - screen.addPreference(category); - category.setLayoutResource(preferencesCategoryLayout); - category.setTitle(str("revanced_sb_general")); - - toastOnConnectionError = new SwitchPreference(context); - toastOnConnectionError.setTitle(str("revanced_sb_toast_on_connection_error_title")); - toastOnConnectionError.setSummaryOn(str("revanced_sb_toast_on_connection_error_summary_on")); - toastOnConnectionError.setSummaryOff(str("revanced_sb_toast_on_connection_error_summary_off")); - toastOnConnectionError.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_TOAST_ON_CONNECTION_ERROR.save((Boolean) newValue); - updateUI(); - return true; - }); - category.addPreference(toastOnConnectionError); - - trackSkips = new SwitchPreference(context); - trackSkips.setTitle(str("revanced_sb_general_skipcount")); - trackSkips.setSummaryOn(str("revanced_sb_general_skipcount_sum_on")); - trackSkips.setSummaryOff(str("revanced_sb_general_skipcount_sum_off")); - trackSkips.setOnPreferenceChangeListener((preference1, newValue) -> { - Settings.SB_TRACK_SKIP_COUNT.save((Boolean) newValue); - updateUI(); - return true; - }); - category.addPreference(trackSkips); - - minSegmentDuration = new ResettableEditTextPreference(context); - minSegmentDuration.setTitle(str("revanced_sb_general_min_duration")); - minSegmentDuration.setSummary(str("revanced_sb_general_min_duration_sum")); - minSegmentDuration.setKey(Settings.SB_SEGMENT_MIN_DURATION.key); - minSegmentDuration.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); - minSegmentDuration.setOnPreferenceChangeListener((preference1, newValue) -> { - try { - Float minTimeDuration = Float.valueOf(newValue.toString()); - Settings.SB_SEGMENT_MIN_DURATION.save(minTimeDuration); - return true; - } catch (NumberFormatException ex) { - Logger.printInfo(() -> "Invalid minimum segment duration", ex); - } - - Utils.showToastLong(str("revanced_sb_general_min_duration_invalid")); - updateUI(); - return false; - }); - category.addPreference(minSegmentDuration); - - privateUserId = new ResettableEditTextPreference(context); - privateUserId.setTitle(str("revanced_sb_general_uuid")); - privateUserId.setSummary(str("revanced_sb_general_uuid_sum")); - privateUserId.setKey(Settings.SB_PRIVATE_USER_ID.key); - privateUserId.setOnPreferenceChangeListener((preference1, newValue) -> { - String newUUID = newValue.toString(); - if (!SponsorBlockSettings.isValidSBUserId(newUUID)) { - Utils.showToastLong(str("revanced_sb_general_uuid_invalid")); - return false; - } - - Settings.SB_PRIVATE_USER_ID.save(newUUID); - updateUI(); - fetchAndDisplayStats(); - return true; - }); - category.addPreference(privateUserId); - - apiUrl = new EditTextPreference(context) { - @Override - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { - EditText editText = getEditText(); - String apiUrl = Settings.SB_API_URL.get(); - editText.setText(apiUrl); - editText.setSelection(apiUrl.length()); - - Utils.setEditTextDialogTheme(builder); - builder.setTitle(getTitle()); - builder.setNeutralButton(str("revanced_sb_reset"), (dialog, which) -> { - String defaultStringValue = Settings.SB_API_URL.defaultValue; - editText.setText(defaultStringValue); - editText.setSelection(defaultStringValue.length()); // move cursor to end of text - - Settings.SB_API_URL.resetToDefault(); - Utils.showToastLong(str("revanced_sb_api_url_reset")); - }); - builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { - String serverAddress = editText.getText().toString(); - if (!SponsorBlockSettings.isValidSBServerAddress(serverAddress)) { - Utils.showToastLong(str("revanced_sb_api_url_invalid")); - } else if (!serverAddress.equals(Settings.SB_API_URL.get())) { - Settings.SB_API_URL.save(serverAddress); - Utils.showToastLong(str("revanced_sb_api_url_changed")); - } - }); - super.onPrepareDialogBuilder(builder); - } - }; - apiUrl.setTitle(str("revanced_sb_general_api_url")); - apiUrl.setSummary(Html.fromHtml(str("revanced_sb_general_api_url_sum"))); - apiUrl.setKey(Settings.SB_API_URL.key); - apiUrl.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); - category.addPreference(apiUrl); - - importExport = new EditTextPreference(context) { - @Override - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { - Utils.setEditTextDialogTheme(builder); - super.onPrepareDialogBuilder(builder); - builder.setTitle(getTitle()); - builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> - Utils.setClipboard(getEditText().getText().toString(), str("revanced_sb_share_copy_settings_success"))); - } - }; - importExport.setTitle(str("revanced_sb_settings_ie")); - // Summary is set in updateUI() - importExport.getEditText().setInputType(InputType.TYPE_CLASS_TEXT - | InputType.TYPE_TEXT_FLAG_MULTI_LINE - | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); - importExport.getEditText().setAutofillHints((String) null); - importExport.getEditText().setTextSize(TypedValue.COMPLEX_UNIT_PT, 8); - importExport.setOnPreferenceClickListener(preference1 -> { - importExport.getEditText().setText(SponsorBlockSettings.exportDesktopSettings()); - return true; - }); - importExport.setOnPreferenceChangeListener((preference1, newValue) -> { - SponsorBlockSettings.importDesktopSettings((String) newValue); - updateSegmentCategories(); - fetchAndDisplayStats(); - updateUI(); - return true; - }); - category.addPreference(importExport); - } - - private void updateSegmentCategories() { - try { - segmentCategory.removeAll(); - - Activity activity = getActivity(); - for (SegmentCategory category : SegmentCategory.categoriesWithoutUnsubmitted()) { - segmentCategory.addPreference(new SegmentCategoryListPreference(activity, category)); - } - } catch (Exception ex) { - Logger.printException(() -> "updateSegmentCategories failure", ex); - } - } - - private void addAboutCategory(Context context, PreferenceScreen screen) { - PreferenceCategory category = new PreferenceCategory(context); - screen.addPreference(category); - category.setLayoutResource(preferencesCategoryLayout); - category.setTitle(str("revanced_sb_about")); - - { - Preference preference = new Preference(context); - category.addPreference(preference); - preference.setTitle(str("revanced_sb_about_api")); - preference.setSummary(str("revanced_sb_about_api_sum")); - preference.setOnPreferenceClickListener(preference1 -> { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://sponsor.ajay.app")); - preference1.getContext().startActivity(i); - return false; - }); - } - } - - private void openGuidelines() { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse("https://wiki.sponsor.ajay.app/w/Guidelines")); - getActivity().startActivity(intent); - } - - 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); - if (Settings.SB_ENABLED.get()) { - loadingPlaceholderPreference.setTitle(str("revanced_sb_stats_loading")); - Utils.runOnBackgroundThread(() -> { - UserStats stats = SBRequester.retrieveUserStats(); - Utils.runOnMainThread(() -> { // get back on main thread to modify UI elements - addUserStats(loadingPlaceholderPreference, stats); - addLocalUserStats(); - }); - }); - } else { - loadingPlaceholderPreference.setTitle(str("revanced_sb_stats_sb_disabled")); - } - } catch (Exception ex) { - Logger.printException(() -> "fetchAndDisplayStats failure", ex); - } - } - - private void addUserStats(@NonNull Preference loadingPlaceholder, @Nullable UserStats stats) { - Utils.verifyOnMainThread(); - try { - if (stats == null) { - loadingPlaceholder.setTitle(str("revanced_sb_stats_connection_failure")); - return; - } - 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. - ResettableEditTextPreference preference = new ResettableEditTextPreference(context); - statsCategory.addPreference(preference); - String userName = stats.userName; - preference.setTitle(fromHtml(str("revanced_sb_stats_username", userName))); - preference.setSummary(str("revanced_sb_stats_username_change")); - preference.setText(userName); - preference.setOnPreferenceChangeListener((preference1, value) -> { - Utils.runOnBackgroundThread(() -> { - String newUserName = (String) value; - String errorMessage = SBRequester.setUsername(newUserName); - Utils.runOnMainThread(() -> { - if (errorMessage == null) { - preference.setTitle(fromHtml(str("revanced_sb_stats_username", newUserName))); - preference.setText(newUserName); - Utils.showToastLong(str("revanced_sb_stats_username_changed")); - } else { - preference.setText(userName); // revert to previous - Utils.showToastLong(errorMessage); - } - }); - }); - return true; - }); - } - - { - // number of segment submissions (does not include ignored segments) - Preference preference = new Preference(context); - statsCategory.addPreference(preference); - String formatted = SponsorBlockUtils.getNumberOfSkipsString(stats.segmentCount); - preference.setTitle(fromHtml(str("revanced_sb_stats_submissions", formatted))); - preference.setSummary(str("revanced_sb_stats_submissions_sum")); - if (stats.totalSegmentCountIncludingIgnored == 0) { - preference.setSelectable(false); - } else { - preference.setOnPreferenceClickListener(preference1 -> { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://sb.ltn.fi/userid/" + stats.publicUserId)); - preference1.getContext().startActivity(i); - return true; - }); - } - } - - { - // "user reputation". Usually not useful, since it appears most users have zero reputation. - // But if there is a reputation, then show it here - Preference preference = new Preference(context); - preference.setTitle(fromHtml(str("revanced_sb_stats_reputation", stats.reputation))); - preference.setSelectable(false); - if (stats.reputation != 0) { - statsCategory.addPreference(preference); - } - } - - { - // time saved for other users - Preference preference = new Preference(context); - statsCategory.addPreference(preference); - - String stats_saved; - String stats_saved_sum; - if (stats.totalSegmentCountIncludingIgnored == 0) { - stats_saved = str("revanced_sb_stats_saved_zero"); - stats_saved_sum = str("revanced_sb_stats_saved_sum_zero"); - } else { - stats_saved = str("revanced_sb_stats_saved", - SponsorBlockUtils.getNumberOfSkipsString(stats.viewCount)); - stats_saved_sum = str("revanced_sb_stats_saved_sum", SponsorBlockUtils.getTimeSavedString((long) (60 * stats.minutesSaved))); - } - preference.setTitle(fromHtml(stats_saved)); - preference.setSummary(fromHtml(stats_saved_sum)); - preference.setOnPreferenceClickListener(preference1 -> { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://sponsor.ajay.app/stats/")); - preference1.getContext().startActivity(i); - return false; - }); - } - } catch (Exception ex) { - Logger.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 = SponsorBlockUtils.getNumberOfSkipsString(Settings.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.get()); - preference.setTitle(fromHtml(str("revanced_sb_stats_self_saved", formatted))); - String formattedSaved = SponsorBlockUtils.getTimeSavedString(Settings.SB_LOCAL_TIME_SAVED_MILLISECONDS.get() / 1000); - preference.setSummary(fromHtml(str("revanced_sb_stats_self_saved_sum", formattedSaved))); - }; - updateStatsSelfSaved.run(); - preference.setOnPreferenceClickListener(preference1 -> { - new AlertDialog.Builder(preference1.getContext()) - .setTitle(str("revanced_sb_stats_self_saved_reset_title")) - .setPositiveButton(android.R.string.yes, (dialog, whichButton) -> { - Settings.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.resetToDefault(); - Settings.SB_LOCAL_TIME_SAVED_MILLISECONDS.resetToDefault(); - updateStatsSelfSaved.run(); - }) - .setNegativeButton(android.R.string.no, null).show(); - return true; - }); - } - -} diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockSettingsPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockSettingsPreference.java new file mode 100644 index 0000000000..48c6cbee60 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/SponsorBlockSettingsPreference.java @@ -0,0 +1,433 @@ +package app.revanced.integrations.youtube.settings.preference; + +import static android.text.Html.fromHtml; + +import static app.revanced.integrations.shared.utils.ResourceUtils.getLayoutIdentifier; +import static app.revanced.integrations.shared.utils.StringRef.str; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; +import android.text.InputType; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TableLayout; +import android.widget.TableRow; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Objects; + +import app.revanced.integrations.shared.settings.BooleanSetting; +import app.revanced.integrations.shared.settings.Setting; +import app.revanced.integrations.shared.settings.preference.ResettableEditTextPreference; +import app.revanced.integrations.shared.utils.Logger; +import app.revanced.integrations.shared.utils.Utils; +import app.revanced.integrations.youtube.patches.utils.PatchStatus; +import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.youtube.sponsorblock.SegmentPlaybackController; +import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings; +import app.revanced.integrations.youtube.sponsorblock.SponsorBlockUtils; +import app.revanced.integrations.youtube.sponsorblock.objects.SegmentCategory; +import app.revanced.integrations.youtube.sponsorblock.objects.UserStats; +import app.revanced.integrations.youtube.sponsorblock.requests.SBRequester; +import app.revanced.integrations.youtube.sponsorblock.ui.SponsorBlockViewController; + +@SuppressWarnings({"unused", "deprecation"}) +public class SponsorBlockSettingsPreference extends ReVancedPreferenceFragment { + + private static PreferenceCategory statsCategory; + + private static final int preferencesCategoryLayout = getLayoutIdentifier("revanced_settings_preferences_category"); + + private static final Preference.OnPreferenceChangeListener updateUI = (pref, newValue) -> { + updateUI(); + + return true; + }; + + @NonNull + private static SwitchPreference findSwitchPreference(BooleanSetting setting) { + final String key = setting.key; + if (mPreferenceManager.findPreference(key) instanceof SwitchPreference switchPreference) { + switchPreference.setOnPreferenceChangeListener(updateUI); + return switchPreference; + } else { + throw new IllegalStateException("SwitchPreference is null: " + key); + } + } + + @NonNull + private static ResettableEditTextPreference findResettableEditTextPreference(Setting setting) { + final String key = setting.key; + if (mPreferenceManager.findPreference(key) instanceof ResettableEditTextPreference switchPreference) { + switchPreference.setOnPreferenceChangeListener(updateUI); + return switchPreference; + } else { + throw new IllegalStateException("ResettableEditTextPreference is null: " + key); + } + } + + public static void updateUI() { + if (!Settings.SB_ENABLED.get()) { + SponsorBlockViewController.hideAll(); + SegmentPlaybackController.clearData(); + } else if (!Settings.SB_CREATE_NEW_SEGMENT.get()) { + SponsorBlockViewController.hideNewSegmentLayout(); + } + } + + @TargetApi(26) + public static void init(Activity mActivity) { + if (!PatchStatus.SponsorBlock()) { + return; + } + + final SwitchPreference sbEnabled = findSwitchPreference(Settings.SB_ENABLED); + sbEnabled.setOnPreferenceClickListener(preference -> { + updateUI(); + fetchAndDisplayStats(); + updateSegmentCategories(); + return false; + }); + + if (!(sbEnabled.getParent() instanceof PreferenceScreen mPreferenceScreen)) { + return; + } + + final SwitchPreference votingEnabled = findSwitchPreference(Settings.SB_VOTING_BUTTON); + final SwitchPreference compactSkipButton = findSwitchPreference(Settings.SB_COMPACT_SKIP_BUTTON); + final SwitchPreference autoHideSkipSegmentButton = findSwitchPreference(Settings.SB_AUTO_HIDE_SKIP_BUTTON); + final SwitchPreference showSkipToast = findSwitchPreference(Settings.SB_TOAST_ON_SKIP); + showSkipToast.setOnPreferenceClickListener(preference -> { + Utils.showToastShort(str("revanced_sb_skipped_sponsor")); + return false; + }); + + final SwitchPreference showTimeWithoutSegments = findSwitchPreference(Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS); + + final SwitchPreference addNewSegment = findSwitchPreference(Settings.SB_CREATE_NEW_SEGMENT); + addNewSegment.setOnPreferenceChangeListener((preference, newValue) -> { + if ((Boolean) newValue && !Settings.SB_SEEN_GUIDELINES.get()) { + Context context = preference.getContext(); + new AlertDialog.Builder(context) + .setTitle(str("revanced_sb_guidelines_popup_title")) + .setMessage(str("revanced_sb_guidelines_popup_content")) + .setNegativeButton(str("revanced_sb_guidelines_popup_already_read"), null) + .setPositiveButton(str("revanced_sb_guidelines_popup_open"), (dialogInterface, i) -> openGuidelines(context)) + .setOnDismissListener(dialog -> Settings.SB_SEEN_GUIDELINES.save(true)) + .setCancelable(false) + .show(); + } + updateUI(); + return true; + }); + + final ResettableEditTextPreference newSegmentStep = findResettableEditTextPreference(Settings.SB_CREATE_NEW_SEGMENT_STEP); + newSegmentStep.setOnPreferenceChangeListener((preference, newValue) -> { + try { + final int newAdjustmentValue = Integer.parseInt(newValue.toString()); + if (newAdjustmentValue != 0) { + Settings.SB_CREATE_NEW_SEGMENT_STEP.save(newAdjustmentValue); + return true; + } + } catch (NumberFormatException ex) { + Logger.printInfo(() -> "Invalid new segment step", ex); + } + + Utils.showToastLong(str("revanced_sb_general_adjusting_invalid")); + updateUI(); + return false; + }); + final Preference guidelinePreferences = Objects.requireNonNull(mPreferenceManager.findPreference("revanced_sb_guidelines_preference")); + guidelinePreferences.setDependency(Settings.SB_ENABLED.key); + guidelinePreferences.setOnPreferenceClickListener(preference -> { + openGuidelines(preference.getContext()); + return true; + }); + + final SwitchPreference toastOnConnectionError = findSwitchPreference(Settings.SB_TOAST_ON_CONNECTION_ERROR); + final SwitchPreference trackSkips = findSwitchPreference(Settings.SB_TRACK_SKIP_COUNT); + final ResettableEditTextPreference minSegmentDuration = findResettableEditTextPreference(Settings.SB_SEGMENT_MIN_DURATION); + minSegmentDuration.setOnPreferenceChangeListener((preference, newValue) -> { + try { + Float minTimeDuration = Float.valueOf(newValue.toString()); + Settings.SB_SEGMENT_MIN_DURATION.save(minTimeDuration); + return true; + } catch (NumberFormatException ex) { + Logger.printInfo(() -> "Invalid minimum segment duration", ex); + } + + Utils.showToastLong(str("revanced_sb_general_min_duration_invalid")); + updateUI(); + return false; + }); + final ResettableEditTextPreference privateUserId = findResettableEditTextPreference(Settings.SB_PRIVATE_USER_ID); + privateUserId.setOnPreferenceChangeListener((preference, newValue) -> { + String newUUID = newValue.toString(); + if (!SponsorBlockSettings.isValidSBUserId(newUUID)) { + Utils.showToastLong(str("revanced_sb_general_uuid_invalid")); + return false; + } + + Settings.SB_PRIVATE_USER_ID.save(newUUID); + try { + updateUI(); + } catch (Exception e) { + throw new RuntimeException(e); + } + fetchAndDisplayStats(); + return true; + }); + final Preference apiUrl = mPreferenceManager.findPreference(Settings.SB_API_URL.key); + if (apiUrl != null) { + apiUrl.setOnPreferenceClickListener(preference -> { + Context context = preference.getContext(); + + TableLayout table = new TableLayout(context); + table.setOrientation(LinearLayout.HORIZONTAL); + table.setPadding(15, 0, 15, 0); + + TableRow row = new TableRow(context); + + EditText editText = new EditText(context); + editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); + editText.setText(Settings.SB_API_URL.get()); + editText.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)); + row.addView(editText); + table.addView(row); + + DialogInterface.OnClickListener urlChangeListener = (dialog, buttonPressed) -> { + if (buttonPressed == DialogInterface.BUTTON_NEUTRAL) { + Settings.SB_API_URL.resetToDefault(); + Utils.showToastLong(str("revanced_sb_api_url_reset")); + } else if (buttonPressed == DialogInterface.BUTTON_POSITIVE) { + String serverAddress = editText.getText().toString(); + if (!SponsorBlockSettings.isValidSBServerAddress(serverAddress)) { + Utils.showToastLong(str("revanced_sb_api_url_invalid")); + } else if (!serverAddress.equals(Settings.SB_API_URL.get())) { + Settings.SB_API_URL.save(serverAddress); + Utils.showToastLong(str("revanced_sb_api_url_changed")); + } + } + }; + Utils.getEditTextDialogBuilder(context) + .setView(table) + .setTitle(apiUrl.getTitle()) + .setNegativeButton(android.R.string.cancel, null) + .setNeutralButton(str("revanced_sb_reset"), urlChangeListener) + .setPositiveButton(android.R.string.ok, urlChangeListener) + .show(); + return true; + }); + } + + statsCategory = new PreferenceCategory(mActivity); + statsCategory.setLayoutResource(preferencesCategoryLayout); + statsCategory.setTitle(str("revanced_sb_stats")); + mPreferenceScreen.addPreference(statsCategory); + fetchAndDisplayStats(); + + final PreferenceCategory aboutCategory = new PreferenceCategory(mActivity); + aboutCategory.setLayoutResource(preferencesCategoryLayout); + aboutCategory.setTitle(str("revanced_sb_about")); + mPreferenceScreen.addPreference(aboutCategory); + + Preference aboutPreference = new Preference(mActivity); + aboutCategory.addPreference(aboutPreference); + aboutPreference.setTitle(str("revanced_sb_about_api")); + aboutPreference.setSummary(str("revanced_sb_about_api_sum")); + aboutPreference.setOnPreferenceClickListener(preference -> { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://sponsor.ajay.app")); + preference.getContext().startActivity(i); + return false; + }); + + updateUI(); + } + + public static void updateSegmentCategories() { + try { + for (SegmentCategory category : SegmentCategory.categoriesWithoutUnsubmitted()) { + final String key = category.keyValue; + if (mPreferenceManager.findPreference(key) instanceof SegmentCategoryListPreference segmentCategoryListPreference) { + segmentCategoryListPreference.setTitle(category.getTitleWithColorDot()); + segmentCategoryListPreference.setEnabled(Settings.SB_ENABLED.get()); + } + } + } catch (Exception ex) { + Logger.printException(() -> "updateSegmentCategories failure", ex); + } + } + + private static void openGuidelines(Context context) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse("https://wiki.sponsor.ajay.app/w/Guidelines")); + context.startActivity(intent); + } + + public static void fetchAndDisplayStats() { + try { + if (statsCategory == null) { + return; + } + statsCategory.removeAll(); + if (!SponsorBlockSettings.userHasSBPrivateId()) { + // User has never voted or created any segments. No stats to show. + addLocalUserStats(); + return; + } + + Context context = statsCategory.getContext(); + + Preference loadingPlaceholderPreference = new Preference(context); + loadingPlaceholderPreference.setEnabled(false); + statsCategory.addPreference(loadingPlaceholderPreference); + if (Settings.SB_ENABLED.get()) { + loadingPlaceholderPreference.setTitle(str("revanced_sb_stats_loading")); + Utils.runOnBackgroundThread(() -> { + UserStats stats = SBRequester.retrieveUserStats(); + Utils.runOnMainThread(() -> { // get back on main thread to modify UI elements + addUserStats(loadingPlaceholderPreference, stats); + addLocalUserStats(); + }); + }); + } else { + loadingPlaceholderPreference.setTitle(str("revanced_sb_stats_sb_disabled")); + } + } catch (Exception ex) { + Logger.printException(() -> "fetchAndDisplayStats failure", ex); + } + } + + private static void addUserStats(@NonNull Preference loadingPlaceholder, @Nullable UserStats stats) { + Utils.verifyOnMainThread(); + try { + if (stats == null) { + loadingPlaceholder.setTitle(str("revanced_sb_stats_connection_failure")); + return; + } + 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. + ResettableEditTextPreference preference = new ResettableEditTextPreference(context); + statsCategory.addPreference(preference); + String userName = stats.userName; + preference.setTitle(fromHtml(str("revanced_sb_stats_username", userName))); + preference.setSummary(str("revanced_sb_stats_username_change")); + preference.setText(userName); + preference.setOnPreferenceChangeListener((preference1, value) -> { + Utils.runOnBackgroundThread(() -> { + String newUserName = (String) value; + String errorMessage = SBRequester.setUsername(newUserName); + Utils.runOnMainThread(() -> { + if (errorMessage == null) { + preference.setTitle(fromHtml(str("revanced_sb_stats_username", newUserName))); + preference.setText(newUserName); + Utils.showToastLong(str("revanced_sb_stats_username_changed")); + } else { + preference.setText(userName); // revert to previous + Utils.showToastLong(errorMessage); + } + }); + }); + return true; + }); + } + + { + // number of segment submissions (does not include ignored segments) + Preference preference = new Preference(context); + statsCategory.addPreference(preference); + String formatted = SponsorBlockUtils.getNumberOfSkipsString(stats.segmentCount); + preference.setTitle(fromHtml(str("revanced_sb_stats_submissions", formatted))); + preference.setSummary(str("revanced_sb_stats_submissions_sum")); + if (stats.totalSegmentCountIncludingIgnored == 0) { + preference.setSelectable(false); + } else { + preference.setOnPreferenceClickListener(preference1 -> { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://sb.ltn.fi/userid/" + stats.publicUserId)); + preference1.getContext().startActivity(i); + return true; + }); + } + } + + { + // "user reputation". Usually not useful, since it appears most users have zero reputation. + // But if there is a reputation, then show it here + Preference preference = new Preference(context); + preference.setTitle(fromHtml(str("revanced_sb_stats_reputation", stats.reputation))); + preference.setSelectable(false); + if (stats.reputation != 0) { + statsCategory.addPreference(preference); + } + } + + { + // time saved for other users + Preference preference = new Preference(context); + statsCategory.addPreference(preference); + + String stats_saved; + String stats_saved_sum; + if (stats.totalSegmentCountIncludingIgnored == 0) { + stats_saved = str("revanced_sb_stats_saved_zero"); + stats_saved_sum = str("revanced_sb_stats_saved_sum_zero"); + } else { + stats_saved = str("revanced_sb_stats_saved", + SponsorBlockUtils.getNumberOfSkipsString(stats.viewCount)); + stats_saved_sum = str("revanced_sb_stats_saved_sum", SponsorBlockUtils.getTimeSavedString((long) (60 * stats.minutesSaved))); + } + preference.setTitle(fromHtml(stats_saved)); + preference.setSummary(fromHtml(stats_saved_sum)); + preference.setOnPreferenceClickListener(preference1 -> { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://sponsor.ajay.app/stats/")); + preference1.getContext().startActivity(i); + return false; + }); + } + } catch (Exception ex) { + Logger.printException(() -> "addUserStats failure", ex); + } + } + + private static void addLocalUserStats() { + // time the user saved by using SB + Preference preference = new Preference(statsCategory.getContext()); + statsCategory.addPreference(preference); + + Runnable updateStatsSelfSaved = () -> { + String formatted = SponsorBlockUtils.getNumberOfSkipsString(Settings.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.get()); + preference.setTitle(fromHtml(str("revanced_sb_stats_self_saved", formatted))); + String formattedSaved = SponsorBlockUtils.getTimeSavedString(Settings.SB_LOCAL_TIME_SAVED_MILLISECONDS.get() / 1000); + preference.setSummary(fromHtml(str("revanced_sb_stats_self_saved_sum", formattedSaved))); + }; + updateStatsSelfSaved.run(); + preference.setOnPreferenceClickListener(preference1 -> { + new AlertDialog.Builder(preference1.getContext()) + .setTitle(str("revanced_sb_stats_self_saved_reset_title")) + .setPositiveButton(android.R.string.yes, (dialog, whichButton) -> { + Settings.SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS.resetToDefault(); + Settings.SB_LOCAL_TIME_SAVED_MILLISECONDS.resetToDefault(); + updateStatsSelfSaved.run(); + }) + .setNegativeButton(android.R.string.no, null).show(); + return true; + }); + } +} diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ViewCountAboutPreference.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ViewCountAboutPreference.java deleted file mode 100644 index 1b463a3531..0000000000 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ViewCountAboutPreference.java +++ /dev/null @@ -1,76 +0,0 @@ -package app.revanced.integrations.youtube.settings.preference; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.Preference; -import android.preference.PreferenceManager; -import android.util.AttributeSet; - -import app.revanced.integrations.shared.settings.BooleanSetting; -import app.revanced.integrations.shared.settings.Setting; -import app.revanced.integrations.shared.utils.Utils; -import app.revanced.integrations.youtube.settings.Settings; - -@SuppressWarnings({"deprecation", "unused"}) -public class ViewCountAboutPreference extends Preference { - - private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> { - // Because this listener may run before the ReVanced settings fragment updates Settings, - // this could show the prior config and not the current. - // - // Push this call to the end of the main run queue, - // so all other listeners are done and Settings is up to date. - Utils.runOnMainThread(this::updateUI); - }; - - public ViewCountAboutPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public ViewCountAboutPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public ViewCountAboutPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ViewCountAboutPreference(Context context) { - super(context); - } - - private void addChangeListener() { - Setting.preferences.preferences.registerOnSharedPreferenceChangeListener(listener); - } - - private void removeChangeListener() { - Setting.preferences.preferences.unregisterOnSharedPreferenceChangeListener(listener); - } - - @Override - protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { - super.onAttachedToHierarchy(preferenceManager); - updateUI(); - addChangeListener(); - } - - @Override - protected void onPrepareForRemoval() { - super.onPrepareForRemoval(); - removeChangeListener(); - } - - private void updateUI() { - boolean viewCountFilterEnabled = false; - - final BooleanSetting[] viewCountFilterSettings = { - Settings.HIDE_VIDEO_BY_VIEW_COUNTS_HOME, - Settings.HIDE_VIDEO_BY_VIEW_COUNTS_SEARCH, - Settings.HIDE_VIDEO_BY_VIEW_COUNTS_SUBSCRIPTIONS - }; - for (BooleanSetting s : viewCountFilterSettings) { - viewCountFilterEnabled |= s.get(); - } - setEnabled(viewCountFilterEnabled); - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/SponsorBlockSettings.java b/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/SponsorBlockSettings.java index f7d8bd8192..4a8ab3c6c5 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/SponsorBlockSettings.java +++ b/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/SponsorBlockSettings.java @@ -18,6 +18,7 @@ import app.revanced.integrations.shared.utils.Logger; import app.revanced.integrations.shared.utils.Utils; import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.youtube.settings.preference.SponsorBlockSettingsPreference; import app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour; import app.revanced.integrations.youtube.sponsorblock.objects.SegmentCategory; @@ -240,5 +241,6 @@ public static void initialize() { */ public static void updateFromImportedSettings() { SegmentCategory.loadAllCategoriesFromSettings(); + SponsorBlockSettingsPreference.updateSegmentCategories(); } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/CategoryBehaviour.java b/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/CategoryBehaviour.java index 0701904e37..2064eb8fd0 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/CategoryBehaviour.java +++ b/app/src/main/java/app/revanced/integrations/youtube/sponsorblock/objects/CategoryBehaviour.java @@ -94,28 +94,28 @@ private static void createNameAndKeyArrays() { } } - static String[] getBehaviorKeyValues() { + public static String[] getBehaviorKeyValues() { if (behaviorKeyValues == null) { createNameAndKeyArrays(); } return behaviorKeyValues; } - static String[] getBehaviorKeyValuesWithoutSkipOnce() { + public static String[] getBehaviorKeyValuesWithoutSkipOnce() { if (behaviorKeyValuesWithoutSkipOnce == null) { createNameAndKeyArrays(); } return behaviorKeyValuesWithoutSkipOnce; } - static String[] getBehaviorDescriptions() { + public static String[] getBehaviorDescriptions() { if (behaviorDescriptions == null) { createNameAndKeyArrays(); } return behaviorDescriptions; } - static String[] getBehaviorDescriptionsWithoutSkipOnce() { + public static String[] getBehaviorDescriptionsWithoutSkipOnce() { if (behaviorDescriptionsWithoutSkipOnce == null) { createNameAndKeyArrays(); }