From dabbc3de3a1e2134314b8c6bcc84ebdaed896f75 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 25 Oct 2024 06:35:06 -0400 Subject: [PATCH] fix(YouTube - Playback speed): Restore old playback speed menu --- .../revanced/integrations/shared/Utils.java | 5 +- .../PlaybackSpeedMenuFilterPatch.java | 33 +++++-- .../speed/CustomPlaybackSpeedPatch.java | 93 ++++++++++++------- 3 files changed, 87 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/shared/Utils.java b/app/src/main/java/app/revanced/integrations/shared/Utils.java index 296c0b3bc0..86906be688 100644 --- a/app/src/main/java/app/revanced/integrations/shared/Utils.java +++ b/app/src/main/java/app/revanced/integrations/shared/Utils.java @@ -317,9 +317,10 @@ public static ViewParent getParentView(@NonNull View view, int nthParent) { return parent; } - final int currentDepthLog = currentDepth; + final int finalDepthLog = currentDepth; + final ViewParent finalParent = parent; Logger.printDebug(() -> "Could not find parent view of depth: " + nthParent - + " and instead found at: " + currentDepthLog + " view: " + view); + + " and instead found at: " + finalDepthLog + " view: " + finalParent); return null; } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java index 03319588d5..f6b9ba806f 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java @@ -8,20 +8,41 @@ * Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}. */ public final class PlaybackSpeedMenuFilterPatch extends Filter { - // Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread. - public static volatile boolean isPlaybackSpeedMenuVisible; + + /** + * Old litho based speed selection menu. + */ + public static volatile boolean isOldPlaybackSpeedMenuVisible; + /** + * 0.05x speed selection menu. + */ + public static volatile boolean isPlaybackRateSelectorMenuVisible; + + private final StringFilterGroup playbackRateSelector; public PlaybackSpeedMenuFilterPatch() { - addPathCallbacks(new StringFilterGroup( + // 0.05x speed menu. + playbackRateSelector = new StringFilterGroup( null, - "playback_speed_sheet_content.eml-js" - )); + "playback_rate_selector_menu_sheet.eml-js" + ); + + // Old litho based speed menu. + var oldPlaybackMenu = new StringFilterGroup( + null, + "playback_speed_sheet_content.eml-js"); + + addPathCallbacks(playbackRateSelector, oldPlaybackMenu); } @Override boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { - isPlaybackSpeedMenuVisible = true; + if (matchedGroup == playbackRateSelector) { + isPlaybackRateSelectorMenuVisible = true; + } else { + isOldPlaybackSpeedMenuVisible = true; + } return false; } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java index 2ca56ed315..9550df3073 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -59,17 +59,20 @@ private static void loadCustomSpeeds() { if (speedStrings.length == 0) { throw new IllegalArgumentException(); } + customPlaybackSpeeds = 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(customPlaybackSpeeds, speed)) { throw new IllegalArgumentException(); } + if (speed >= MAXIMUM_PLAYBACK_SPEED) { resetCustomSpeeds(str("revanced_custom_playback_speeds_invalid", MAXIMUM_PLAYBACK_SPEED)); loadCustomSpeeds(); return; } + customPlaybackSpeeds[i] = speed; } } catch (Exception ex) { @@ -89,10 +92,12 @@ private static boolean arrayContains(float[] array, float value) { /** * Initialize a settings preference list with the available playback speeds. */ + @SuppressWarnings("deprecation") public static void initializeListPreference(ListPreference preference) { if (preferenceListEntries == null) { preferenceListEntries = new String[customPlaybackSpeeds.length]; preferenceListEntryValues = new String[customPlaybackSpeeds.length]; + int i = 0; for (float speed : customPlaybackSpeeds) { String speedString = String.valueOf(speed); @@ -101,6 +106,7 @@ public static void initializeListPreference(ListPreference preference) { i++; } } + preference.setEntries(preferenceListEntries); preference.setEntryValues(preferenceListEntryValues); } @@ -111,52 +117,67 @@ public static void initializeListPreference(ListPreference preference) { public static void onFlyoutMenuCreate(RecyclerView recyclerView) { recyclerView.getViewTreeObserver().addOnDrawListener(() -> { try { - // For some reason, the custom playback speed flyout panel is activated when the user opens the share panel. (A/B tests) - // Check the child count of playback speed flyout panel to prevent this issue. - // Child count of playback speed flyout panel is always 8. - if (!PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible || recyclerView.getChildCount() == 0) { + if (PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible) { + if (hideLithoMenuAndShowOldSpeedMenu(recyclerView, 5)) { + PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible = false; + } return; } + } catch (Exception ex) { + Logger.printException(() -> "isPlaybackRateSelectorMenuVisible failure failure: ", ex); + } - View firstChild = recyclerView.getChildAt(0); - if (!(firstChild instanceof ViewGroup)) { - return; - } - ViewGroup PlaybackSpeedParentView = (ViewGroup) firstChild; - if (PlaybackSpeedParentView.getChildCount() != 8) { - return; + try { + if (PlaybackSpeedMenuFilterPatch.isOldPlaybackSpeedMenuVisible) { + if (hideLithoMenuAndShowOldSpeedMenu(recyclerView, 8)) { + PlaybackSpeedMenuFilterPatch.isOldPlaybackSpeedMenuVisible = false; + } } + } catch (Exception ex) { + Logger.printException(() -> "isOldPlaybackSpeedMenuVisible failure: ", ex); + } + }); + } - PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false; - - ViewParent parentView3rd = Utils.getParentView(recyclerView, 3); - if (!(parentView3rd instanceof ViewGroup)) { - return; - } - ViewParent parentView4th = parentView3rd.getParent(); - if (!(parentView4th instanceof ViewGroup)) { - return; - } + private static boolean hideLithoMenuAndShowOldSpeedMenu(RecyclerView recyclerView, int expectedChildCount) { + if (recyclerView.getChildCount() == 0) { + return false; + } - // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView. - // This only shows in phone layout. - final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0); - touchInsidedView.setSoundEffectsEnabled(false); - touchInsidedView.performClick(); + View firstChild = recyclerView.getChildAt(0); + if (!(firstChild instanceof ViewGroup)) { + return false; + } - // In tablet layout there is no Dismiss View, instead we just hide all two parent views. - ((ViewGroup) parentView3rd).setVisibility(View.GONE); - ((ViewGroup) parentView4th).setVisibility(View.GONE); + ViewGroup PlaybackSpeedParentView = (ViewGroup) firstChild; + if (PlaybackSpeedParentView.getChildCount() != expectedChildCount) { + return false; + } - // This works without issues for both tablet and phone layouts, - // So no code is needed to check whether the current device is a tablet or phone. + ViewParent parentView3rd = Utils.getParentView(recyclerView, 3); + if (!(parentView3rd instanceof ViewGroup)) { + return true; + } - // Close the new Playback speed menu and show the old one. - showOldPlaybackSpeedMenu(); - } catch (Exception ex) { - Logger.printException(() -> "onFlyoutMenuCreate failure", ex); + ViewParent parentView4th = parentView3rd.getParent(); + if (!(parentView4th instanceof ViewGroup)) { + return true; } - }); + + // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView. + // This only shows in phone layout. + final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0); + touchInsidedView.setSoundEffectsEnabled(false); + touchInsidedView.performClick(); + + // In tablet layout there is no Dismiss View, instead we just hide all two parent views. + ((ViewGroup) parentView3rd).setVisibility(View.GONE); + ((ViewGroup) parentView4th).setVisibility(View.GONE); + + // Close the litho speed menu and show the old one. + showOldPlaybackSpeedMenu(); + + return true; } public static void showOldPlaybackSpeedMenu() {