From 1f95e07e7a7b718db4dfde677b453f5694523c54 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Fri, 3 Jan 2025 21:54:27 +0900 Subject: [PATCH] feat(YouTube - Fullscreen components): Add `Enter fullscreen mode` setting --- .../patches/player/EnterFullscreenPatch.java | 67 +++++++++++++++++++ .../extension/youtube/settings/Settings.java | 1 + .../BaseMainActivityResolvePatch.kt | 7 ++ .../fullscreen/FullscreenComponentsPatch.kt | 22 ++++++ .../youtube/settings/host/values/strings.xml | 5 ++ .../youtube/settings/xml/revanced_prefs.xml | 1 + 6 files changed, 103 insertions(+) create mode 100644 extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/EnterFullscreenPatch.java diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/EnterFullscreenPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/EnterFullscreenPatch.java new file mode 100644 index 000000000..5c5bed7ab --- /dev/null +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/EnterFullscreenPatch.java @@ -0,0 +1,67 @@ +package app.revanced.extension.youtube.patches.player; + +import androidx.annotation.NonNull; + +import app.revanced.extension.shared.utils.Logger; +import app.revanced.extension.shared.utils.Utils; +import app.revanced.extension.youtube.settings.Settings; +import app.revanced.extension.youtube.shared.PlayerType; +import app.revanced.extension.youtube.utils.VideoUtils; + +@SuppressWarnings("unused") +public class EnterFullscreenPatch { + private static volatile boolean isForeground = true; + + @NonNull + private static String videoId = ""; + + /** + * Injection point. + */ + public static void onAppBackgrounded() { + isForeground = false; + } + + /** + * Injection point. + */ + public static void onAppForegrounded() { + isForeground = true; + } + + /** + * Injection point. + */ + public static void enterFullscreen(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName, + @NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle, + final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) { + try { + if (!Settings.ENTER_FULLSCREEN.get()) { + return; + } + PlayerType playerType = PlayerType.getCurrent(); + // 1. The user opened the video while playing a video in the feed. + // 2. This is a valid request, so the videoId is not saved. + if (playerType == PlayerType.INLINE_MINIMAL) { + return; + } + if (videoId.equals(newlyLoadedVideoId)) { + return; + } + videoId = newlyLoadedVideoId; + + // 1. User clicks home button in [PlayerType.WATCH_WHILE_MAXIMIZED], thus entering audio only mode. + // 2. PlayerType is still [PlayerType.WATCH_WHILE_MAXIMIZED]. + // 3. Next video starts in audio only mode, then returns to foreground mode. + // 4. Enters fullscreen for a moment and then returns. + // We can prevent this by checking if the app is in the foreground. + if (playerType == PlayerType.WATCH_WHILE_MAXIMIZED && isForeground) { + // It works without delay, but in this case sometimes portrait videos have landscape orientation. + Utils.runOnMainThreadDelayed(VideoUtils::enterFullscreenMode, 250L); + } + } catch (Exception ex) { + Logger.printException(() -> "enterFullscreen failure", ex); + } + } + +} diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java index ade8423d5..6658ef05a 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -335,6 +335,7 @@ public class Settings extends BaseSettings { // PreferenceScreen: Player - Fullscreen public static final BooleanSetting DISABLE_ENGAGEMENT_PANEL = new BooleanSetting("revanced_disable_engagement_panel", FALSE, true); + public static final BooleanSetting ENTER_FULLSCREEN = new BooleanSetting("revanced_enter_fullscreen", FALSE); public static final EnumSetting EXIT_FULLSCREEN = new EnumSetting<>("revanced_exit_fullscreen", FullscreenMode.DISABLED); public static final BooleanSetting SHOW_VIDEO_TITLE_SECTION = new BooleanSetting("revanced_show_video_title_section", TRUE, true, parent(DISABLE_ENGAGEMENT_PANEL)); public static final BooleanSetting HIDE_AUTOPLAY_PREVIEW = new BooleanSetting("revanced_hide_autoplay_preview", FALSE, true); diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt index 8122949da..af3c7355f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt @@ -18,6 +18,10 @@ lateinit var onConfigurationChangedMethod: MutableMethod private set lateinit var onCreateMethod: MutableMethod private set +lateinit var onStartMethod: MutableMethod + private set +lateinit var onStopMethod: MutableMethod + private set private lateinit var constructorMethod: MutableMethod private lateinit var onBackPressedMethod: MutableMethod @@ -45,6 +49,9 @@ fun baseMainActivityResolvePatch( // set onConfigurationChanged method onConfigurationChangedMethod = getMainActivityMethod("onConfigurationChanged") + + onStartMethod = getMainActivityMethod("onStart") + onStopMethod = getMainActivityMethod("onStop") } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt index e721180e6..21f315edc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt @@ -11,6 +11,8 @@ import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.litho.addLithoFilter import app.revanced.patches.shared.litho.lithoFilterPatch import app.revanced.patches.shared.mainactivity.onConfigurationChangedMethod +import app.revanced.patches.shared.mainactivity.onStartMethod +import app.revanced.patches.shared.mainactivity.onStopMethod import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.extension.Constants.PATCH_STATUS_CLASS_DESCRIPTOR @@ -31,6 +33,7 @@ import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference import app.revanced.patches.youtube.utils.settings.settingsPatch import app.revanced.patches.youtube.utils.youtubeControlsOverlayFingerprint +import app.revanced.patches.youtube.video.information.hookBackgroundPlayVideoInformation import app.revanced.patches.youtube.video.information.videoEndMethod import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.util.Utils.printWarn @@ -54,6 +57,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val FILTER_CLASS_DESCRIPTOR = "$COMPONENTS_PATH/QuickActionFilter;" +private const val EXTENSION_ENTER_FULLSCREEN_CLASS_DESCRIPTOR = + "$PLAYER_PATH/EnterFullscreenPatch;" + private const val EXTENSION_EXIT_FULLSCREEN_CLASS_DESCRIPTOR = "$PLAYER_PATH/ExitFullscreenPatch;" @@ -118,6 +124,22 @@ val fullscreenComponentsPatch = bytecodePatch( // endregion + // region patch for enter fullscreen + + mapOf( + onStartMethod to "onAppForegrounded", + onStopMethod to "onAppBackgrounded" + ).forEach { (method, name) -> + method.addInstruction( + 0, + "invoke-static {}, $EXTENSION_ENTER_FULLSCREEN_CLASS_DESCRIPTOR->$name()V" + ) + } + + hookBackgroundPlayVideoInformation("$EXTENSION_ENTER_FULLSCREEN_CLASS_DESCRIPTOR->enterFullscreen(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V") + + // endregion + // region patch for exit fullscreen videoEndMethod.apply { diff --git a/patches/src/main/resources/youtube/settings/host/values/strings.xml b/patches/src/main/resources/youtube/settings/host/values/strings.xml index d12e3b47b..dc3c41d7e 100644 --- a/patches/src/main/resources/youtube/settings/host/values/strings.xml +++ b/patches/src/main/resources/youtube/settings/host/values/strings.xml @@ -923,6 +923,11 @@ Settings → Autoplay → Autoplay next video" Disable engagement panel Engagement panel is disabled. Engagement panel is enabled. + Enter fullscreen mode when video starts + "Enter fullscreen mode when the video starts. + +Limitation: Does not work if the player is minimized, in PiP mode, or in the background. + Do not enter fullscreen mode when the video starts. Exit fullscreen mode at end of video Disabled Portrait diff --git a/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml index c91f850ad..f87a6a472 100644 --- a/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -397,6 +397,7 @@