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 d945af94f3
commit dbec9b80eb
2 changed files with 55 additions and 82 deletions

View File

@ -3,71 +3,44 @@ package app.revanced.integrations.patches.playback.quality;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
import android.widget.ListView; import android.widget.ListView;
import androidx.annotation.NonNull;
import app.revanced.integrations.patches.components.VideoQualityMenuFilterPatch; import app.revanced.integrations.patches.components.VideoQualityMenuFilterPatch;
import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper; 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 * This patch contains the logic to show the old video quality menu.
// and a ListView in the old one. * 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 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; 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. recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
addRecyclerListener(linearLayout, 3, 2, recyclerView -> { try {
// Check if the current view is the quality menu. // Check if the current view is the quality menu.
if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) { if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) {
VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false; VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false;
linearLayout.setVisibility(View.GONE); ((ViewGroup) recyclerView.getParent().getParent().getParent()).setVisibility(View.GONE);
// Click the "Advanced" quality menu to show the "old" quality menu. // Click the "Advanced" quality menu to show the "old" quality menu.
((ComponentHost) recyclerView.getChildAt(0)).getChildAt(3).performClick(); ((ViewGroup) recyclerView.getChildAt(0)).getChildAt(3).performClick();
LogHelper.printDebug(() -> "Advanced quality menu in new type of quality menu clicked"); }
} catch (Exception ex) {
LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex);
} }
}); });
} }
public static void addRecyclerListener(@NonNull LinearLayout linearLayout, /**
int expectedLayoutChildCount, int recyclerViewIndex, * Injection point. Only used if spoofing to an old app version.
@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")
public static void showOldVideoQualityMenu(final ListView listView) { public static void showOldVideoQualityMenu(final ListView listView) {
if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return;

View File

@ -1,23 +1,23 @@
package app.revanced.integrations.patches.playback.speed; package app.revanced.integrations.patches.playback.speed;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.util.Arrays;
import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch; import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch;
import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils; 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 { public class CustomPlaybackSpeedPatch {
/** /**
* Maximum playback speed, exclusive value. Custom speeds must be less than this value. * 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; public static final float MAXIMUM_PLAYBACK_SPEED = 10;
@ -26,16 +26,6 @@ public class CustomPlaybackSpeedPatch {
*/ */
public static float[] customPlaybackSpeeds; 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. * PreferenceList entries and values, of all available playback speeds.
*/ */
@ -69,8 +59,6 @@ public class CustomPlaybackSpeedPatch {
loadCustomSpeeds(); loadCustomSpeeds();
return; return;
} }
minPlaybackSpeed = Math.min(minPlaybackSpeed, speed);
maxPlaybackSpeed = Math.max(maxPlaybackSpeed, speed);
customPlaybackSpeeds[i] = speed; customPlaybackSpeeds[i] = speed;
} }
} catch (Exception ex) { } catch (Exception ex) {
@ -106,25 +94,37 @@ public class CustomPlaybackSpeedPatch {
preference.setEntryValues(preferenceListEntryValues); preference.setEntryValues(preferenceListEntryValues);
} }
/* /**
* To reduce copy and paste between two similar code paths. * Injection point.
*/ */
public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
// The playback rate menu is a RecyclerView with 2 children. The third child is the "Advanced" quality menu. recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
addRecyclerListener(linearLayout, 2, 1, recyclerView -> { try {
if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible) { // For some reason, the custom playback speed flyout panel is activated when the user opens the share panel. (A/B tests)
PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false; // 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) { // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
linearLayout.setVisibility(View.GONE); // 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(); 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);
} }
}); });
} }