diff --git a/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt index be7954ba6..1ecd2a24d 100644 --- a/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt @@ -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(limiterMinConstIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/tabletminiplayer/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/tabletminiplayer/TabletMiniPlayerPatch.kt index a994a2755..cf1f87e8c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/tabletminiplayer/TabletMiniPlayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/tabletminiplayer/TabletMiniPlayerPatch.kt @@ -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( diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt index e7ca0cc75..dd5a0b55d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt @@ -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(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(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)) ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt index 91d6d1604..42acc32f1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt @@ -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 ~ }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt index db09f3137..5f1ed3c4e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt @@ -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(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( diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt index 799b6a9bd..89543d208 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt @@ -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()?.definingClass == definingClass + } + val classRegister = getInstruction(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" diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt new file mode 100644 index 000000000..b042c12a7 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt @@ -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(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(insertIndex) + val insertReference = getInstruction(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(insertIndex).registerA + + hook(insertIndex, insertRegister, jumpIndex) + } + } + + slideToSeekBooleanMethod.apply { + var insertIndex = getTargetIndex(Opcode.IGET_OBJECT) + var insertRegister = getInstruction(insertIndex).registerA + var jumpIndex = getTargetIndexReversed(Opcode.INVOKE_VIRTUAL) + + hook(insertIndex, insertRegister, jumpIndex) + + val constructorMethod = + context.findClass(definingClass)?.mutableClass + ?.methods?.find { method -> method.name == "" } + ?: throw PatchException("Could not find constructor method") + + constructorMethod.apply { + val syntheticIndex = getTargetIndexReversed(Opcode.NEW_INSTANCE) + val syntheticClass = getInstruction(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(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(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(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()?.definingClass == definingClass + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/HorizontalTouchOffsetConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/HorizontalTouchOffsetConstructorFingerprint.kt new file mode 100644 index 000000000..b6f74ec64 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/HorizontalTouchOffsetConstructorFingerprint.kt @@ -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 } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt new file mode 100644 index 000000000..f5ef60b0c --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt @@ -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") + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt similarity index 84% rename from src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt index 698e8a439..e27dac2f0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt @@ -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 diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SlideToSeekMotionEventFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SlideToSeekMotionEventFingerprint.kt new file mode 100644 index 000000000..00b8e13a5 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SlideToSeekMotionEventFingerprint.kt @@ -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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/SpeedOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt similarity index 84% rename from src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/SpeedOverlayFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt index a6e4bd821..dd1fc9e7e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/SpeedOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt @@ -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 diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt new file mode 100644 index 000000000..434305547 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt @@ -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" } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/SpeedOverlayValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt similarity index 88% rename from src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/SpeedOverlayValueFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt index 9be6d0bee..c60dc03f8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/SpeedOverlayValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt @@ -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 diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt index f10b46690..380473da4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt @@ -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(targetIndex)).reference as FieldReference } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt index f61902cf6..4e537e538 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt @@ -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, diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt index c71e0d0eb..9dc16d62a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt @@ -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") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsPivotFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsPivotFingerprint.kt index ce20636ec..18a54fc29 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsPivotFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsPivotFingerprint.kt @@ -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 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt index d062f3f43..41eb1bf17 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt @@ -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() + 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(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)) ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/fingerprints/UserWasInShortsABConfigFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/fingerprints/UserWasInShortsABConfigFingerprint.kt index 4d822f615..2733b1ed5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/fingerprints/UserWasInShortsABConfigFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/fingerprints/UserWasInShortsABConfigFingerprint.kt @@ -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: ") -) \ No newline at end of file + strings = listOf("Failed to get offline response: "), + customFingerprint = { methodDef, _ -> + indexOfOptionalInstruction(methodDef) >= 0 + } +) { + fun indexOfOptionalInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_STATIC + && getReference().toString() == "Lj${'$'}/util/Optional;->of(Ljava/lang/Object;)Lj${'$'}/util/Optional;" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt index 795446b5d..199a36a9f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt @@ -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", ) ) ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/FullscreenButtonViewStubPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/FullscreenButtonViewStubPatch.kt index 3a6b42c9e..67d48dc73 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/FullscreenButtonViewStubPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/FullscreenButtonViewStubPatch.kt @@ -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(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(targetIndex).registerA - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) + addInstruction( + targetIndex + 1, + "const/4 v$targetRegister, 0x0" + ) + } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/fingerprints/FullscreenButtonPositionFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/fingerprints/FullscreenButtonPositionFingerprint.kt new file mode 100644 index 000000000..152b6a6fe --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/fullscreen/fingerprints/FullscreenButtonPositionFingerprint.kt @@ -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 } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt index abe3f0701..5624d8fbc 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt @@ -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")