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

feat(YouTube): Add Shorts autoplay patch #719

Merged
merged 12 commits into from
Oct 21, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package app.revanced.integrations.youtube.patches;

import android.app.Activity;
import android.os.Build;

import androidx.annotation.RequiresApi;

import java.lang.ref.WeakReference;
import java.util.Objects;

import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.settings.Settings;

@SuppressWarnings("unused")
public class ShortsAutoplayPatch {

private enum ShortsLoopBehavior {
UNKNOWN,
/**
* Repeat the same Short forever!
*/
REPEAT,
/**
* Play once, then advanced to the next Short.
*/
SINGLE_PLAY,
/**
* Pause playback after 1 play.
*/
END_SCREEN;

static void setYTEnumValue(Enum<?> ytBehavior) {
for (ShortsLoopBehavior rvBehavior : values()) {
if (ytBehavior.name().endsWith(rvBehavior.name())) {
rvBehavior.ytEnumValue = ytBehavior;

Logger.printDebug(() -> rvBehavior + " set to YT enum: " + ytBehavior.name());
return;
}
}

Logger.printException(() -> "Unknown Shorts loop behavior: " + ytBehavior.name());
}

/**
* YouTube enum value of the obfuscated enum type.
*/
private Enum<?> ytEnumValue;
}

private static WeakReference<Activity> mainActivityRef = new WeakReference<>(null);


public static void setMainActivity(Activity activity) {
mainActivityRef = new WeakReference<>(activity);
}

/**
* @return If the app is currently in background PiP mode.
*/
@RequiresApi(api = Build.VERSION_CODES.N)
private static boolean isAppInBackgroundPiPMode() {
Activity activity = mainActivityRef.get();
return activity != null && activity.isInPictureInPictureMode();
}

/**
* Injection point.
*/
public static void setYTShortsRepeatEnum(Enum<?> ytEnum) {
try {
for (Enum<?> ytBehavior : Objects.requireNonNull(ytEnum.getClass().getEnumConstants())) {
ShortsLoopBehavior.setYTEnumValue(ytBehavior);
}
} catch (Exception ex) {
Logger.printException(() -> "setYTShortsRepeatEnum failure", ex);
}
}

/**
* Injection point.
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public static Enum<?> changeShortsRepeatBehavior(Enum<?> original) {
try {
final boolean autoplay;

if (isAppInBackgroundPiPMode()) {
if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
// 19.34+ is required to set background play behavior.
Logger.printDebug(() -> "PiP Shorts not supported, using original repeat behavior");

return original;
}

autoplay = Settings.SHORTS_AUTOPLAY_BACKGROUND.get();
} else {
autoplay = Settings.SHORTS_AUTOPLAY.get();
}

final ShortsLoopBehavior behavior = autoplay
? ShortsLoopBehavior.SINGLE_PLAY
: ShortsLoopBehavior.REPEAT;

if (behavior.ytEnumValue != null) {
Logger.printDebug(() -> behavior.ytEnumValue == original
? "Changing Shorts repeat behavior from: " + original.name() + " to: " + behavior.ytEnumValue
: "Behavior setting is same as original. Using original: " + original.name()
);

return behavior.ytEnumValue;
}
} catch (Exception ex) {
Logger.printException(() -> "changeShortsRepeatState failure", ex);
}

return original;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ public class VersionCheckPatch {
public static final boolean IS_19_21_OR_GREATER = Utils.getAppVersionName().compareTo("19.21.00") >= 0;
public static final boolean IS_19_26_OR_GREATER = Utils.getAppVersionName().compareTo("19.26.00") >= 0;
public static final boolean IS_19_29_OR_GREATER = Utils.getAppVersionName().compareTo("19.29.00") >= 0;
public static final boolean IS_19_34_OR_GREATER = Utils.getAppVersionName().compareTo("19.34.00") >= 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ public static int getSeekbarColor() {
}

public static boolean playerSeekbarGradientEnabled(boolean original) {
if (original) {
Logger.printDebug(() -> "playerSeekbarGradientEnabled original: " + true);
if (SEEKBAR_CUSTOM_COLOR_ENABLED) return false;
}
if (SEEKBAR_CUSTOM_COLOR_ENABLED) return false;

return original;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_SHORTS_SOUND_METADATA_LABEL = new BooleanSetting("revanced_hide_shorts_sound_metadata_label", FALSE);
public static final BooleanSetting HIDE_SHORTS_FULL_VIDEO_LINK_LABEL = new BooleanSetting("revanced_hide_shorts_full_video_link_label", FALSE);
public static final BooleanSetting HIDE_SHORTS_NAVIGATION_BAR = new BooleanSetting("revanced_hide_shorts_navigation_bar", FALSE, true);
public static final BooleanSetting SHORTS_AUTOPLAY = new BooleanSetting("revanced_shorts_autoplay", FALSE);
public static final BooleanSetting SHORTS_AUTOPLAY_BACKGROUND = new BooleanSetting("revanced_shorts_autoplay_background", TRUE);

// Seekbar
public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", TRUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,10 +662,7 @@ private static void setSponsorBarAbsoluteRight(Rect rect) {
*/
@SuppressWarnings("unused")
public static void setSponsorBarThickness(int thickness) {
if (sponsorBarThickness != thickness) {
Logger.printDebug(() -> "setSponsorBarThickness: " + thickness);
sponsorBarThickness = thickness;
}
sponsorBarThickness = thickness;
}

/**
Expand Down
Loading