fix(YouTube - Disable Shorts resuming on startup): Resolve patch not working on experimental versions

Co-authored-by: ILoveOpenSourceApplications <117499019+iloveopensourceapplications@users.noreply.github.com>
This commit is contained in:
oSumAtrIX 2026-03-21 19:37:50 +01:00
parent 53318c48ee
commit 58898b92fe
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
7 changed files with 130 additions and 87 deletions

View file

@ -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<RegisterRangeInstruction>(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<OneRegisterInstruction>(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

View file

@ -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 == "<init>" && parameterTypes.zip(method1ParametersPrefix)
.all { (a, b) -> a.startsWith(b) }
}
),
afterAtMost(
50, allOf(
Opcode.INVOKE_DIRECT_RANGE(),
method {
name == "<init>" && 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(),
)
}

View file

@ -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(),
)
}

View file

@ -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"</string>
<string name="revanced_change_start_page_always_summary_off">Start page is changed only on app startup</string>
</patch>
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
<string name="revanced_disable_resuming_shorts_player_title">Disable resuming Shorts player</string>
<string name="revanced_disable_resuming_shorts_player_summary_on">Shorts player will not resume on app startup</string>
<string name="revanced_disable_resuming_shorts_player_summary_off">Shorts player will resume on app startup</string>
<patch id="layout.shortsresuming.disableResumingShortsOnStartupPatch">
<string name="revanced_disable_resuming_shorts_on_startup_title">Disable resuming Shorts player</string>
<string name="revanced_disable_resuming_shorts_on_startup_summary_on">Shorts player will not resume on app startup</string>
<string name="revanced_disable_resuming_shorts_on_startup_summary_off">Shorts player will resume on app startup</string>
</patch>
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
<string name="revanced_shorts_player_type_title">Open Shorts with</string>