fix(YouTube): fix old quality and custom speed not working on tablets (#477)

This commit is contained in:
LisoUseInAIKyrios 2023-09-19 06:22:15 +04:00 committed by GitHub
parent aa10de41b6
commit 2352fa5426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 92 deletions

View File

@ -3,71 +3,44 @@ package app.revanced.integrations.patches.playback.quality;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
import android.widget.ListView;
import androidx.annotation.NonNull;
import app.revanced.integrations.patches.components.VideoQualityMenuFilterPatch;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
import com.facebook.litho.ComponentHost;
import kotlin.Deprecated;
// This patch contains the logic to show the old video quality menu.
// Two methods are required, because the quality menu is a RecyclerView in the new YouTube version
// and a ListView in the old one.
/**
* This patch contains the logic to show the old video quality menu.
* Two methods are required, because the quality menu is a RecyclerView in the new YouTube version
* and a ListView in the old one.
*/
public final class OldVideoQualityMenuPatch {
public static void onFlyoutMenuCreate(final LinearLayout linearLayout) {
/**
* Injection point.
*/
public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return;
// The quality menu is a RecyclerView with 3 children. The third child is the "Advanced" quality menu.
addRecyclerListener(linearLayout, 3, 2, recyclerView -> {
// Check if the current view is the quality menu.
if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) {
VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false;
linearLayout.setVisibility(View.GONE);
recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
try {
// Check if the current view is the quality menu.
if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) {
VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false;
((ViewGroup) recyclerView.getParent().getParent().getParent()).setVisibility(View.GONE);
// Click the "Advanced" quality menu to show the "old" quality menu.
((ComponentHost) recyclerView.getChildAt(0)).getChildAt(3).performClick();
LogHelper.printDebug(() -> "Advanced quality menu in new type of quality menu clicked");
// Click the "Advanced" quality menu to show the "old" quality menu.
((ViewGroup) recyclerView.getChildAt(0)).getChildAt(3).performClick();
}
} catch (Exception ex) {
LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex);
}
});
}
public static void addRecyclerListener(@NonNull LinearLayout linearLayout,
int expectedLayoutChildCount, int recyclerViewIndex,
@NonNull RecyclerViewGlobalLayoutListener listener) {
if (linearLayout.getChildCount() != expectedLayoutChildCount) return;
var layoutChild = linearLayout.getChildAt(recyclerViewIndex);
if (!(layoutChild instanceof RecyclerView)) return;
final var recyclerView = (RecyclerView) layoutChild;
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
try {
listener.recyclerOnGlobalLayout(recyclerView);
} catch (Exception ex) {
LogHelper.printException(() -> "addRecyclerListener failure", ex);
} finally {
// Remove the listener because it will be added again.
recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
);
}
public interface RecyclerViewGlobalLayoutListener {
void recyclerOnGlobalLayout(@NonNull RecyclerView recyclerView);
}
@Deprecated(message = "This patch is deprecated because the quality menu is not a ListView anymore")
/**
* Injection point. Only used if spoofing to an old app version.
*/
public static void showOldVideoQualityMenu(final ListView listView) {
if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return;

View File

@ -1,23 +1,23 @@
package app.revanced.integrations.patches.playback.speed;
import android.preference.ListPreference;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import java.util.Arrays;
import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
import com.facebook.litho.ComponentHost;
import java.util.Arrays;
import static app.revanced.integrations.patches.playback.quality.OldVideoQualityMenuPatch.addRecyclerListener;
public class CustomPlaybackSpeedPatch {
/**
* Maximum playback speed, exclusive value. Custom speeds must be less than this value.
* Limit is required otherwise double digit speeds show up out of order in the UI selector.
*/
public static final float MAXIMUM_PLAYBACK_SPEED = 10;
@ -26,16 +26,6 @@ public class CustomPlaybackSpeedPatch {
*/
public static float[] customPlaybackSpeeds;
/**
* Minimum value of {@link #customPlaybackSpeeds}
*/
public static float minPlaybackSpeed;
/**
* Maxium value of {@link #customPlaybackSpeeds}
*/
public static float maxPlaybackSpeed;
/**
* PreferenceList entries and values, of all available playback speeds.
*/
@ -69,8 +59,6 @@ public class CustomPlaybackSpeedPatch {
loadCustomSpeeds();
return;
}
minPlaybackSpeed = Math.min(minPlaybackSpeed, speed);
maxPlaybackSpeed = Math.max(maxPlaybackSpeed, speed);
customPlaybackSpeeds[i] = speed;
}
} catch (Exception ex) {
@ -106,25 +94,37 @@ public class CustomPlaybackSpeedPatch {
preference.setEntryValues(preferenceListEntryValues);
}
/*
* To reduce copy and paste between two similar code paths.
/**
* Injection point.
*/
public static void onFlyoutMenuCreate(final LinearLayout linearLayout) {
// The playback rate menu is a RecyclerView with 2 children. The third child is the "Advanced" quality menu.
addRecyclerListener(linearLayout, 2, 1, recyclerView -> {
if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible) {
PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false;
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
&& ((ViewGroup) recyclerView.getChildAt(0)).getChildCount() == 8) {
PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false;
ViewGroup parentView3rd = (ViewGroup) recyclerView.getParent().getParent().getParent();
ViewGroup parentView4th = (ViewGroup) parentView3rd.getParent();
if (recyclerView.getChildCount() == 1 && recyclerView.getChildAt(0) instanceof ComponentHost) {
linearLayout.setVisibility(View.GONE);
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
// This only shows in phone layout.
parentView4th.getChildAt(0).performClick();
// Close the new Playback speed menu and instead show the old one.
// In tablet layout there is no Dismiss View, instead we just hide all two parent views.
parentView3rd.setVisibility(View.GONE);
parentView4th.setVisibility(View.GONE);
// 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.
// Close the new Playback speed menu and show the old one.
showOldPlaybackSpeedMenu();
// DismissView [R.id.touch_outside] is the 1st ChildView of the 3rd ParentView.
((ViewGroup) linearLayout.getParent().getParent().getParent())
.getChildAt(0).performClick();
}
} catch (Exception ex) {
LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex);
}
});
}

View File

@ -1,10 +0,0 @@
package com.facebook.litho;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
public final class ComponentHost extends RecyclerView {
public ComponentHost(Context context) {
super(context);
}
}