Skip to content

Commit d4f840b

Browse files
Move sorted preference list behavior into custom classes.
1 parent 53141f8 commit d4f840b

File tree

8 files changed

+172
-114
lines changed

8 files changed

+172
-114
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package app.revanced.extension.shared.settings.preference;
2+
3+
import android.content.Context;
4+
import android.preference.ListPreference;
5+
import android.util.AttributeSet;
6+
import android.util.Pair;
7+
8+
import java.util.ArrayList;
9+
import java.util.Collections;
10+
import java.util.List;
11+
12+
/**
13+
* PreferenceList that sorts itself.
14+
* By default the first entry is preserved in its original position,
15+
* and all other entries are sorted alphabetically.
16+
*
17+
* Ideally the 'keep first entries to preserve' is an xml parameter,
18+
* but currently that's not so simple since Extensions code cannot use
19+
* generated code from the Patches repo (which is required for custom xml parameters).
20+
*
21+
* If any class wants to use a different getFirstEntriesToPreserve value,
22+
* it needs to subclass this preference and override {@link #getFirstEntriesToPreserve}.
23+
*/
24+
@SuppressWarnings({"unused", "deprecation"})
25+
public class SortedListPreference extends ListPreference {
26+
27+
/**
28+
* Sorts the list entries, but preserves the first N entries in their current position.
29+
*/
30+
protected void sortEntryAndValues() {
31+
final int firstEntriesToPreserve = getFirstEntriesToPreserve();
32+
33+
CharSequence[] entries = getEntries();
34+
CharSequence[] entryValues = getEntryValues();
35+
final int entrySize = entries.length;
36+
37+
if (entrySize != entryValues.length) {
38+
// Xml array declaration has a missing/extra entry.
39+
throw new IllegalStateException();
40+
}
41+
42+
List<Pair<CharSequence, CharSequence>> firstPairs = new ArrayList<>(firstEntriesToPreserve);
43+
List<Pair<CharSequence, CharSequence>> pairsToSort = new ArrayList<>(entrySize);
44+
45+
for (int i = 0; i < entrySize; i++) {
46+
Pair<CharSequence, CharSequence> pair = new Pair<>(entries[i], entryValues[i]);
47+
if (i < firstEntriesToPreserve) {
48+
firstPairs.add(pair);
49+
} else {
50+
pairsToSort.add(pair);
51+
}
52+
}
53+
54+
Collections.sort(pairsToSort, (pair1, pair2)
55+
-> pair1.first.toString().compareToIgnoreCase(pair2.first.toString()));
56+
57+
CharSequence[] sortedEntries = new CharSequence[entrySize];
58+
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
59+
60+
int i = 0;
61+
for (Pair<CharSequence, CharSequence> pair : firstPairs) {
62+
sortedEntries[i] = pair.first;
63+
sortedEntryValues[i] = pair.second;
64+
i++;
65+
}
66+
67+
for (Pair<CharSequence, CharSequence> pair : pairsToSort) {
68+
sortedEntries[i] = pair.first;
69+
sortedEntryValues[i] = pair.second;
70+
i++;
71+
}
72+
73+
super.setEntries(sortedEntries);
74+
super.setEntryValues(sortedEntryValues);
75+
}
76+
77+
protected int getFirstEntriesToPreserve() {
78+
return 1;
79+
}
80+
81+
public SortedListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
82+
super(context, attrs, defStyleAttr, defStyleRes);
83+
84+
sortEntryAndValues();
85+
}
86+
87+
public SortedListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
88+
super(context, attrs, defStyleAttr);
89+
90+
sortEntryAndValues();
91+
}
92+
93+
public SortedListPreference(Context context, AttributeSet attrs) {
94+
super(context, attrs);
95+
96+
sortEntryAndValues();
97+
}
98+
99+
public SortedListPreference(Context context) {
100+
super(context);
101+
102+
sortEntryAndValues();
103+
}
104+
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java

-38
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
package app.revanced.extension.youtube.patches.playback.speed;
22

3-
import static app.revanced.extension.shared.StringRef.sf;
43
import static app.revanced.extension.shared.StringRef.str;
54

6-
import android.preference.ListPreference;
75
import android.support.v7.widget.RecyclerView;
86
import android.view.View;
97
import android.view.ViewGroup;
108
import android.view.ViewParent;
119

12-
import androidx.annotation.NonNull;
13-
1410
import java.util.Arrays;
1511

1612
import app.revanced.extension.shared.Logger;
@@ -21,8 +17,6 @@
2117
@SuppressWarnings("unused")
2218
public class CustomPlaybackSpeedPatch {
2319

24-
private static final float PLAYBACK_SPEED_AUTO = Settings.PLAYBACK_SPEED_DEFAULT.defaultValue;
25-
2620
/**
2721
* Maximum playback speed, exclusive value. Custom speeds must be less than this value.
2822
* <p>
@@ -47,11 +41,6 @@ public class CustomPlaybackSpeedPatch {
4741
*/
4842
private static long lastTimeOldPlaybackMenuInvoked;
4943

50-
/**
51-
* PreferenceList entries and values, of all available playback speeds.
52-
*/
53-
private static String[] preferenceListEntries, preferenceListEntryValues;
54-
5544
static {
5645
final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get();
5746

@@ -117,33 +106,6 @@ private static boolean arrayContains(float[] array, float value) {
117106
return false;
118107
}
119108

120-
/**
121-
* Initialize a settings preference list with the available playback speeds.
122-
*/
123-
@SuppressWarnings("deprecation")
124-
public static void initializeListPreference(ListPreference preference) {
125-
if (preferenceListEntries == null) {
126-
final int numberOfEntries = customPlaybackSpeeds.length + 1;
127-
preferenceListEntries = new String[numberOfEntries];
128-
preferenceListEntryValues = new String[numberOfEntries];
129-
130-
// Auto speed (same behavior as unpatched).
131-
preferenceListEntries[0] = sf("revanced_custom_playback_speeds_auto").toString();
132-
preferenceListEntryValues[0] = String.valueOf(PLAYBACK_SPEED_AUTO);
133-
134-
int i = 1;
135-
for (float speed : customPlaybackSpeeds) {
136-
String speedString = String.valueOf(speed);
137-
preferenceListEntries[i] = speedString + "x";
138-
preferenceListEntryValues[i] = speedString;
139-
i++;
140-
}
141-
}
142-
143-
preference.setEntries(preferenceListEntries);
144-
preference.setEntryValues(preferenceListEntryValues);
145-
}
146-
147109
/**
148110
* Injection point.
149111
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package app.revanced.extension.youtube.settings.preference;
2+
3+
import static app.revanced.extension.shared.StringRef.sf;
4+
5+
import android.content.Context;
6+
import android.preference.ListPreference;
7+
import android.util.AttributeSet;
8+
9+
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
10+
import app.revanced.extension.youtube.settings.Settings;
11+
12+
/**
13+
* Custom video speeds used by {@link CustomPlaybackSpeedPatch}.
14+
*/
15+
@SuppressWarnings({"unused", "deprecation"})
16+
public final class CustomVideoSpeedListPreference extends ListPreference {
17+
18+
/**
19+
* Initialize a settings preference list with the available playback speeds.
20+
*/
21+
private void initializeEntryValues() {
22+
float[] customPlaybackSpeeds = CustomPlaybackSpeedPatch.customPlaybackSpeeds;
23+
final int numberOfEntries = customPlaybackSpeeds.length + 1;
24+
String[] preferenceListEntries = new String[numberOfEntries];
25+
String[] preferenceListEntryValues = new String[numberOfEntries];
26+
27+
// Auto speed (same behavior as unpatched).
28+
preferenceListEntries[0] = sf("revanced_custom_playback_speeds_auto").toString();
29+
preferenceListEntryValues[0] = String.valueOf(Settings.PLAYBACK_SPEED_DEFAULT.defaultValue);
30+
31+
int i = 1;
32+
for (float speed : customPlaybackSpeeds) {
33+
String speedString = String.valueOf(speed);
34+
preferenceListEntries[i] = speedString + "x";
35+
preferenceListEntryValues[i] = speedString;
36+
i++;
37+
}
38+
39+
setEntries(preferenceListEntries);
40+
setEntryValues(preferenceListEntryValues);
41+
}
42+
43+
{
44+
initializeEntryValues();
45+
}
46+
47+
public CustomVideoSpeedListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
48+
super(context, attrs, defStyleAttr, defStyleRes);
49+
}
50+
51+
public CustomVideoSpeedListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
52+
super(context, attrs, defStyleAttr);
53+
}
54+
55+
public CustomVideoSpeedListPreference(Context context, AttributeSet attrs) {
56+
super(context, attrs);
57+
}
58+
59+
public CustomVideoSpeedListPreference(Context context) {
60+
super(context);
61+
}
62+
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java

-74
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import android.text.SpannableStringBuilder;
1818
import android.text.TextUtils;
1919
import android.text.style.BackgroundColorSpan;
20-
import android.util.Pair;
2120
import android.util.TypedValue;
2221
import android.view.ViewGroup;
2322
import android.view.WindowInsets;
@@ -40,13 +39,10 @@
4039
import app.revanced.extension.shared.Logger;
4140
import app.revanced.extension.shared.Utils;
4241
import app.revanced.extension.shared.settings.BaseSettings;
43-
import app.revanced.extension.shared.settings.EnumSetting;
4442
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
4543
import app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory;
4644
import app.revanced.extension.youtube.ThemeHelper;
47-
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
4845
import app.revanced.extension.youtube.settings.LicenseActivityHook;
49-
import app.revanced.extension.youtube.settings.Settings;
5046
import app.revanced.extension.youtube.sponsorblock.ui.SponsorBlockPreferenceGroup;
5147

5248
/**
@@ -83,56 +79,6 @@ public static Drawable getBackButtonDrawable() {
8379
return Utils.getContext().getResources().getDrawable(backButtonResource);
8480
}
8581

86-
/**
87-
* Sorts a preference list by menu entries,
88-
* but preserves the first N entries in their current position.
89-
*/
90-
@SuppressWarnings("SameParameterValue")
91-
private static void sortListPreferenceByValues(ListPreference listPreference, int firstEntriesToPreserve) {
92-
CharSequence[] entries = listPreference.getEntries();
93-
CharSequence[] entryValues = listPreference.getEntryValues();
94-
final int entrySize = entries.length;
95-
96-
if (entrySize != entryValues.length) {
97-
// Xml array declaration has a missing/extra entry.
98-
throw new IllegalStateException();
99-
}
100-
101-
List<Pair<CharSequence, CharSequence>> firstPairs = new ArrayList<>(firstEntriesToPreserve);
102-
List<Pair<CharSequence, CharSequence>> pairsToSort = new ArrayList<>(entrySize);
103-
104-
for (int i = 0; i < entrySize; i++) {
105-
Pair<CharSequence, CharSequence> pair = new Pair<>(entries[i], entryValues[i]);
106-
if (i < firstEntriesToPreserve) {
107-
firstPairs.add(pair);
108-
} else {
109-
pairsToSort.add(pair);
110-
}
111-
}
112-
113-
pairsToSort.sort((pair1, pair2)
114-
-> pair1.first.toString().compareToIgnoreCase(pair2.first.toString()));
115-
116-
CharSequence[] sortedEntries = new CharSequence[entrySize];
117-
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
118-
119-
int i = 0;
120-
for (Pair<CharSequence, CharSequence> pair : firstPairs) {
121-
sortedEntries[i] = pair.first;
122-
sortedEntryValues[i] = pair.second;
123-
i++;
124-
}
125-
126-
for (Pair<CharSequence, CharSequence> pair : pairsToSort) {
127-
sortedEntries[i] = pair.first;
128-
sortedEntryValues[i] = pair.second;
129-
i++;
130-
}
131-
132-
listPreference.setEntries(sortedEntries);
133-
listPreference.setEntryValues(sortedEntryValues);
134-
}
135-
13682
/**
13783
* Initializes the preference fragment, copying the original screen to allow full restoration.
13884
*/
@@ -141,16 +87,6 @@ protected void initialize() {
14187
super.initialize();
14288

14389
try {
144-
sortPreferenceListMenu(Settings.CHANGE_START_PAGE);
145-
sortPreferenceListMenu(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE);
146-
sortPreferenceListMenu(BaseSettings.REVANCED_LANGUAGE);
147-
148-
// If the preference was included, then initialize it based on the available playback speed.
149-
Preference preference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key);
150-
if (preference instanceof ListPreference playbackPreference) {
151-
CustomPlaybackSpeedPatch.initializeListPreference(playbackPreference);
152-
}
153-
15490
preferenceScreen = getPreferenceScreen();
15591
Utils.sortPreferenceGroups(preferenceScreen);
15692

@@ -273,16 +209,6 @@ public void filterPreferences(String query) {
273209
}
274210
}
275211

276-
/**
277-
* Sorts a specific list preference by its entries, but retain the first entry as the first item.
278-
*/
279-
private void sortPreferenceListMenu(EnumSetting<?> setting) {
280-
Preference preference = findPreference(setting.key);
281-
if (preference instanceof ListPreference languagePreference) {
282-
sortListPreferenceByValues(languagePreference, 1);
283-
}
284-
}
285-
286212
/**
287213
* Sets toolbar for all nested preference screens.
288214
*/

patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/ChangeStartPagePatch.kt

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ val changeStartPagePatch = bytecodePatch(
5454
ListPreference(
5555
key = "revanced_change_start_page",
5656
summaryKey = null,
57+
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
5758
),
5859
SwitchPreference("revanced_change_start_page_always")
5960
)

patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ val settingsPatch = bytecodePatch(
207207
),
208208
ListPreference(
209209
key = "revanced_language",
210-
summaryKey = null
210+
summaryKey = null,
211+
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
211212
)
212213
)
213214

patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
6262
summaryKey = null,
6363
// Language strings are declared in Setting patch.
6464
entriesKey = "revanced_language_entries",
65-
entryValuesKey = "revanced_language_entry_values"
65+
entryValuesKey = "revanced_language_entry_values",
66+
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
6667
),
6768
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
6869
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),

patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ internal val rememberPlaybackSpeedPatch = bytecodePatch {
3838
// Entries and values are set by the extension code based on the actual speeds available.
3939
entriesKey = null,
4040
entryValuesKey = null,
41+
tag = "app.revanced.extension.youtube.settings.preference.CustomVideoSpeedListPreference"
4142
),
4243
SwitchPreference("revanced_remember_playback_speed_last_selected")
4344
)

0 commit comments

Comments
 (0)