mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-06-13 05:37:40 +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.SpeedArrayGeneratorFingerprint
|
||||||
import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFallBackFingerprint
|
import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFallBackFingerprint
|
||||||
import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFingerprint
|
import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFingerprint
|
||||||
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getTargetIndexWithFieldReferenceType
|
import app.revanced.util.getTargetIndexWithFieldReferenceType
|
||||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
import app.revanced.util.resultOrThrow
|
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.NarrowLiteralInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
@ -71,7 +73,7 @@ abstract class BaseCustomPlaybackSpeedPatch(
|
|||||||
val limiterMinConstIndex =
|
val limiterMinConstIndex =
|
||||||
indexOfFirstInstruction { (this as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() }
|
indexOfFirstInstruction { (this as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() }
|
||||||
val limiterMaxConstIndex =
|
val limiterMaxConstIndex =
|
||||||
indexOfFirstInstruction { (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() }
|
getTargetIndex(limiterMinConstIndex + 1, Opcode.CONST_HIGH16)
|
||||||
|
|
||||||
val limiterMinConstDestination =
|
val limiterMinConstDestination =
|
||||||
getInstruction<OneRegisterInstruction>(limiterMinConstIndex).registerA
|
getInstruction<OneRegisterInstruction>(limiterMinConstIndex).registerA
|
||||||
|
@ -79,21 +79,24 @@ object TabletMiniPlayerPatch : BaseBytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In ModernMiniPlayer, the drawables of the close button and expand button are reversed.
|
// This issue has been fixed in YouTube 19.17.41+.
|
||||||
// OnClickListener appears to be applied normally, so this appears to be a bug in YouTube.
|
if (YtOutlineXWhite != -1L && YtOutlinePiPWhite != -1L) {
|
||||||
// To solve this, swap the drawables of the close and expand buttons.
|
// In ModernMiniPlayer, the drawables of the close button and expand button are reversed.
|
||||||
// This Drawable will be used in multiple Classes, so instead of using LiteralValueFingerprint to patch only specific methods,
|
// OnClickListener appears to be applied normally, so this appears to be a bug in YouTube.
|
||||||
// Apply the patch to all methods where literals are used.
|
// To solve this, swap the drawables of the close and expand buttons.
|
||||||
mapOf(
|
// This Drawable will be used in multiple Classes, so instead of using LiteralValueFingerprint to patch only specific methods,
|
||||||
YtOutlineXWhite to "replaceCloseButtonDrawableId",
|
// Apply the patch to all methods where literals are used.
|
||||||
YtOutlinePiPWhite to "replaceExpandButtonDrawableId"
|
mapOf(
|
||||||
).forEach { (literal, methodName) ->
|
YtOutlineXWhite to "replaceCloseButtonDrawableId",
|
||||||
val smaliInstruction = """
|
YtOutlinePiPWhite to "replaceExpandButtonDrawableId"
|
||||||
|
).forEach { (literal, methodName) ->
|
||||||
|
val smaliInstruction = """
|
||||||
invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $GENERAL_CLASS_DESCRIPTOR->$methodName(I)I
|
invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $GENERAL_CLASS_DESCRIPTOR->$methodName(I)I
|
||||||
move-result v$REGISTER_TEMPLATE_REPLACEMENT
|
move-result v$REGISTER_TEMPLATE_REPLACEMENT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
context.literalInstructionHook(literal, smaliInstruction)
|
context.literalInstructionHook(literal, smaliInstruction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arrayOf(
|
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.castbutton.CastButtonPatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.LayoutConstructorFingerprint
|
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.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
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.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.PlayerCollapseButton
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getTargetIndexWithReference
|
|
||||||
import app.revanced.util.getWideLiteralInstructionIndex
|
import app.revanced.util.getWideLiteralInstructionIndex
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
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.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
|
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -38,6 +39,7 @@ object PlayerButtonsPatch : BaseBytecodePatch(
|
|||||||
description = "Adds an option to hide buttons in the video player.",
|
description = "Adds an option to hide buttons in the video player.",
|
||||||
dependencies = setOf(
|
dependencies = setOf(
|
||||||
CastButtonPatch::class,
|
CastButtonPatch::class,
|
||||||
|
FullscreenButtonViewStubPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
SharedResourceIdPatch::class
|
SharedResourceIdPatch::class
|
||||||
),
|
),
|
||||||
@ -147,16 +149,22 @@ object PlayerButtonsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
FullScreenButtonFingerprint.resultOrThrow().let {
|
FullScreenButtonFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val viewIndex = getTargetIndexWithReference("Landroid/widget/ImageView;->getResources()Landroid/content/res/Resources;")
|
val buttonCalls = implementation!!.instructions.withIndex()
|
||||||
val viewRegister = getInstruction<FiveRegisterInstruction>(viewIndex).registerC
|
.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(
|
addInstructionsWithLabels(
|
||||||
viewIndex, """
|
insertIndex, """
|
||||||
invoke-static {v$viewRegister}, $PLAYER_CLASS_DESCRIPTOR->hideFullscreenButton(Landroid/widget/ImageView;)Landroid/widget/ImageView;
|
invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->hideFullscreenButton(Landroid/widget/ImageView;)Landroid/widget/ImageView;
|
||||||
move-result-object v$viewRegister
|
move-result-object v$insertRegister
|
||||||
if-nez v$viewRegister, :show
|
if-nez v$insertRegister, :show
|
||||||
return-void
|
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.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
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.FadeDurationFast
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenButton
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenButton
|
||||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||||
@ -11,8 +12,11 @@ internal object FullScreenButtonFingerprint : MethodFingerprint(
|
|||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("Landroid/view/View;"),
|
parameters = listOf("Landroid/view/View;"),
|
||||||
customFingerprint = { methodDef, _ ->
|
customFingerprint = handler@{ methodDef, _ ->
|
||||||
methodDef.containsWideLiteralInstructionIndex(FadeDurationFast)
|
if (!methodDef.containsWideLiteralInstructionIndex(FullScreenButton))
|
||||||
&& 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.LayoutCircleFingerprint
|
||||||
import app.revanced.patches.youtube.player.components.fingerprints.LayoutIconFingerprint
|
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.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.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.SuggestedActionsFingerprint
|
||||||
import app.revanced.patches.youtube.player.components.fingerprints.TouchAreaOnClickListenerFingerprint
|
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.WatermarkFingerprint
|
||||||
import app.revanced.patches.youtube.player.components.fingerprints.WatermarkParentFingerprint
|
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.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.controlsoverlay.ControlsOverlayConfigPatch
|
import app.revanced.patches.youtube.utils.controlsoverlay.ControlsOverlayConfigPatch
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
|
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.getTargetIndexReversed
|
||||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||||
import app.revanced.util.getWideLiteralInstructionIndex
|
import app.revanced.util.getWideLiteralInstructionIndex
|
||||||
import app.revanced.util.literalInstructionBooleanHook
|
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@ -64,6 +61,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
PlayerTypeHookPatch::class,
|
PlayerTypeHookPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
SharedResourceIdPatch::class,
|
SharedResourceIdPatch::class,
|
||||||
|
SpeedOverlayPatch::class,
|
||||||
SuggestedVideoEndScreenPatch::class
|
SuggestedVideoEndScreenPatch::class
|
||||||
),
|
),
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||||
@ -75,10 +73,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
LayoutCircleFingerprint,
|
LayoutCircleFingerprint,
|
||||||
LayoutIconFingerprint,
|
LayoutIconFingerprint,
|
||||||
LayoutVideoFingerprint,
|
LayoutVideoFingerprint,
|
||||||
RestoreSlideToSeekBehaviorFingerprint,
|
|
||||||
SeekEduContainerFingerprint,
|
SeekEduContainerFingerprint,
|
||||||
SpeedOverlayFingerprint,
|
|
||||||
SpeedOverlayValueFingerprint,
|
|
||||||
SuggestedActionsFingerprint,
|
SuggestedActionsFingerprint,
|
||||||
TouchAreaOnClickListenerFingerprint,
|
TouchAreaOnClickListenerFingerprint,
|
||||||
WatermarkParentFingerprint,
|
WatermarkParentFingerprint,
|
||||||
@ -131,34 +126,6 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
// endregion
|
// 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
|
// region patch for hide channel watermark
|
||||||
|
|
||||||
WatermarkFingerprint.resolve(
|
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.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getStringInstructionIndex
|
import app.revanced.util.getStringInstructionIndex
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getTargetIndexReversed
|
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.FiveRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
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.ReferenceInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object ChangeTogglePatch : BaseBytecodePatch(
|
object ChangeTogglePatch : BaseBytecodePatch(
|
||||||
@ -123,6 +126,12 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
CinematicLightingFingerprint.resultOrThrow().let {
|
CinematicLightingFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
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 stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting")
|
||||||
|
|
||||||
val checkCastIndex = getTargetIndexReversed(stringIndex, Opcode.CHECK_CAST)
|
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;
|
invoke-static {v$freeRegisterE}, $PLAYER_CLASS_DESCRIPTOR->getToggleString(Ljava/lang/String;)Ljava/lang/String;
|
||||||
move-result-object v$freeRegisterE
|
move-result-object v$freeRegisterE
|
||||||
:set_string
|
:set_string
|
||||||
iget-object v$freeRegisterC, p0, $iGetObjectPrimaryReference
|
iget-object v$freeRegisterC, v$classRegister, $iGetObjectPrimaryReference
|
||||||
check-cast v$freeRegisterC, $checkCastReference
|
check-cast v$freeRegisterC, $checkCastReference
|
||||||
iget-object v$freeRegisterC, v$freeRegisterC, $iGetObjectSecondaryReference
|
iget-object v$freeRegisterC, v$freeRegisterC, $iGetObjectSecondaryReference
|
||||||
const-string v$freeRegisterD, "menu_item_cinematic_lighting"
|
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 app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
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 app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
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.patcher.extensions.or
|
||||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
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.ReelDynShare
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelForcedMuteButton
|
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.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.ReelRightDislikeIcon
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightLikeIcon
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightLikeIcon
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.RightComment
|
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.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
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.TwoRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -150,8 +152,14 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
|||||||
}
|
}
|
||||||
} ?: ShortsPivotFingerprint.resultOrThrow().let {
|
} ?: ShortsPivotFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
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
|
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;")
|
hideButtons(insertIndex, "hideShortsSoundButton(Ljava/lang/Object;)Ljava/lang/Object;")
|
||||||
}
|
}
|
||||||
@ -215,7 +223,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
|||||||
lateinit var subscriptionFieldReference: FieldReference
|
lateinit var subscriptionFieldReference: FieldReference
|
||||||
|
|
||||||
parentResult.mutableMethod.apply {
|
parentResult.mutableMethod.apply {
|
||||||
val targetIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.ReelPlayerFooter) - 1
|
val targetIndex = getWideLiteralInstructionIndex(ReelPlayerFooter) - 1
|
||||||
subscriptionFieldReference =
|
subscriptionFieldReference =
|
||||||
(getInstruction<ReferenceInstruction>(targetIndex)).reference as FieldReference
|
(getInstruction<ReferenceInstruction>(targetIndex)).reference as FieldReference
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ object ShortsNavigationBarPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderBottomNavigationBarFingerprint.resultOrThrow().let {
|
RenderBottomNavigationBarFingerprint.resultOrThrow().let {
|
||||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||||
|
|
||||||
walkerMethod.addInstruction(
|
walkerMethod.addInstruction(
|
||||||
0,
|
0,
|
||||||
|
@ -4,13 +4,10 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
|||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal object RenderBottomNavigationBarFingerprint : MethodFingerprint(
|
internal object RenderBottomNavigationBarFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "Landroid/view/View;",
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
Opcode.CONST_STRING,
|
Opcode.CONST_STRING,
|
||||||
Opcode.INVOKE_VIRTUAL,
|
Opcode.INVOKE_VIRTUAL
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_NEZ
|
|
||||||
),
|
),
|
||||||
strings = listOf("r_ipl")
|
strings = listOf("r_pfcv")
|
||||||
)
|
)
|
@ -1,9 +1,20 @@
|
|||||||
package app.revanced.patches.youtube.shorts.components.fingerprints
|
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.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",
|
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.patch.PatchException
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
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
|
||||||
|
import app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints.UserWasInShortsABConfigFingerprint.indexOfOptionalInstruction
|
||||||
import app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints.UserWasInShortsFingerprint
|
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.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getTargetIndex
|
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
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.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
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.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -36,23 +35,34 @@ object ResumingShortsOnStartupPatch : BaseBytecodePatch(
|
|||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
UserWasInShortsABConfigFingerprint.resultOrThrow().let {
|
UserWasInShortsABConfigFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
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.
|
// 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.
|
// Presumably a method that processes the ProtoDataStore value (boolean) for the 'user_was_in_shorts' key.
|
||||||
walkerMethod.apply {
|
walkerMethod.apply {
|
||||||
val insertIndex = getTargetIndex(Opcode.IGET_OBJECT)
|
|
||||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
insertIndex, """
|
0, """
|
||||||
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
||||||
move-result v$insertRegister
|
move-result v0
|
||||||
if-eqz v$insertRegister, :show
|
if-eqz v0, :show
|
||||||
const/4 v$insertRegister, 0x0
|
const/4 v0, 0x0
|
||||||
return v$insertRegister
|
return v0
|
||||||
""", ExternalLabel("show", getInstruction(insertIndex))
|
""", ExternalLabel("show", getInstruction(0))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,26 @@
|
|||||||
package app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints
|
package app.revanced.patches.youtube.shorts.startupshortsreset.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
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.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.
|
* This fingerprint is compatible with all YouTube versions after v18.15.40.
|
||||||
*/
|
*/
|
||||||
internal object UserWasInShortsABConfigFingerprint : MethodFingerprint(
|
internal object UserWasInShortsABConfigFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
opcodes = listOf(
|
strings = listOf("Failed to get offline response: "),
|
||||||
Opcode.INVOKE_VIRTUAL,
|
customFingerprint = { methodDef, _ ->
|
||||||
Opcode.MOVE_RESULT,
|
indexOfOptionalInstruction(methodDef) >= 0
|
||||||
Opcode.INVOKE_VIRTUAL,
|
}
|
||||||
Opcode.MOVE_RESULT,
|
) {
|
||||||
Opcode.INVOKE_VIRTUAL,
|
fun indexOfOptionalInstruction(methodDef: Method) =
|
||||||
Opcode.MOVE_RESULT,
|
methodDef.indexOfFirstInstruction {
|
||||||
Opcode.INVOKE_VIRTUAL
|
opcode == Opcode.INVOKE_STATIC
|
||||||
),
|
&& getReference<MethodReference>().toString() == "Lj${'$'}/util/Optional;->of(Ljava/lang/Object;)Lj${'$'}/util/Optional;"
|
||||||
strings = listOf("Failed to get offline response: ")
|
}
|
||||||
)
|
}
|
@ -12,7 +12,9 @@ object Constants {
|
|||||||
"18.38.44",
|
"18.38.44",
|
||||||
"18.48.39",
|
"18.48.39",
|
||||||
"19.05.36",
|
"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.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
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.patches.youtube.utils.fix.fullscreen.fingerprints.FullscreenButtonViewStubFingerprint
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getWideLiteralInstructionIndex
|
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."
|
description = "Fixes an issue where overlay button patches were broken by the new layout."
|
||||||
)
|
)
|
||||||
object FullscreenButtonViewStubPatch : BytecodePatch(
|
object FullscreenButtonViewStubPatch : BytecodePatch(
|
||||||
setOf(FullscreenButtonViewStubFingerprint)
|
setOf(
|
||||||
|
FullscreenButtonPositionFingerprint,
|
||||||
|
FullscreenButtonViewStubFingerprint
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
@ -23,15 +27,20 @@ object FullscreenButtonViewStubPatch : BytecodePatch(
|
|||||||
* This issue only affects some versions of YouTube.
|
* This issue only affects some versions of YouTube.
|
||||||
* Therefore, this patch only applies to versions that can resolve this fingerprint.
|
* Therefore, this patch only applies to versions that can resolve this fingerprint.
|
||||||
*/
|
*/
|
||||||
FullscreenButtonViewStubFingerprint.result?.let {
|
mapOf(
|
||||||
it.mutableMethod.apply {
|
FullscreenButtonViewStubFingerprint to 45617294,
|
||||||
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(45617294), Opcode.MOVE_RESULT)
|
FullscreenButtonPositionFingerprint to 45627640
|
||||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
).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(
|
addInstruction(
|
||||||
targetIndex + 1,
|
targetIndex + 1,
|
||||||
"const/4 v$targetRegister, 0x0"
|
"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 BottomUiContainerStub = -1L
|
||||||
var CaptionToggleContainer = -1L
|
var CaptionToggleContainer = -1L
|
||||||
var CastMediaRouteButton = -1L
|
var CastMediaRouteButton = -1L
|
||||||
|
var CfFullscreenButton = -1L
|
||||||
var ChannelListSubMenu = -1L
|
var ChannelListSubMenu = -1L
|
||||||
var CompactLink = -1L
|
var CompactLink = -1L
|
||||||
var CompactListItem = -1L
|
var CompactListItem = -1L
|
||||||
@ -83,6 +84,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
|||||||
var RightComment = -1L
|
var RightComment = -1L
|
||||||
var ScrimOverlay = -1L
|
var ScrimOverlay = -1L
|
||||||
var Scrubbing = -1L
|
var Scrubbing = -1L
|
||||||
|
var SeekEasyHorizontalTouchOffsetToStartScrubbing = -1L
|
||||||
var SeekUndoEduOverlayStub = -1L
|
var SeekUndoEduOverlayStub = -1L
|
||||||
var SingleLoopEduSnackBarText = -1L
|
var SingleLoopEduSnackBarText = -1L
|
||||||
var SlidingDialogAnimation = -1L
|
var SlidingDialogAnimation = -1L
|
||||||
@ -121,6 +123,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
|||||||
BottomUiContainerStub = getId(ID, "bottom_ui_container_stub")
|
BottomUiContainerStub = getId(ID, "bottom_ui_container_stub")
|
||||||
CaptionToggleContainer = getId(ID, "caption_toggle_container")
|
CaptionToggleContainer = getId(ID, "caption_toggle_container")
|
||||||
CastMediaRouteButton = getId(LAYOUT, "castmediaroutebutton")
|
CastMediaRouteButton = getId(LAYOUT, "castmediaroutebutton")
|
||||||
|
CfFullscreenButton = getId(ID, "cf_fullscreen_button")
|
||||||
ChannelListSubMenu = getId(LAYOUT, "channel_list_sub_menu")
|
ChannelListSubMenu = getId(LAYOUT, "channel_list_sub_menu")
|
||||||
CompactLink = getId(LAYOUT, "compact_link")
|
CompactLink = getId(LAYOUT, "compact_link")
|
||||||
CompactListItem = getId(LAYOUT, "compact_list_item")
|
CompactListItem = getId(LAYOUT, "compact_list_item")
|
||||||
@ -172,6 +175,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
|||||||
RightComment = getId(DRAWABLE, "ic_right_comment_32c")
|
RightComment = getId(DRAWABLE, "ic_right_comment_32c")
|
||||||
ScrimOverlay = getId(ID, "scrim_overlay")
|
ScrimOverlay = getId(ID, "scrim_overlay")
|
||||||
Scrubbing = getId(DIMEN, "vertical_touch_offset_to_enter_fine_scrubbing")
|
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")
|
SeekUndoEduOverlayStub = getId(ID, "seek_undo_edu_overlay_stub")
|
||||||
SingleLoopEduSnackBarText = getId(STRING, "single_loop_edu_snackbar_text")
|
SingleLoopEduSnackBarText = getId(STRING, "single_loop_edu_snackbar_text")
|
||||||
SlidingDialogAnimation = getId(STYLE, "SlidingDialogAnimation")
|
SlidingDialogAnimation = getId(STYLE, "SlidingDialogAnimation")
|
||||||
|
Reference in New Issue
Block a user