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:
parent
53318c48ee
commit
58898b92fe
7 changed files with 130 additions and 87 deletions
|
|
@ -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
|
||||
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue