mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-04 16:44:29 +02:00
fix(YouTube/Return YouTube Dislike): prevent the first Short opened from freezing the UI
This commit is contained in:
parent
f77c62cbad
commit
fa3acf8ffd
@ -18,8 +18,10 @@ import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardR
|
|||||||
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererSpecRecommendedLevelFingerprint
|
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererSpecRecommendedLevelFingerprint
|
||||||
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailFingerprint
|
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailFingerprint
|
||||||
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailParentFingerprint
|
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailParentFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.playerresponse.PlayerResponsePatch
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch
|
||||||
import app.revanced.util.integrations.Constants.MISC_PATH
|
import app.revanced.util.integrations.Constants.MISC_PATH
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
@ -29,6 +31,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|||||||
description = "Spoofs player parameters to prevent playback issues.",
|
description = "Spoofs player parameters to prevent playback issues.",
|
||||||
dependencies = [
|
dependencies = [
|
||||||
PlayerTypeHookPatch::class,
|
PlayerTypeHookPatch::class,
|
||||||
|
PlayerResponsePatch::class,
|
||||||
|
VideoIdPatch::class,
|
||||||
SettingsPatch::class
|
SettingsPatch::class
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
@ -75,19 +79,9 @@ object SpoofPlayerParameterPatch : BytecodePatch(
|
|||||||
/**
|
/**
|
||||||
* Hook player parameter
|
* Hook player parameter
|
||||||
*/
|
*/
|
||||||
PlayerParameterBuilderFingerprint.result?.let {
|
PlayerResponsePatch += PlayerResponsePatch.Hook.PlayerParameter(
|
||||||
it.mutableMethod.apply {
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Z)Ljava/lang/String;"
|
||||||
val videoIdRegister = 1
|
|
||||||
val playerParameterRegister = 3
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
0, """
|
|
||||||
invoke-static {p$videoIdRegister, p$playerParameterRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object p$playerParameterRegister
|
|
||||||
"""
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
} ?: throw PlayerParameterBuilderFingerprint.exception
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces the SeekBar thumbnail preview container to be shown
|
* Forces the SeekBar thumbnail preview container to be shown
|
||||||
|
@ -2,39 +2,58 @@ package app.revanced.patches.youtube.utils.playerresponse
|
|||||||
|
|
||||||
import app.revanced.extensions.exception
|
import app.revanced.extensions.exception
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.PlayerParameterBuilderFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.PlayerParameterBuilderFingerprint
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
object PlayerResponsePatch : BytecodePatch(
|
object PlayerResponsePatch : BytecodePatch(
|
||||||
setOf(PlayerParameterBuilderFingerprint)
|
setOf(PlayerParameterBuilderFingerprint)
|
||||||
) {
|
), Closeable,MutableSet<PlayerResponsePatch.Hook> by mutableSetOf() {
|
||||||
private const val VIDEO_ID_PARAMETER = 1
|
private const val VIDEO_ID_PARAMETER = 1
|
||||||
private const val VIDEO_IS_OPENING_OR_PLAYING_PARAMETER = 11
|
private const val PLAYER_PARAMETER = 3
|
||||||
|
private const val IS_SHORT_AND_OPENING_OR_PLAYING_PARAMETER = 11
|
||||||
|
|
||||||
private lateinit var insertMethod: MutableMethod
|
private lateinit var playerResponseMethod: MutableMethod
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an invoke-static instruction, called with the new id when the video changes
|
|
||||||
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
|
|
||||||
*/
|
|
||||||
internal fun injectCall(
|
|
||||||
methodDescriptor: String
|
|
||||||
) {
|
|
||||||
insertMethod.addInstructions(
|
|
||||||
0, // move-result-object offset
|
|
||||||
"invoke-static {p$VIDEO_ID_PARAMETER, p$VIDEO_IS_OPENING_OR_PLAYING_PARAMETER}, $methodDescriptor"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
playerResponseMethod = PlayerParameterBuilderFingerprint.result?.mutableMethod
|
||||||
PlayerParameterBuilderFingerprint.result?.let {
|
?: throw PlayerParameterBuilderFingerprint.exception
|
||||||
insertMethod = it.mutableMethod
|
|
||||||
} ?: throw PlayerParameterBuilderFingerprint.exception
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
fun hookVideoId(hook: Hook) = playerResponseMethod.addInstruction(
|
||||||
|
0,
|
||||||
|
"invoke-static {p$VIDEO_ID_PARAMETER, p$IS_SHORT_AND_OPENING_OR_PLAYING_PARAMETER}, $hook"
|
||||||
|
)
|
||||||
|
|
||||||
|
fun hookPlayerParameter(hook: Hook) = playerResponseMethod.addInstructions(
|
||||||
|
0, """
|
||||||
|
invoke-static {p$PLAYER_PARAMETER, p$IS_SHORT_AND_OPENING_OR_PLAYING_PARAMETER}, $hook
|
||||||
|
move-result-object p$PLAYER_PARAMETER
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reverse the order in order to preserve insertion order of the hooks.
|
||||||
|
val beforeVideoIdHooks = filterIsInstance<Hook.PlayerBeforeVideoId>().asReversed()
|
||||||
|
val videoIdHooks = filterIsInstance<Hook.VideoId>().asReversed()
|
||||||
|
val afterVideoIdHooks = filterIsInstance<Hook.PlayerParameter>().asReversed()
|
||||||
|
|
||||||
|
// Add the hooks in this specific order as they insert instructions at the beginning of the method.
|
||||||
|
afterVideoIdHooks.forEach(::hookPlayerParameter)
|
||||||
|
videoIdHooks.forEach(::hookVideoId)
|
||||||
|
beforeVideoIdHooks.forEach(::hookPlayerParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class Hook(private val methodDescriptor: String) {
|
||||||
|
internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor)
|
||||||
|
|
||||||
|
internal class PlayerParameter(methodDescriptor: String) : Hook(methodDescriptor)
|
||||||
|
internal class PlayerBeforeVideoId(methodDescriptor: String) : Hook(methodDescriptor)
|
||||||
|
|
||||||
|
override fun toString() = methodDescriptor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +101,14 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
|
|
||||||
|
|
||||||
TextComponentConstructorFingerprint.result?.let { parentResult ->
|
TextComponentConstructorFingerprint.result?.let { parentResult ->
|
||||||
|
// Resolves fingerprints
|
||||||
|
val parentClassDef = parentResult.classDef
|
||||||
|
TextComponentContextFingerprint.resolve(context, parentClassDef)
|
||||||
|
TextComponentTmpFingerprint.resolve(context, parentClassDef)
|
||||||
|
TextComponentAtomicReferenceFingerprint.resolve(context, parentClassDef)
|
||||||
|
TextComponentAtomicReferenceLegacyFingerprint.resolve(context, parentClassDef)
|
||||||
|
|
||||||
TextComponentContextFingerprint.also {
|
TextComponentContextFingerprint.result?.let {
|
||||||
it.resolve(
|
|
||||||
context,
|
|
||||||
parentResult.classDef
|
|
||||||
)
|
|
||||||
}.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val booleanIndex = it.scanResult.patternScanResult!!.endIndex
|
val booleanIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
|
|
||||||
@ -127,12 +128,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
} ?: throw TextComponentContextFingerprint.exception
|
} ?: throw TextComponentContextFingerprint.exception
|
||||||
|
|
||||||
TextComponentTmpFingerprint.also {
|
TextComponentTmpFingerprint.result?.let {
|
||||||
it.resolve(
|
|
||||||
context,
|
|
||||||
parentResult.classDef
|
|
||||||
)
|
|
||||||
}.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
tmpRegister =
|
tmpRegister =
|
||||||
@ -142,17 +138,11 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
|
|
||||||
|
|
||||||
val textComponentAtomicReferenceResult =
|
val textComponentAtomicReferenceResult =
|
||||||
TextComponentAtomicReferenceFingerprint.also {
|
TextComponentAtomicReferenceFingerprint.result
|
||||||
it.resolve(context, parentResult.classDef)
|
?: TextComponentAtomicReferenceLegacyFingerprint.result
|
||||||
}.result
|
|
||||||
?: TextComponentAtomicReferenceLegacyFingerprint.also {
|
|
||||||
it.resolve(context, parentResult.classDef)
|
|
||||||
}.result
|
|
||||||
?: throw TextComponentAtomicReferenceLegacyFingerprint.exception
|
?: throw TextComponentAtomicReferenceLegacyFingerprint.exception
|
||||||
|
|
||||||
TextComponentAtomicReferenceFingerprint.also {
|
TextComponentAtomicReferenceFingerprint.result?.let {
|
||||||
it.resolve(context, parentResult.classDef)
|
|
||||||
}.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
val originalRegisterA =
|
val originalRegisterA =
|
||||||
@ -196,14 +186,14 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
} ?: throw TextComponentConstructorFingerprint.exception
|
} ?: throw TextComponentConstructorFingerprint.exception
|
||||||
|
|
||||||
|
VideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
||||||
|
VideoIdPatch.injectPlayerResponseVideoId("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->preloadVideoId(Ljava/lang/String;Z)V")
|
||||||
|
|
||||||
if (SettingsPatch.upward1834) {
|
if (SettingsPatch.upward1834) {
|
||||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||||
PlayerResponsePatch.injectCall("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
VideoIdPatch.injectPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerResponsePatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->preloadVideoId(Ljava/lang/String;Z)V")
|
|
||||||
VideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add ReVanced Extended Settings
|
* Add ReVanced Extended Settings
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +13,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.OrganicPlaybackContextModelFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.OrganicPlaybackContextModelFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.playerresponse.PlayerResponsePatch
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.utils.videoid.general.fingerprint.PlayerControllerSetTimeReferenceFingerprint
|
import app.revanced.patches.youtube.utils.videoid.general.fingerprint.PlayerControllerSetTimeReferenceFingerprint
|
||||||
import app.revanced.patches.youtube.utils.videoid.general.fingerprint.VideoEndFingerprint
|
import app.revanced.patches.youtube.utils.videoid.general.fingerprint.VideoEndFingerprint
|
||||||
@ -27,7 +28,12 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
|||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
@Patch(dependencies = [PlayerTypeHookPatch::class])
|
@Patch(
|
||||||
|
dependencies = [
|
||||||
|
PlayerTypeHookPatch::class,
|
||||||
|
PlayerResponsePatch::class
|
||||||
|
]
|
||||||
|
)
|
||||||
object VideoIdPatch : BytecodePatch(
|
object VideoIdPatch : BytecodePatch(
|
||||||
setOf(
|
setOf(
|
||||||
OrganicPlaybackContextModelFingerprint,
|
OrganicPlaybackContextModelFingerprint,
|
||||||
@ -144,8 +150,12 @@ object VideoIdPatch : BytecodePatch(
|
|||||||
} ?: throw VideoIdFingerprint.exception
|
} ?: throw VideoIdFingerprint.exception
|
||||||
} ?: throw VideoIdParentFingerprint.exception
|
} ?: throw VideoIdParentFingerprint.exception
|
||||||
|
|
||||||
injectCall("$VIDEO_PATH/VideoInformation;->setVideoId(Ljava/lang/String;)V")
|
injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V")
|
||||||
|
injectPlayerResponseVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
||||||
|
// Call before any other video id hooks,
|
||||||
|
// so they can use VideoInformation and check if the video id is for a Short.
|
||||||
|
PlayerResponsePatch += PlayerResponsePatch.Hook.PlayerBeforeVideoId(
|
||||||
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseSignature(Ljava/lang/String;Z)Ljava/lang/String;")
|
||||||
}
|
}
|
||||||
|
|
||||||
const val INTEGRATIONS_CLASS_DESCRIPTOR = "$VIDEO_PATH/VideoInformation;"
|
const val INTEGRATIONS_CLASS_DESCRIPTOR = "$VIDEO_PATH/VideoInformation;"
|
||||||
@ -173,6 +183,34 @@ object VideoIdPatch : BytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks the video id of every video when loaded.
|
||||||
|
* Supports all videos and functions in all situations.
|
||||||
|
*
|
||||||
|
* First parameter is the video id.
|
||||||
|
* Second parameter is if the video is a Short AND it is being opened or is currently playing.
|
||||||
|
*
|
||||||
|
* Hook is always called off the main thread.
|
||||||
|
*
|
||||||
|
* This hook is called as soon as the player response is parsed,
|
||||||
|
* and called before many other hooks are updated such as [PlayerTypeHookPatch].
|
||||||
|
*
|
||||||
|
* Note: The video id returned here may not be the current video that's being played.
|
||||||
|
* It's common for multiple Shorts to load at once in preparation
|
||||||
|
* for the user swiping to the next Short.
|
||||||
|
*
|
||||||
|
* Be aware, this can be called multiple times for the same video id.
|
||||||
|
*
|
||||||
|
* @param methodDescriptor which method to call. Params must be `Ljava/lang/String;Z`
|
||||||
|
*/
|
||||||
|
internal fun injectPlayerResponseVideoId(
|
||||||
|
methodDescriptor: String
|
||||||
|
) {
|
||||||
|
PlayerResponsePatch += PlayerResponsePatch.Hook.VideoId(
|
||||||
|
methodDescriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
|
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
|
||||||
addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
|
addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user