Skip to content

Commit

Permalink
feat(YouTube): Add Open Shorts in regular player patch (#4153)
Browse files Browse the repository at this point in the history
  • Loading branch information
LisoUseInAIKyrios authored Dec 19, 2024
1 parent a4db3f1 commit c7c5e5b
Show file tree
Hide file tree
Showing 18 changed files with 463 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package app.revanced.extension.youtube.patches;

import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;

import java.lang.ref.WeakReference;

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

@SuppressWarnings("unused")
public class OpenShortsInRegularPlayerPatch {

public enum ShortsPlayerType {
SHORTS_PLAYER,
REGULAR_PLAYER,
REGULAR_PLAYER_FULLSCREEN
}

static {
if (!VersionCheckPatch.IS_19_46_OR_GREATER
&& Settings.SHORTS_PLAYER_TYPE.get() == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN) {
// User imported newer settings to an older app target.
Logger.printInfo(() -> "Resetting " + Settings.SHORTS_PLAYER_TYPE);
Settings.SHORTS_PLAYER_TYPE.resetToDefault();
}
}

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

/**
* Injection point.
*/
public static void setMainActivity(Activity activity) {
mainActivityRef = new WeakReference<>(activity);
}

/**
* Injection point.
*/
public static boolean openShort(String videoID) {
try {
ShortsPlayerType type = Settings.SHORTS_PLAYER_TYPE.get();
if (type == ShortsPlayerType.SHORTS_PLAYER) {
return false; // Default unpatched behavior.
}

if (videoID.isEmpty()) {
// Shorts was opened using launcher app shortcut.
//
// This check will not detect if the Shorts app shortcut is used
// while the app is running in the background (instead the regular player is opened).
// To detect that the hooked method map parameter can be checked
// if integer key 'com.google.android.apps.youtube.app.endpoint.flags'
// has bitmask 16 set.
//
// This use case seems unlikely if the user has the Shorts
// set to open in the regular player, so it's ignored as
// checking the map makes the patch more complicated.
Logger.printDebug(() -> "Ignoring Short with no videoId");
return false;
}

if (NavigationButton.getSelectedNavigationButton() == NavigationButton.SHORTS) {
return false; // Always use Shorts player for the Shorts nav button.
}

final boolean forceFullScreen = (type == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN);
OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(forceFullScreen);

// Can use the application context and add intent flags of
// FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TOP
// But the activity context seems to fix random app crashes
// if Shorts urls are opened outside the app.
var context = mainActivityRef.get();

Intent videoPlayerIntent = new Intent(
Intent.ACTION_VIEW,
Uri.parse("https://youtube.com/watch?v=" + videoID)
);
videoPlayerIntent.setPackage(context.getPackageName());

context.startActivity(videoPlayerIntent);
return true;
} catch (Exception ex) {
OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(null);
Logger.printException(() -> "openShort failure", ex);
return false;
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package app.revanced.extension.youtube.patches;

import androidx.annotation.Nullable;

import app.revanced.extension.youtube.settings.Settings;

@SuppressWarnings("unused")
public class OpenVideosFullscreenHookPatch {

@Nullable
private static volatile Boolean openNextVideoFullscreen;

public static void setOpenNextVideoFullscreen(@Nullable Boolean forceFullScreen) {
openNextVideoFullscreen = forceFullScreen;
}

/**
* Changed during patching since this class is also
* used by {@link OpenVideosFullscreenHookPatch}.
*/
private static boolean isFullScreenPatchIncluded() {
return false;
}

/**
* Injection point.
*/
public static boolean openVideoFullscreenPortrait(boolean original) {
Boolean openFullscreen = openNextVideoFullscreen;
if (openFullscreen != null) {
openNextVideoFullscreen = null;
return openFullscreen;
}

if (!isFullScreenPatchIncluded()) {
return false;
}

return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public class VersionCheckPatch {
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;
public static final boolean IS_19_46_OR_GREATER = Utils.getAppVersionName().compareTo("19.46.00") >= 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_2;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_3;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_4;
import static app.revanced.extension.youtube.patches.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_19_17_OR_GREATER;
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.IGNORE;
Expand Down Expand Up @@ -224,6 +225,7 @@ public class Settings extends BaseSettings {
// Shorts
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE);
public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_shorts_disable_background_playback", FALSE);
public static final EnumSetting<ShortsPlayerType> SHORTS_PLAYER_TYPE = new EnumSetting<>("revanced_shorts_player_type", ShortsPlayerType.SHORTS_PLAYER);
public static final BooleanSetting HIDE_SHORTS_CHANNEL_BAR = new BooleanSetting("revanced_hide_shorts_channel_bar", FALSE);
public static final BooleanSetting HIDE_SHORTS_COMMENTS_BUTTON = new BooleanSetting("revanced_hide_shorts_comments_button", FALSE);
public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE);
Expand Down
8 changes: 8 additions & 0 deletions patches/api/patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,10 @@ public final class app/revanced/patches/youtube/layout/player/background/PlayerC
}

public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt {
public static final fun getOpenVideosFullscreen ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatchKt {
public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

Expand Down Expand Up @@ -1210,6 +1214,10 @@ public final class app/revanced/patches/youtube/layout/shortsautoplay/ShortsAuto
public static final fun getShortsAutoplayPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatchKt {
public static final fun getOpenShortsInRegularPlayerPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatchKt {
public static final fun getSponsorBlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package app.revanced.patches.shared.misc.checks

import android.os.Build.*
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
Expand Down Expand Up @@ -82,7 +82,7 @@ fun checkEnvironmentPatch(
}
}

fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstructions(
fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstruction(
0,
"invoke-static/range { p0 .. p0 },$EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@ internal val openVideosFullscreenPortraitFingerprint = fingerprint {
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG
}
}

/**
* Used to enable opening regular videos fullscreen.
*/
internal val openVideosFullscreenHookPatchExtensionFingerprint = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
returns("Z")
parameters()
custom { methodDef, classDef ->
methodDef.name == "isFullScreenPatchIncluded" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
}
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,9 @@
package app.revanced.patches.youtube.layout.player.fullscreen

import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.insertFeatureFlagBooleanOverride

private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreen;"

@Suppress("unused")
val openVideosFullscreenPatch = bytecodePatch(
name = "Open videos fullscreen",
description = "Adds an option to open videos in full screen portrait mode.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
)

compatibleWith(
"com.google.android.youtube"(
"19.46.42",
)
)

execute {
openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
)

// Add resources and setting last, in case the user force patches an old incompatible version.

addResources("youtube", "layout.player.fullscreen.openVideosFullscreen")

PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_open_videos_fullscreen_portrait")
)
}
}
@Deprecated("Renamed to openVideosFullscreenPatch", ReplaceWith("openVideosFullscreenPatch"))
val openVideosFullscreen = bytecodePatch{
dependsOn(openVideosFullscreenPatch)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package app.revanced.patches.youtube.layout.player.fullscreen

import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.youtube.layout.shortsplayer.openShortsInRegularPlayerPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.util.insertFeatureFlagBooleanOverride

internal const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch;"

/**
* Used by both [openVideosFullscreenPatch] and [openShortsInRegularPlayerPatch].
*/
internal val openVideosFullscreenHookPatch = bytecodePatch {
dependsOn(
sharedExtensionPatch,
versionCheckPatch
)

execute {
if (!is_19_46_or_greater) {
return@execute
}

openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package app.revanced.patches.youtube.layout.player.fullscreen

import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.returnEarly

@Suppress("unused")
val openVideosFullscreenPatch = bytecodePatch(
name = "Open videos fullscreen",
description = "Adds an option to open videos in full screen portrait mode.",
) {
dependsOn(
openVideosFullscreenHookPatch,
settingsPatch,
addResourcesPatch,
versionCheckPatch
)

compatibleWith(
"com.google.android.youtube"(
"19.46.42",
)
)

execute {
if (!is_19_46_or_greater) {
throw PatchException("'Open videos fullscreen' requires 19.46.42 or greater")
}

addResources("youtube", "layout.player.fullscreen.openVideosFullscreen")

PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_open_videos_fullscreen_portrait")
)

// Enable the logic for the user Setting to open regular videos fullscreen.
openVideosFullscreenHookPatchExtensionFingerprint.method.returnEarly(true)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.shortsautoplay

import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
Expand Down Expand Up @@ -56,7 +57,7 @@ val shortsAutoplayPatch = bytecodePatch(
}

// Main activity is used to check if app is in pip mode.
mainActivityOnCreateFingerprint.method.addInstructions(
mainActivityOnCreateFingerprint.method.addInstruction(
1,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
"setMainActivity(Landroid/app/Activity;)V",
Expand Down
Loading

0 comments on commit c7c5e5b

Please sign in to comment.