diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java index 6692dc85..95450b46 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java @@ -1,12 +1,103 @@ package app.revanced.integrations.patches.playback.speed; +import android.preference.ListPreference; + +import androidx.annotation.NonNull; + +import java.util.Arrays; + +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; + public class CustomVideoSpeedPatch { /** - * Default playback speeds offered by YouTube. - * Values are also used by {@link RememberPlaybackSpeedPatch}. - * - * If custom video speed is applied, - * then this array is overwritten by the patch with custom speeds + * Maximum playback speed, exclusive value. Custom speeds must be less than this value. */ - public static final float[] videoSpeeds = {0.25f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f}; + public static final float MAXIMUM_PLAYBACK_SPEED = 10; + + /** + * Custom playback speeds. + */ + public static float[] customVideoSpeeds; + + /** + * Minimum value of {@link #customVideoSpeeds} + */ + public static float minVideoSpeed; + + /** + * Maxium value of {@link #customVideoSpeeds} + */ + public static float maxVideoSpeed; + + /** + * PreferenceList entries and values, of all available playback speeds. + */ + private static String[] preferenceListEntries, preferenceListEntryValues; + + static { + loadSpeeds(); + } + + private static void resetCustomSpeeds(@NonNull String toastMessage) { + ReVancedUtils.showToastLong(toastMessage); + SettingsEnum.PLAYBACK_SPEED_AVAILABLE.saveValue(SettingsEnum.PLAYBACK_SPEED_AVAILABLE.defaultValue); + } + + private static void loadSpeeds() { + try { + String[] speedStrings = SettingsEnum.PLAYBACK_SPEED_AVAILABLE.getString().split("\\s+"); + Arrays.sort(speedStrings); + if (speedStrings.length == 0) { + throw new IllegalArgumentException(); + } + customVideoSpeeds = new float[speedStrings.length]; + for (int i = 0, length = speedStrings.length; i < length; i++) { + final float speed = Float.parseFloat(speedStrings[i]); + if (speed <= 0 || arrayContains(customVideoSpeeds, speed)) { + throw new IllegalArgumentException(); + } + if (speed >= MAXIMUM_PLAYBACK_SPEED) { + resetCustomSpeeds("Custom speeds must be less than " + MAXIMUM_PLAYBACK_SPEED + + ". Using default values."); + loadSpeeds(); + return; + } + minVideoSpeed = Math.min(minVideoSpeed, speed); + maxVideoSpeed = Math.max(maxVideoSpeed, speed); + customVideoSpeeds[i] = speed; + } + } catch (Exception ex) { + LogHelper.printInfo(() -> "parse error", ex); + resetCustomSpeeds("Invalid custom video speeds. Using default values."); + loadSpeeds(); + } + } + + private static boolean arrayContains(float[] array, float value) { + for (float arrayValue : array) { + if (arrayValue == value) return true; + } + return false; + } + + /** + * Initialize a settings preference list with the available playback speeds. + */ + public static void initializeListPreference(ListPreference preference) { + if (preferenceListEntries == null) { + preferenceListEntries = new String[customVideoSpeeds.length]; + preferenceListEntryValues = new String[customVideoSpeeds.length]; + int i = 0; + for (float speed : customVideoSpeeds) { + String speedString = String.valueOf(speed); + preferenceListEntries[i] = speedString + "x"; + preferenceListEntryValues[i] = speedString; + i++; + } + } + preference.setEntries(preferenceListEntries); + preference.setEntryValues(preferenceListEntryValues); + } } diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java index 5b96940d..4cb9a3a2 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java @@ -1,7 +1,5 @@ package app.revanced.integrations.patches.playback.speed; -import android.preference.ListPreference; - import app.revanced.integrations.patches.VideoInformation; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; @@ -9,12 +7,6 @@ import app.revanced.integrations.utils.ReVancedUtils; public final class RememberPlaybackSpeedPatch { - /** - * PreferenceList entries and values, of all available playback speeds. - */ - private static String[] preferenceListEntries, preferenceListEntryValues; - - /** * Injection point. */ @@ -44,26 +36,4 @@ public final class RememberPlaybackSpeedPatch { return VideoInformation.getPlaybackSpeed(); } - /** - * Initialize a settings preference list. - * - * Normally this is done during patching by creating a static xml preference list, - * but the available playback speeds differ depending if {@link CustomVideoSpeedPatch} is applied or not. - */ - public static void initializeListPreference(ListPreference preference) { - if (preferenceListEntries == null) { - float[] videoSpeeds = CustomVideoSpeedPatch.videoSpeeds; - preferenceListEntries = new String[videoSpeeds.length]; - preferenceListEntryValues = new String[videoSpeeds.length]; - int i = 0; - for (float speed : videoSpeeds) { - String speedString = String.valueOf(speed); - preferenceListEntries[i] = speedString + "x"; - preferenceListEntryValues[i] = speedString; - i++; - } - } - preference.setEntries(preferenceListEntries); - preference.setEntryValues(preferenceListEntryValues); - } } diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index f2e79ffb..3a062df4 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -28,6 +28,8 @@ public enum SettingsEnum { 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, + "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 diff --git a/app/src/main/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java b/app/src/main/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java index 16b427d2..d57ccc6f 100644 --- a/app/src/main/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java +++ b/app/src/main/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java @@ -24,7 +24,7 @@ import androidx.annotation.Nullable; import com.google.android.apps.youtube.app.application.Shell_HomeActivity; -import app.revanced.integrations.patches.playback.speed.RememberPlaybackSpeedPatch; +import app.revanced.integrations.patches.playback.speed.CustomVideoSpeedPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.settings.SharedPrefCategory; import app.revanced.integrations.utils.LogHelper; @@ -88,7 +88,7 @@ public class ReVancedSettingsFragment extends PreferenceFragment { // if the preference was included, then initialize it based on the available playback speed Preference defaultSpeedPreference = findPreference(SettingsEnum.PLAYBACK_SPEED_DEFAULT.path); if (defaultSpeedPreference instanceof ListPreference) { - RememberPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); + CustomVideoSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); } // set the summary text for any ListPreferences @@ -120,6 +120,9 @@ 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()); if (entryIndex >= 0) { diff --git a/app/src/main/java/app/revanced/integrations/settingsmenu/ResettableEditTextPreference.java b/app/src/main/java/app/revanced/integrations/settingsmenu/ResettableEditTextPreference.java index fc4c7f7e..f4a47e8a 100644 --- a/app/src/main/java/app/revanced/integrations/settingsmenu/ResettableEditTextPreference.java +++ b/app/src/main/java/app/revanced/integrations/settingsmenu/ResettableEditTextPreference.java @@ -16,18 +16,16 @@ import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; public class ResettableEditTextPreference extends EditTextPreference { + public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } - public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } - public ResettableEditTextPreference(Context context, AttributeSet attrs) { super(context, attrs); } - public ResettableEditTextPreference(Context context) { super(context); } @@ -53,7 +51,6 @@ public class ResettableEditTextPreference extends EditTextPreference { button.setOnClickListener(v -> { try { SettingsEnum setting = Objects.requireNonNull(SettingsEnum.settingFromPath(getKey())); - setting.saveValue(setting.defaultValue); String defaultStringValue = setting.defaultValue.toString(); EditText editText = getEditText(); editText.setText(defaultStringValue);