Skip to content
This repository was archived by the owner on Oct 26, 2024. It is now read-only.

Commit dabbc3d

Browse files
fix(YouTube - Playback speed): Restore old playback speed menu
1 parent 966268f commit dabbc3d

File tree

3 files changed

+87
-44
lines changed

3 files changed

+87
-44
lines changed

app/src/main/java/app/revanced/integrations/shared/Utils.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,10 @@ public static ViewParent getParentView(@NonNull View view, int nthParent) {
317317
return parent;
318318
}
319319

320-
final int currentDepthLog = currentDepth;
320+
final int finalDepthLog = currentDepth;
321+
final ViewParent finalParent = parent;
321322
Logger.printDebug(() -> "Could not find parent view of depth: " + nthParent
322-
+ " and instead found at: " + currentDepthLog + " view: " + view);
323+
+ " and instead found at: " + finalDepthLog + " view: " + finalParent);
323324
return null;
324325
}
325326

app/src/main/java/app/revanced/integrations/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,41 @@
88
* Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}.
99
*/
1010
public final class PlaybackSpeedMenuFilterPatch extends Filter {
11-
// Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread.
12-
public static volatile boolean isPlaybackSpeedMenuVisible;
11+
12+
/**
13+
* Old litho based speed selection menu.
14+
*/
15+
public static volatile boolean isOldPlaybackSpeedMenuVisible;
16+
/**
17+
* 0.05x speed selection menu.
18+
*/
19+
public static volatile boolean isPlaybackRateSelectorMenuVisible;
20+
21+
private final StringFilterGroup playbackRateSelector;
1322

1423
public PlaybackSpeedMenuFilterPatch() {
15-
addPathCallbacks(new StringFilterGroup(
24+
// 0.05x speed menu.
25+
playbackRateSelector = new StringFilterGroup(
1626
null,
17-
"playback_speed_sheet_content.eml-js"
18-
));
27+
"playback_rate_selector_menu_sheet.eml-js"
28+
);
29+
30+
// Old litho based speed menu.
31+
var oldPlaybackMenu = new StringFilterGroup(
32+
null,
33+
"playback_speed_sheet_content.eml-js");
34+
35+
addPathCallbacks(playbackRateSelector, oldPlaybackMenu);
1936
}
2037

2138
@Override
2239
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
2340
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
24-
isPlaybackSpeedMenuVisible = true;
41+
if (matchedGroup == playbackRateSelector) {
42+
isPlaybackRateSelectorMenuVisible = true;
43+
} else {
44+
isOldPlaybackSpeedMenuVisible = true;
45+
}
2546

2647
return false;
2748
}

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

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,20 @@ private static void loadCustomSpeeds() {
5959
if (speedStrings.length == 0) {
6060
throw new IllegalArgumentException();
6161
}
62+
6263
customPlaybackSpeeds = new float[speedStrings.length];
6364
for (int i = 0, length = speedStrings.length; i < length; i++) {
6465
final float speed = Float.parseFloat(speedStrings[i]);
6566
if (speed <= 0 || arrayContains(customPlaybackSpeeds, speed)) {
6667
throw new IllegalArgumentException();
6768
}
69+
6870
if (speed >= MAXIMUM_PLAYBACK_SPEED) {
6971
resetCustomSpeeds(str("revanced_custom_playback_speeds_invalid", MAXIMUM_PLAYBACK_SPEED));
7072
loadCustomSpeeds();
7173
return;
7274
}
75+
7376
customPlaybackSpeeds[i] = speed;
7477
}
7578
} catch (Exception ex) {
@@ -89,10 +92,12 @@ private static boolean arrayContains(float[] array, float value) {
8992
/**
9093
* Initialize a settings preference list with the available playback speeds.
9194
*/
95+
@SuppressWarnings("deprecation")
9296
public static void initializeListPreference(ListPreference preference) {
9397
if (preferenceListEntries == null) {
9498
preferenceListEntries = new String[customPlaybackSpeeds.length];
9599
preferenceListEntryValues = new String[customPlaybackSpeeds.length];
100+
96101
int i = 0;
97102
for (float speed : customPlaybackSpeeds) {
98103
String speedString = String.valueOf(speed);
@@ -101,6 +106,7 @@ public static void initializeListPreference(ListPreference preference) {
101106
i++;
102107
}
103108
}
109+
104110
preference.setEntries(preferenceListEntries);
105111
preference.setEntryValues(preferenceListEntryValues);
106112
}
@@ -111,52 +117,67 @@ public static void initializeListPreference(ListPreference preference) {
111117
public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
112118
recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
113119
try {
114-
// For some reason, the custom playback speed flyout panel is activated when the user opens the share panel. (A/B tests)
115-
// Check the child count of playback speed flyout panel to prevent this issue.
116-
// Child count of playback speed flyout panel is always 8.
117-
if (!PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible || recyclerView.getChildCount() == 0) {
120+
if (PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible) {
121+
if (hideLithoMenuAndShowOldSpeedMenu(recyclerView, 5)) {
122+
PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible = false;
123+
}
118124
return;
119125
}
126+
} catch (Exception ex) {
127+
Logger.printException(() -> "isPlaybackRateSelectorMenuVisible failure failure: ", ex);
128+
}
120129

121-
View firstChild = recyclerView.getChildAt(0);
122-
if (!(firstChild instanceof ViewGroup)) {
123-
return;
124-
}
125-
ViewGroup PlaybackSpeedParentView = (ViewGroup) firstChild;
126-
if (PlaybackSpeedParentView.getChildCount() != 8) {
127-
return;
130+
try {
131+
if (PlaybackSpeedMenuFilterPatch.isOldPlaybackSpeedMenuVisible) {
132+
if (hideLithoMenuAndShowOldSpeedMenu(recyclerView, 8)) {
133+
PlaybackSpeedMenuFilterPatch.isOldPlaybackSpeedMenuVisible = false;
134+
}
128135
}
136+
} catch (Exception ex) {
137+
Logger.printException(() -> "isOldPlaybackSpeedMenuVisible failure: ", ex);
138+
}
139+
});
140+
}
129141

130-
PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false;
131-
132-
ViewParent parentView3rd = Utils.getParentView(recyclerView, 3);
133-
if (!(parentView3rd instanceof ViewGroup)) {
134-
return;
135-
}
136-
ViewParent parentView4th = parentView3rd.getParent();
137-
if (!(parentView4th instanceof ViewGroup)) {
138-
return;
139-
}
142+
private static boolean hideLithoMenuAndShowOldSpeedMenu(RecyclerView recyclerView, int expectedChildCount) {
143+
if (recyclerView.getChildCount() == 0) {
144+
return false;
145+
}
140146

141-
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
142-
// This only shows in phone layout.
143-
final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0);
144-
touchInsidedView.setSoundEffectsEnabled(false);
145-
touchInsidedView.performClick();
147+
View firstChild = recyclerView.getChildAt(0);
148+
if (!(firstChild instanceof ViewGroup)) {
149+
return false;
150+
}
146151

147-
// In tablet layout there is no Dismiss View, instead we just hide all two parent views.
148-
((ViewGroup) parentView3rd).setVisibility(View.GONE);
149-
((ViewGroup) parentView4th).setVisibility(View.GONE);
152+
ViewGroup PlaybackSpeedParentView = (ViewGroup) firstChild;
153+
if (PlaybackSpeedParentView.getChildCount() != expectedChildCount) {
154+
return false;
155+
}
150156

151-
// This works without issues for both tablet and phone layouts,
152-
// So no code is needed to check whether the current device is a tablet or phone.
157+
ViewParent parentView3rd = Utils.getParentView(recyclerView, 3);
158+
if (!(parentView3rd instanceof ViewGroup)) {
159+
return true;
160+
}
153161

154-
// Close the new Playback speed menu and show the old one.
155-
showOldPlaybackSpeedMenu();
156-
} catch (Exception ex) {
157-
Logger.printException(() -> "onFlyoutMenuCreate failure", ex);
162+
ViewParent parentView4th = parentView3rd.getParent();
163+
if (!(parentView4th instanceof ViewGroup)) {
164+
return true;
158165
}
159-
});
166+
167+
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
168+
// This only shows in phone layout.
169+
final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0);
170+
touchInsidedView.setSoundEffectsEnabled(false);
171+
touchInsidedView.performClick();
172+
173+
// In tablet layout there is no Dismiss View, instead we just hide all two parent views.
174+
((ViewGroup) parentView3rd).setVisibility(View.GONE);
175+
((ViewGroup) parentView4th).setVisibility(View.GONE);
176+
177+
// Close the litho speed menu and show the old one.
178+
showOldPlaybackSpeedMenu();
179+
180+
return true;
160181
}
161182

162183
public static void showOldPlaybackSpeedMenu() {

0 commit comments

Comments
 (0)