From 58898b92fe12f2f3d7f0f8794e89f265c2ba480b Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 21 Mar 2026 19:37:50 +0100 Subject: [PATCH] fix(YouTube - Disable Shorts resuming on startup): Resolve patch not working on experimental versions Co-authored-by: ILoveOpenSourceApplications <117499019+iloveopensourceapplications@users.noreply.github.com> --- .../DisableResumingShortsOnStartupPatch.java | 21 +++++ ...sableResumingStartupShortsPlayerPatch.java | 21 ----- .../extension/youtube/settings/Settings.java | 2 +- .../DisableResumingShortsOnStartupPatch.kt | 40 ++++++---- .../layout/shortsresuming/Fingerprints.kt | 79 +++++++++++++++++++ .../layout/startupshortsreset/Fingerprints.kt | 46 ----------- .../resources/addresources/values/strings.xml | 8 +- 7 files changed, 130 insertions(+), 87 deletions(-) create mode 100644 extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingShortsOnStartupPatch.java delete mode 100644 extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch.java rename patches/src/main/kotlin/app/revanced/patches/youtube/layout/{startupshortsreset => shortsresuming}/DisableResumingShortsOnStartupPatch.kt (75%) create mode 100644 patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/Fingerprints.kt delete mode 100644 patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingShortsOnStartupPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingShortsOnStartupPatch.java new file mode 100644 index 0000000000..5f42b36db6 --- /dev/null +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingShortsOnStartupPatch.java @@ -0,0 +1,21 @@ +package app.revanced.extension.youtube.patches; + +import app.revanced.extension.youtube.settings.Settings; + +@SuppressWarnings("unused") +public class DisableResumingShortsOnStartupPatch { + + /** + * Injection point. + */ + public static boolean disableResumingShortsOnStartup() { + return Settings.DISABLE_RESUMING_SHORTS_ON_STARTUP.get(); + } + + /** + * Injection point. + */ + public static boolean disableResumingShortsOnStartup(boolean original) { + return original && !Settings.DISABLE_RESUMING_SHORTS_ON_STARTUP.get(); + } +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch.java deleted file mode 100644 index 2e8c3cc06a..0000000000 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch.java +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.extension.youtube.patches; - -import app.revanced.extension.youtube.settings.Settings; - -@SuppressWarnings("unused") -public class DisableResumingStartupShortsPlayerPatch { - - /** - * Injection point. - */ - public static boolean disableResumingStartupShortsPlayer() { - return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get(); - } - - /** - * Injection point. - */ - public static boolean disableResumingStartupShortsPlayer(boolean original) { - return original && !Settings.DISABLE_RESUMING_SHORTS_PLAYER.get(); - } -} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java index 6f3c273865..18a557d67f 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -324,7 +324,7 @@ public class Settings extends YouTubeAndMusicSettings { public static final BooleanSetting WIDE_SEARCHBAR = new BooleanSetting("revanced_wide_searchbar", FALSE, true); // Shorts - public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE); + public static final BooleanSetting DISABLE_RESUMING_SHORTS_ON_STARTUP = new BooleanSetting("revanced_disable_resuming_shorts_on_startup", FALSE); public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_shorts_disable_background_playback", FALSE); public static final EnumSetting SHORTS_PLAYER_TYPE = new EnumSetting<>("revanced_shorts_player_type", ShortsPlayerType.SHORTS_PLAYER); public static final BooleanSetting HIDE_SHORTS_AI_BUTTON = new BooleanSetting("revanced_hide_shorts_ai_button", FALSE); diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/DisableResumingShortsOnStartupPatch.kt similarity index 75% rename from patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt rename to patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/DisableResumingShortsOnStartupPatch.kt index c7ca37a67f..2c759c98ec 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/DisableResumingShortsOnStartupPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.layout.startupshortsreset +package app.revanced.patches.youtube.layout.shortsresuming import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction @@ -18,10 +18,11 @@ import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = - "Lapp/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch;" + "Lapp/revanced/extension/youtube/patches/DisableResumingShortsOnStartupPatch;" @Suppress("unused") val disableResumingShortsOnStartupPatch = bytecodePatch( @@ -44,24 +45,33 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( "20.37.48", "20.40.45", "20.44.38" - // This patch is obsolete with 21.03 because YT seems to have - // removed resuming Shorts functionality. - // TODO: Before adding 21.03+, merge this patch into `Hide Shorts component` ), ) apply { - // 21.03+ seems to no longer have resuming Shorts functionality. - if (is_21_03_or_greater) return@apply - - addResources("youtube", "layout.startupshortsreset.disableResumingShortsOnStartupPatch") + addResources("youtube", "layout.shortsresuming.disableResumingShortsOnStartupPatch") PreferenceScreen.SHORTS.addPreferences( - SwitchPreference("revanced_disable_resuming_shorts_player"), + SwitchPreference("revanced_disable_resuming_shorts_on_startup"), ) - if (is_20_03_or_greater) { - userWasInShortsAlternativeMethodMatch.let { + if (is_21_03_or_greater) { + userWasInShortsEvaluateMethodMatch.let { + it.method.apply { + val instruction = getInstruction(it[0]) + val zMRegister = instruction.startRegister + 2 + + addInstructions( + it[0], + """ + invoke-static { v$zMRegister }, ${EXTENSION_CLASS_DESCRIPTOR}->disableResumingShortsOnStartup(Z)Z + move-result v$zMRegister + """ + ) + } + } + } else if (is_20_03_or_greater) { + userWasInShortsListenerMethodMatch.let { it.method.apply { val insertIndex = it[2] + 1 val register = getInstruction(insertIndex).registerA @@ -69,7 +79,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( addInstructions( insertIndex, """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingShortsOnStartup(Z)Z move-result v$register """, ) @@ -87,7 +97,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( addInstructionsAtControlFlowLabel( listenableInstructionIndex, """ - invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z + invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingShortsOnStartup()Z move-result v$freeRegister if-eqz v$freeRegister, :show_startup_shorts_player return-void @@ -101,7 +111,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( userWasInShortsConfigMethod.addInstructions( 0, """ - invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z + invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingShortsOnStartup()Z move-result v0 if-eqz v0, :show const/4 v0, 0x0 diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/Fingerprints.kt new file mode 100644 index 0000000000..4392f35283 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsresuming/Fingerprints.kt @@ -0,0 +1,79 @@ +package app.revanced.patches.youtube.layout.shortsresuming + +import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import kotlin.collections.all +import kotlin.collections.zip + + +/** + * 21.03+ + */ +internal val BytecodePatchContext.userWasInShortsEvaluateMethodMatch by composingFirstMethod { + val method1ParametersPrefix = listOf("L", "Z", "Z", "L", "Z") + val method2ParametersPrefix = listOf("L", "L", "L", "L", "L", "I") + + instructions( + allOf( + Opcode.INVOKE_DIRECT_RANGE(), + method { + name == "" && parameterTypes.zip(method1ParametersPrefix) + .all { (a, b) -> a.startsWith(b) } + } + ), + afterAtMost( + 50, allOf( + Opcode.INVOKE_DIRECT_RANGE(), + method { + name == "" && parameterTypes.zip(method2ParametersPrefix) + .all { (a, b) -> a.startsWith(b) } + } + ) + ) + ) +} + +/** + * 20.02+ + */ +internal +val BytecodePatchContext.userWasInShortsListenerMethodMatch by composingFirstMethod { + returnType("V") + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameterTypes("Ljava/lang/Object;") + instructions( + allOf(Opcode.CHECK_CAST(), type("Ljava/lang/Boolean;")), + after(method { toString() == "Ljava/lang/Boolean;->booleanValue()Z" }), + after(Opcode.MOVE_RESULT()), + // 20.40+ string was merged into another string and is a partial match. + afterAtMost(30, "ShortsStartup SetUserWasInShortsListener"(String::contains)), + ) +} + +/** + * Pre 20.02 + */ +internal +val BytecodePatchContext.userWasInShortsLegacyMethod by gettingFirstMethodDeclaratively { + returnType("V") + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameterTypes("Ljava/lang/Object;") + instructions( + "Failed to read user_was_in_shorts proto after successful warmup"(), + ) +} + +/** + * 18.15.40+ + */ +internal +val BytecodePatchContext.userWasInShortsConfigMethod by gettingFirstMethodDeclaratively { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returnType("Z") + parameterTypes() + instructions( + 45358360L(), + ) +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt deleted file mode 100644 index 931bff6052..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt +++ /dev/null @@ -1,46 +0,0 @@ -package app.revanced.patches.youtube.layout.startupshortsreset - -import app.revanced.patcher.* -import app.revanced.patcher.patch.BytecodePatchContext -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -/** - * 20.02+ - */ -internal val BytecodePatchContext.userWasInShortsAlternativeMethodMatch by composingFirstMethod { - returnType("V") - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - parameterTypes("Ljava/lang/Object;") - instructions( - allOf(Opcode.CHECK_CAST(), type("Ljava/lang/Boolean;")), - after(method { toString() == "Ljava/lang/Boolean;->booleanValue()Z" }), - after(Opcode.MOVE_RESULT()), - // 20.40+ string was merged into another string and is a partial match. - afterAtMost(15, "userIsInShorts: "(String::contains)), - ) -} - -/** - * Pre 20.02 - */ -internal val BytecodePatchContext.userWasInShortsLegacyMethod by gettingFirstMethodDeclaratively { - returnType("V") - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - parameterTypes("Ljava/lang/Object;") - instructions( - "Failed to read user_was_in_shorts proto after successful warmup"(), - ) -} - -/** - * 18.15.40+ - */ -internal val BytecodePatchContext.userWasInShortsConfigMethod by gettingFirstMethodDeclaratively { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returnType("Z") - parameterTypes() - instructions( - 45358360L(), - ) -} diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 47c483e5c5..ce5c2dd5fc 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -1490,10 +1490,10 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs. Limitation: Using the back button on the toolbar may not work" Start page is changed only on app startup - - Disable resuming Shorts player - Shorts player will not resume on app startup - Shorts player will resume on app startup + + Disable resuming Shorts player + Shorts player will not resume on app startup + Shorts player will resume on app startup Open Shorts with