mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-06-12 05:07:41 +02:00
feat(YouTube): add support versions 19.19.39 ~ 19.20.34
This commit is contained in:
@ -8,10 +8,12 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patches.shared.customspeed.fingerprints.SpeedArrayGeneratorFingerprint
|
||||
import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFallBackFingerprint
|
||||
import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFingerprint
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexWithFieldReferenceType
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@ -71,7 +73,7 @@ abstract class BaseCustomPlaybackSpeedPatch(
|
||||
val limiterMinConstIndex =
|
||||
indexOfFirstInstruction { (this as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() }
|
||||
val limiterMaxConstIndex =
|
||||
indexOfFirstInstruction { (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() }
|
||||
getTargetIndex(limiterMinConstIndex + 1, Opcode.CONST_HIGH16)
|
||||
|
||||
val limiterMinConstDestination =
|
||||
getInstruction<OneRegisterInstruction>(limiterMinConstIndex).registerA
|
||||
|
@ -79,21 +79,24 @@ object TabletMiniPlayerPatch : BaseBytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
// In ModernMiniPlayer, the drawables of the close button and expand button are reversed.
|
||||
// OnClickListener appears to be applied normally, so this appears to be a bug in YouTube.
|
||||
// To solve this, swap the drawables of the close and expand buttons.
|
||||
// This Drawable will be used in multiple Classes, so instead of using LiteralValueFingerprint to patch only specific methods,
|
||||
// Apply the patch to all methods where literals are used.
|
||||
mapOf(
|
||||
YtOutlineXWhite to "replaceCloseButtonDrawableId",
|
||||
YtOutlinePiPWhite to "replaceExpandButtonDrawableId"
|
||||
).forEach { (literal, methodName) ->
|
||||
val smaliInstruction = """
|
||||
// This issue has been fixed in YouTube 19.17.41+.
|
||||
if (YtOutlineXWhite != -1L && YtOutlinePiPWhite != -1L) {
|
||||
// In ModernMiniPlayer, the drawables of the close button and expand button are reversed.
|
||||
// OnClickListener appears to be applied normally, so this appears to be a bug in YouTube.
|
||||
// To solve this, swap the drawables of the close and expand buttons.
|
||||
// This Drawable will be used in multiple Classes, so instead of using LiteralValueFingerprint to patch only specific methods,
|
||||
// Apply the patch to all methods where literals are used.
|
||||
mapOf(
|
||||
YtOutlineXWhite to "replaceCloseButtonDrawableId",
|
||||
YtOutlinePiPWhite to "replaceExpandButtonDrawableId"
|
||||
).forEach { (literal, methodName) ->
|
||||
val smaliInstruction = """
|
||||
invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $GENERAL_CLASS_DESCRIPTOR->$methodName(I)I
|
||||
move-result v$REGISTER_TEMPLATE_REPLACEMENT
|
||||
"""
|
||||
|
||||
context.literalInstructionHook(literal, smaliInstruction)
|
||||
context.literalInstructionHook(literal, smaliInstruction)
|
||||
}
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
|
@ -16,20 +16,21 @@ import app.revanced.patches.youtube.player.buttons.fingerprints.YouTubeControlsO
|
||||
import app.revanced.patches.youtube.utils.castbutton.CastButtonPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.fingerprints.LayoutConstructorFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.fullscreen.FullscreenButtonViewStubPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AutoNavToggle
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenButton
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PlayerCollapseButton
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexWithReference
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
|
||||
|
||||
@Suppress("unused")
|
||||
@ -38,6 +39,7 @@ object PlayerButtonsPatch : BaseBytecodePatch(
|
||||
description = "Adds an option to hide buttons in the video player.",
|
||||
dependencies = setOf(
|
||||
CastButtonPatch::class,
|
||||
FullscreenButtonViewStubPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
@ -147,16 +149,22 @@ object PlayerButtonsPatch : BaseBytecodePatch(
|
||||
|
||||
FullScreenButtonFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val viewIndex = getTargetIndexWithReference("Landroid/widget/ImageView;->getResources()Landroid/content/res/Resources;")
|
||||
val viewRegister = getInstruction<FiveRegisterInstruction>(viewIndex).registerC
|
||||
val buttonCalls = implementation!!.instructions.withIndex()
|
||||
.filter { instruction ->
|
||||
(instruction.value as? WideLiteralInstruction)?.wideLiteral == FullScreenButton
|
||||
}
|
||||
val constIndex = buttonCalls.elementAt(buttonCalls.size - 1).index
|
||||
val castIndex = getTargetIndex(constIndex, Opcode.CHECK_CAST)
|
||||
val insertIndex = castIndex + 1
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(castIndex).registerA
|
||||
|
||||
addInstructionsWithLabels(
|
||||
viewIndex, """
|
||||
invoke-static {v$viewRegister}, $PLAYER_CLASS_DESCRIPTOR->hideFullscreenButton(Landroid/widget/ImageView;)Landroid/widget/ImageView;
|
||||
move-result-object v$viewRegister
|
||||
if-nez v$viewRegister, :show
|
||||
insertIndex, """
|
||||
invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->hideFullscreenButton(Landroid/widget/ImageView;)Landroid/widget/ImageView;
|
||||
move-result-object v$insertRegister
|
||||
if-nez v$insertRegister, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(viewIndex))
|
||||
""", ExternalLabel("show", getInstruction(insertIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package app.revanced.patches.youtube.player.buttons.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CfFullscreenButton
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FadeDurationFast
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenButton
|
||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||
@ -11,8 +12,11 @@ internal object FullScreenButtonFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/view/View;"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.containsWideLiteralInstructionIndex(FadeDurationFast)
|
||||
&& methodDef.containsWideLiteralInstructionIndex(FullScreenButton)
|
||||
customFingerprint = handler@{ methodDef, _ ->
|
||||
if (!methodDef.containsWideLiteralInstructionIndex(FullScreenButton))
|
||||
return@handler false
|
||||
|
||||
methodDef.containsWideLiteralInstructionIndex(FadeDurationFast) // YouTube 18.29.38 ~ YouTube 19.18.41
|
||||
|| methodDef.containsWideLiteralInstructionIndex(CfFullscreenButton) // YouTube 19.19.39 ~
|
||||
},
|
||||
)
|
@ -20,14 +20,12 @@ import app.revanced.patches.youtube.player.components.fingerprints.InfoCardsInco
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.LayoutCircleFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.LayoutIconFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.LayoutVideoFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.RestoreSlideToSeekBehaviorFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.SeekEduContainerFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.SpeedOverlayFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.SpeedOverlayValueFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.SuggestedActionsFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.TouchAreaOnClickListenerFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.WatermarkFingerprint
|
||||
import app.revanced.patches.youtube.player.components.fingerprints.WatermarkParentFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.SpeedOverlayPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.controlsoverlay.ControlsOverlayConfigPatch
|
||||
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
|
||||
@ -44,7 +42,6 @@ import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexReversed
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.literalInstructionBooleanHook
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@ -64,6 +61,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
PlayerTypeHookPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class,
|
||||
SpeedOverlayPatch::class,
|
||||
SuggestedVideoEndScreenPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
@ -75,10 +73,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
LayoutCircleFingerprint,
|
||||
LayoutIconFingerprint,
|
||||
LayoutVideoFingerprint,
|
||||
RestoreSlideToSeekBehaviorFingerprint,
|
||||
SeekEduContainerFingerprint,
|
||||
SpeedOverlayFingerprint,
|
||||
SpeedOverlayValueFingerprint,
|
||||
SuggestedActionsFingerprint,
|
||||
TouchAreaOnClickListenerFingerprint,
|
||||
WatermarkParentFingerprint,
|
||||
@ -131,34 +126,6 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for disable speed overlay and speed overlay value
|
||||
|
||||
mapOf(
|
||||
RestoreSlideToSeekBehaviorFingerprint to 45411329,
|
||||
SpeedOverlayFingerprint to 45411330
|
||||
).forEach { (fingerprint, literal) ->
|
||||
fingerprint.literalInstructionBooleanHook(
|
||||
literal,
|
||||
"$PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
SpeedOverlayValueFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val index = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide channel watermark
|
||||
|
||||
WatermarkFingerprint.resolve(
|
||||
|
@ -16,6 +16,7 @@ import app.revanced.patches.youtube.player.flyoutmenu.toggle.fingerprints.Stable
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexReversed
|
||||
@ -26,6 +27,8 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Suppress("unused")
|
||||
object ChangeTogglePatch : BaseBytecodePatch(
|
||||
@ -123,6 +126,12 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
||||
|
||||
CinematicLightingFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val iGetIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET
|
||||
&& getReference<FieldReference>()?.definingClass == definingClass
|
||||
}
|
||||
val classRegister = getInstruction<TwoRegisterInstruction>(iGetIndex).registerB
|
||||
|
||||
val stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting")
|
||||
|
||||
val checkCastIndex = getTargetIndexReversed(stringIndex, Opcode.CHECK_CAST)
|
||||
@ -158,7 +167,7 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
||||
invoke-static {v$freeRegisterE}, $PLAYER_CLASS_DESCRIPTOR->getToggleString(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$freeRegisterE
|
||||
:set_string
|
||||
iget-object v$freeRegisterC, p0, $iGetObjectPrimaryReference
|
||||
iget-object v$freeRegisterC, v$classRegister, $iGetObjectPrimaryReference
|
||||
check-cast v$freeRegisterC, $checkCastReference
|
||||
iget-object v$freeRegisterC, v$freeRegisterC, $iGetObjectSecondaryReference
|
||||
const-string v$freeRegisterD, "menu_item_cinematic_lighting"
|
||||
|
@ -0,0 +1,224 @@
|
||||
package app.revanced.patches.youtube.player.speedoverlay
|
||||
|
||||
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.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.HorizontalTouchOffsetConstructorFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.NextGenWatchLayoutFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.RestoreSlideToSeekBehaviorFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SlideToSeekMotionEventFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayTextValueFingerprint
|
||||
import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayValueFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexReversed
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceNameReversed
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.literalInstructionBooleanHook
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch(dependencies = [SharedResourceIdPatch::class])
|
||||
object SpeedOverlayPatch : BytecodePatch(
|
||||
setOf(
|
||||
HorizontalTouchOffsetConstructorFingerprint,
|
||||
NextGenWatchLayoutFingerprint,
|
||||
RestoreSlideToSeekBehaviorFingerprint,
|
||||
SpeedOverlayFingerprint,
|
||||
SpeedOverlayTextValueFingerprint,
|
||||
SpeedOverlayValueFingerprint,
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
val restoreSlideToSeekBehaviorFingerprintResult = RestoreSlideToSeekBehaviorFingerprint.result
|
||||
val speedOverlayFingerprintResult = SpeedOverlayFingerprint.result
|
||||
val speedOverlayValueFingerprintResult = SpeedOverlayValueFingerprint.result
|
||||
|
||||
val resolvable =
|
||||
restoreSlideToSeekBehaviorFingerprintResult != null
|
||||
&& speedOverlayFingerprintResult != null
|
||||
&& speedOverlayValueFingerprintResult != null
|
||||
|
||||
if (resolvable) {
|
||||
// Legacy method.
|
||||
// Used on YouTube 18.29.38 ~ YouTube 19.17.41
|
||||
|
||||
// region patch for disable speed overlay
|
||||
|
||||
mapOf(
|
||||
RestoreSlideToSeekBehaviorFingerprint to 45411329,
|
||||
SpeedOverlayFingerprint to 45411330
|
||||
).forEach { (fingerprint, literal) ->
|
||||
fingerprint.result!!.let {
|
||||
fingerprint.literalInstructionBooleanHook(
|
||||
literal,
|
||||
"$PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay(Z)Z"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for custom speed overlay value
|
||||
|
||||
speedOverlayValueFingerprintResult!!.let {
|
||||
it.mutableMethod.apply {
|
||||
val index = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
} else {
|
||||
// New method.
|
||||
// Used on YouTube 19.18.41~
|
||||
|
||||
NextGenWatchLayoutFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val booleanValueIndex = getTargetIndexWithMethodReferenceName("booleanValue")
|
||||
|
||||
val insertIndex = findIGetIndex(booleanValueIndex - 10, booleanValueIndex)
|
||||
val insertInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
|
||||
val insertReference = getInstruction<ReferenceInstruction>(insertIndex).reference
|
||||
|
||||
addInstruction(
|
||||
insertIndex + 1,
|
||||
"iget-object v${insertInstruction.registerA}, v${insertInstruction.registerB}, $insertReference"
|
||||
)
|
||||
|
||||
val jumpIndex = findIGetIndex(booleanValueIndex, booleanValueIndex + 10)
|
||||
|
||||
hook(insertIndex + 1, insertInstruction.registerA, jumpIndex)
|
||||
}
|
||||
|
||||
SlideToSeekMotionEventFingerprint.resolve(
|
||||
context,
|
||||
HorizontalTouchOffsetConstructorFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
SlideToSeekMotionEventFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val scanResult = it.scanResult.patternScanResult!!
|
||||
|
||||
val slideToSeekBooleanIndex = scanResult.startIndex + 1
|
||||
slideToSeekBooleanMethod = getWalkerMethod(context, slideToSeekBooleanIndex)
|
||||
|
||||
val jumpIndex = scanResult.endIndex + 1
|
||||
val insertIndex = scanResult.endIndex - 1
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
hook(insertIndex, insertRegister, jumpIndex)
|
||||
}
|
||||
}
|
||||
|
||||
slideToSeekBooleanMethod.apply {
|
||||
var insertIndex = getTargetIndex(Opcode.IGET_OBJECT)
|
||||
var insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
var jumpIndex = getTargetIndexReversed(Opcode.INVOKE_VIRTUAL)
|
||||
|
||||
hook(insertIndex, insertRegister, jumpIndex)
|
||||
|
||||
val constructorMethod =
|
||||
context.findClass(definingClass)?.mutableClass
|
||||
?.methods?.find { method -> method.name == "<init>" }
|
||||
?: throw PatchException("Could not find constructor method")
|
||||
|
||||
constructorMethod.apply {
|
||||
val syntheticIndex = getTargetIndexReversed(Opcode.NEW_INSTANCE)
|
||||
val syntheticClass = getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
|
||||
|
||||
val syntheticMethod =
|
||||
context.findClass(syntheticClass)?.mutableClass
|
||||
?.methods?.find { method -> method.name == "run" }
|
||||
?: throw PatchException("Could not find synthetic method")
|
||||
|
||||
syntheticMethod.apply {
|
||||
val speedOverlayValueIndex =
|
||||
indexOfFirstInstruction { (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() }
|
||||
val speedOverlayValueRegister =
|
||||
getInstruction<OneRegisterInstruction>(speedOverlayValueIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
speedOverlayValueIndex + 1, """
|
||||
invoke-static {v$speedOverlayValueRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F
|
||||
move-result v$speedOverlayValueRegister
|
||||
"""
|
||||
)
|
||||
|
||||
insertIndex = getTargetIndexWithMethodReferenceNameReversed(speedOverlayValueIndex, "removeCallbacks") + 1
|
||||
insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex - 1).registerC
|
||||
jumpIndex = getTargetIndex(speedOverlayValueIndex, Opcode.RETURN_VOID) + 1
|
||||
hook(insertIndex, insertRegister, jumpIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpeedOverlayTextValueFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1, """
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue()D
|
||||
move-result-wide v$targetRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var slideToSeekBooleanMethod: MutableMethod
|
||||
|
||||
// restore slide to seek
|
||||
private fun MutableMethod.hook(
|
||||
insertIndex: Int,
|
||||
insertRegister: Int,
|
||||
jumpIndex: Int
|
||||
) {
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay()Z
|
||||
move-result v$insertRegister
|
||||
if-eqz v$insertRegister, :disable
|
||||
""", ExternalLabel("disable", getInstruction(jumpIndex))
|
||||
)
|
||||
}
|
||||
|
||||
private fun MutableMethod.findIGetIndex(
|
||||
startIndex: Int,
|
||||
endIndex: Int
|
||||
): Int = implementation!!.instructions.let { instruction ->
|
||||
startIndex + instruction.subList(startIndex, endIndex).indexOfFirst {
|
||||
it.opcode == Opcode.IGET_OBJECT
|
||||
&& it.getReference<FieldReference>()?.definingClass == definingClass
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SeekEasyHorizontalTouchOffsetToStartScrubbing
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object HorizontalTouchOffsetConstructorFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
literalSupplier = { SeekEasyHorizontalTouchOffsetToStartScrubbing }
|
||||
)
|
@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.util.containsMethodReferenceNameInstructionIndex
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object NextGenWatchLayoutFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = emptyList(),
|
||||
customFingerprint = handler@{ methodDef, _ ->
|
||||
if (methodDef.definingClass != "Lcom/google/android/apps/youtube/app/watch/nextgenwatch/ui/NextGenWatchLayout;")
|
||||
return@handler false
|
||||
|
||||
methodDef.containsMethodReferenceNameInstructionIndex("booleanValue")
|
||||
}
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.player.components.fingerprints
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object SlideToSeekMotionEventFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/view/View;", "Landroid/view/MotionEvent;"),
|
||||
opcodes = listOf(
|
||||
Opcode.SUB_FLOAT_2ADDR,
|
||||
Opcode.INVOKE_VIRTUAL, // SlideToSeek Boolean method
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.IGET_OBJECT, // insert index
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.player.components.fingerprints
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.fingerprint.ReferenceFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object SpeedOverlayTextValueFingerprint : ReferenceFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
parameters = emptyList(),
|
||||
opcodes = listOf(Opcode.CONST_WIDE_HIGH16),
|
||||
reference = { "Ljava/math/BigDecimal;->signum()I" }
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.player.components.fingerprints
|
||||
package app.revanced.patches.youtube.player.speedoverlay.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -28,6 +28,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelD
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelDynShare
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelForcedMuteButton
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelPivotButton
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelPlayerFooter
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightDislikeIcon
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightLikeIcon
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.RightComment
|
||||
@ -44,6 +45,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Suppress("unused")
|
||||
@ -150,8 +152,14 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
}
|
||||
} ?: ShortsPivotFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getWideLiteralInstructionIndex(ReelPivotButton)
|
||||
val constCalls = implementation!!.instructions.withIndex()
|
||||
.filter { instruction ->
|
||||
(instruction.value as? WideLiteralInstruction)?.wideLiteral == ReelPivotButton
|
||||
}
|
||||
val targetIndex = constCalls.elementAt(constCalls.size - 1).index
|
||||
val insertIndex = getTargetIndexReversed(targetIndex, Opcode.INVOKE_STATIC) + 1
|
||||
if (insertIndex == 0)
|
||||
throw PatchException("insert index not found")
|
||||
|
||||
hideButtons(insertIndex, "hideShortsSoundButton(Ljava/lang/Object;)Ljava/lang/Object;")
|
||||
}
|
||||
@ -215,7 +223,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
lateinit var subscriptionFieldReference: FieldReference
|
||||
|
||||
parentResult.mutableMethod.apply {
|
||||
val targetIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.ReelPlayerFooter) - 1
|
||||
val targetIndex = getWideLiteralInstructionIndex(ReelPlayerFooter) - 1
|
||||
subscriptionFieldReference =
|
||||
(getInstruction<ReferenceInstruction>(targetIndex)).reference as FieldReference
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ object ShortsNavigationBarPatch : BytecodePatch(
|
||||
}
|
||||
|
||||
RenderBottomNavigationBarFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
|
||||
walkerMethod.addInstruction(
|
||||
0,
|
||||
|
@ -4,13 +4,10 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object RenderBottomNavigationBarFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
returnType = "Landroid/view/View;",
|
||||
opcodes = listOf(
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
),
|
||||
strings = listOf("r_ipl")
|
||||
strings = listOf("r_pfcv")
|
||||
)
|
@ -1,9 +1,20 @@
|
||||
package app.revanced.patches.youtube.shorts.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelPivotButton
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
|
||||
internal object ShortsPivotFingerprint : LiteralValueFingerprint(
|
||||
internal object ShortsPivotFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
literalSupplier = { ReelPivotButton }
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
if (!methodDef.containsWideLiteralInstructionIndex(ReelPivotButton))
|
||||
return@custom false
|
||||
|
||||
if (!SettingsPatch.upward1912)
|
||||
return@custom true
|
||||
|
||||
methodDef.getStringInstructionIndex("RHS is rendered through element view for Ads") > 0
|
||||
}
|
||||
)
|
@ -7,12 +7,12 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints.UserWasInShortsABConfigFingerprint
|
||||
import app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints.UserWasInShortsABConfigFingerprint.indexOfOptionalInstruction
|
||||
import app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints.UserWasInShortsFingerprint
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
@ -20,7 +20,6 @@ import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Suppress("unused")
|
||||
@ -36,23 +35,34 @@ object ResumingShortsOnStartupPatch : BaseBytecodePatch(
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
UserWasInShortsABConfigFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
||||
UserWasInShortsABConfigFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val startIndex = indexOfOptionalInstruction(this)
|
||||
val walkerIndex = implementation!!.instructions.let {
|
||||
val subListIndex = it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
|
||||
val reference = instruction.getReference<MethodReference>()
|
||||
instruction.opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& reference?.returnType == "Z"
|
||||
&& reference.definingClass != "Lj${'$'}/util/Optional;"
|
||||
&& reference.parameterTypes.size == 0
|
||||
}
|
||||
if (subListIndex < 0)
|
||||
throw PatchException("subListIndex not found")
|
||||
|
||||
startIndex + subListIndex
|
||||
}
|
||||
val walkerMethod = getWalkerMethod(context, walkerIndex)
|
||||
|
||||
// This method will only be called for the user being A/B tested.
|
||||
// Presumably a method that processes the ProtoDataStore value (boolean) for the 'user_was_in_shorts' key.
|
||||
walkerMethod.apply {
|
||||
val insertIndex = getTargetIndex(Opcode.IGET_OBJECT)
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
0, """
|
||||
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
||||
move-result v$insertRegister
|
||||
if-eqz v$insertRegister, :show
|
||||
const/4 v$insertRegister, 0x0
|
||||
return v$insertRegister
|
||||
""", ExternalLabel("show", getInstruction(insertIndex))
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,26 @@
|
||||
package app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints.UserWasInShortsABConfigFingerprint.indexOfOptionalInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
/**
|
||||
* This fingerprint is compatible with all YouTube versions after v18.15.40.
|
||||
*/
|
||||
internal object UserWasInShortsABConfigFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
),
|
||||
strings = listOf("Failed to get offline response: ")
|
||||
)
|
||||
strings = listOf("Failed to get offline response: "),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
indexOfOptionalInstruction(methodDef) >= 0
|
||||
}
|
||||
) {
|
||||
fun indexOfOptionalInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_STATIC
|
||||
&& getReference<MethodReference>().toString() == "Lj${'$'}/util/Optional;->of(Ljava/lang/Object;)Lj${'$'}/util/Optional;"
|
||||
}
|
||||
}
|
@ -12,7 +12,9 @@ object Constants {
|
||||
"18.38.44",
|
||||
"18.48.39",
|
||||
"19.05.36",
|
||||
"19.16.39"
|
||||
"19.16.39",
|
||||
"19.19.39",
|
||||
"19.20.34",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.youtube.utils.fix.fullscreen.fingerprints.FullscreenButtonPositionFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.fullscreen.fingerprints.FullscreenButtonViewStubFingerprint
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
@ -15,7 +16,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
description = "Fixes an issue where overlay button patches were broken by the new layout."
|
||||
)
|
||||
object FullscreenButtonViewStubPatch : BytecodePatch(
|
||||
setOf(FullscreenButtonViewStubFingerprint)
|
||||
setOf(
|
||||
FullscreenButtonPositionFingerprint,
|
||||
FullscreenButtonViewStubFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
@ -23,15 +27,20 @@ object FullscreenButtonViewStubPatch : BytecodePatch(
|
||||
* This issue only affects some versions of YouTube.
|
||||
* Therefore, this patch only applies to versions that can resolve this fingerprint.
|
||||
*/
|
||||
FullscreenButtonViewStubFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(45617294), Opcode.MOVE_RESULT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
mapOf(
|
||||
FullscreenButtonViewStubFingerprint to 45617294,
|
||||
FullscreenButtonPositionFingerprint to 45627640
|
||||
).forEach { (fingerprint, literalValue) ->
|
||||
fingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(literalValue.toLong()), Opcode.MOVE_RESULT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"const/4 v$targetRegister, 0x0"
|
||||
)
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"const/4 v$targetRegister, 0x0"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.youtube.utils.fix.fullscreen.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
internal object FullscreenButtonPositionFingerprint : LiteralValueFingerprint(
|
||||
returnType = "Z",
|
||||
literalSupplier = { 45627640 }
|
||||
)
|
@ -34,6 +34,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
||||
var BottomUiContainerStub = -1L
|
||||
var CaptionToggleContainer = -1L
|
||||
var CastMediaRouteButton = -1L
|
||||
var CfFullscreenButton = -1L
|
||||
var ChannelListSubMenu = -1L
|
||||
var CompactLink = -1L
|
||||
var CompactListItem = -1L
|
||||
@ -83,6 +84,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
||||
var RightComment = -1L
|
||||
var ScrimOverlay = -1L
|
||||
var Scrubbing = -1L
|
||||
var SeekEasyHorizontalTouchOffsetToStartScrubbing = -1L
|
||||
var SeekUndoEduOverlayStub = -1L
|
||||
var SingleLoopEduSnackBarText = -1L
|
||||
var SlidingDialogAnimation = -1L
|
||||
@ -121,6 +123,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
||||
BottomUiContainerStub = getId(ID, "bottom_ui_container_stub")
|
||||
CaptionToggleContainer = getId(ID, "caption_toggle_container")
|
||||
CastMediaRouteButton = getId(LAYOUT, "castmediaroutebutton")
|
||||
CfFullscreenButton = getId(ID, "cf_fullscreen_button")
|
||||
ChannelListSubMenu = getId(LAYOUT, "channel_list_sub_menu")
|
||||
CompactLink = getId(LAYOUT, "compact_link")
|
||||
CompactListItem = getId(LAYOUT, "compact_list_item")
|
||||
@ -172,6 +175,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
||||
RightComment = getId(DRAWABLE, "ic_right_comment_32c")
|
||||
ScrimOverlay = getId(ID, "scrim_overlay")
|
||||
Scrubbing = getId(DIMEN, "vertical_touch_offset_to_enter_fine_scrubbing")
|
||||
SeekEasyHorizontalTouchOffsetToStartScrubbing = getId(DIMEN, "seek_easy_horizontal_touch_offset_to_start_scrubbing")
|
||||
SeekUndoEduOverlayStub = getId(ID, "seek_undo_edu_overlay_stub")
|
||||
SingleLoopEduSnackBarText = getId(STRING, "single_loop_edu_snackbar_text")
|
||||
SlidingDialogAnimation = getId(STYLE, "SlidingDialogAnimation")
|
||||
|
Reference in New Issue
Block a user