diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt index 32ef4bde4..0a71b4f2b 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt @@ -13,6 +13,8 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.player.components.fingerprints.AudioVideoSwitchToggleFingerprint +import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightFingerprint +import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightParentFingerprint import app.revanced.patches.music.player.components.fingerprints.HandleSearchRenderedFingerprint import app.revanced.patches.music.player.components.fingerprints.HandleSignInEventFingerprint import app.revanced.patches.music.player.components.fingerprints.InteractionLoggingEnumFingerprint @@ -59,6 +61,7 @@ import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT +import app.revanced.util.alsoResolve import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow @@ -102,6 +105,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( compatiblePackages = COMPATIBLE_PACKAGE, fingerprints = setOf( AudioVideoSwitchToggleFingerprint, + EngagementPanelHeightParentFingerprint, HandleSearchRenderedFingerprint, InteractionLoggingEnumFingerprint, MinimizedPlayerFingerprint, @@ -530,15 +534,12 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.parameters == listOf("Landroid/view/View;", "I") }?.apply { - val bottomSheetBehaviorIndex = - implementation!!.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.INVOKE_VIRTUAL - && instruction.getReference()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;" - && instruction.getReference()?.parameterTypes?.first() == "Z" + val bottomSheetBehaviorIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL + && reference?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;" + && reference.parameterTypes.first() == "Z" } - if (bottomSheetBehaviorIndex < 0) - throw PatchException("Could not find bottomSheetBehaviorIndex") - val freeRegister = getInstruction(bottomSheetBehaviorIndex).registerD @@ -744,18 +745,20 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.mutableMethod.apply { rememberShuffleStateObjectClass = definingClass - val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(45468) - val iGetObjectIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.IGET_OBJECT) - val checkCastIndex = - indexOfFirstInstructionOrThrow(iGetObjectIndex, Opcode.CHECK_CAST) - - val ordinalIndex = indexOfOrdinalInstruction(this) val imageViewIndex = indexOfImageViewInstruction(this) + val ordinalIndex = indexOfOrdinalInstruction(this) + + val invokeInterfaceIndex = + indexOfFirstInstructionReversedOrThrow(ordinalIndex, Opcode.INVOKE_INTERFACE) + val iGetObjectIndex = + indexOfFirstInstructionReversedOrThrow(invokeInterfaceIndex, Opcode.IGET_OBJECT) + val checkCastIndex = + indexOfFirstInstructionOrThrow(invokeInterfaceIndex, Opcode.CHECK_CAST) val iGetObjectReference = getInstruction(iGetObjectIndex).reference val invokeInterfaceReference = - getInstruction(iGetObjectIndex + 1).reference + getInstruction(invokeInterfaceIndex).reference val checkCastReference = getInstruction(checkCastIndex).reference val getOrdinalClassReference = @@ -890,12 +893,82 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old comments popup panels - OldEngagementPanelFingerprint.result?.let { + var restoreOldCommentsPopupPanel = false + + if (SettingsPatch.upward0627 && !SettingsPatch.upward0718) { OldEngagementPanelFingerprint.injectLiteralInstructionBooleanCall( 45427672, "$PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z" ) + restoreOldCommentsPopupPanel = true + } else if (SettingsPatch.upward0718) { + // region disable player from being pushed to the top when opening a comment + + MppWatchWhileLayoutFingerprint.resultOrThrow().mutableMethod.apply { + val callableIndex = + MppWatchWhileLayoutFingerprint.indexOfCallableInstruction(this) + val insertIndex = indexOfFirstInstructionReversedOrThrow(callableIndex, Opcode.NEW_INSTANCE) + val insertRegister = getInstruction(insertIndex).registerA + + addInstructionsWithLabels( + insertIndex, """ + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels()Z + move-result v$insertRegister + if-eqz v$insertRegister, :restore + """, ExternalLabel("restore", getInstruction(callableIndex + 1)) + ) + } + + // endregion + + // region region limit the height of the engagement panel + + EngagementPanelHeightFingerprint.alsoResolve( + context, EngagementPanelHeightParentFingerprint + ).let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = getInstruction(targetIndex).registerA + + addInstructions( + targetIndex + 1, """ + invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z + move-result v$targetRegister + """ + ) + } + } + + MiniPlayerDefaultViewVisibilityFingerprint.resultOrThrow().let { + it.mutableClass.methods.find { method -> + method.parameters == listOf("Landroid/view/View;", "I") + }?.apply { + val targetIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_INTERFACE + && reference?.returnType == "Z" + && reference.parameterTypes.size == 0 + } + 1 + val targetRegister = + getInstruction(targetIndex).registerA + + addInstructions( + targetIndex + 1, """ + invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z + move-result v$targetRegister + """ + ) + } ?: throw PatchException("Could not find targetMethod") + + } + + // endregion + + restoreOldCommentsPopupPanel = true + } + + if (restoreOldCommentsPopupPanel) { SettingsPatch.addSwitchPreference( CategoryType.PLAYER, "revanced_restore_old_comments_popup_panels", diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightFingerprint.kt new file mode 100644 index 000000000..85111f705 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightFingerprint.kt @@ -0,0 +1,26 @@ +package app.revanced.patches.music.player.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object EngagementPanelHeightFingerprint : MethodFingerprint( + returnType = "L", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + ), + parameters = emptyList(), + customFingerprint = custom@{ methodDef, _ -> + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "booleanValue" + } >= 0 + } +) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightParentFingerprint.kt new file mode 100644 index 000000000..334bbd436 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightParentFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.music.player.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction + +internal object EngagementPanelHeightParentFingerprint : MethodFingerprint( + returnType = "L", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf(Opcode.NEW_ARRAY), + parameters = emptyList(), + customFingerprint = custom@{ methodDef, _ -> + if (methodDef.definingClass.startsWith("Lcom/")) { + return@custom false + } + if (methodDef.returnType == "Ljava/lang/Object;") { + return@custom false + } + + methodDef.indexOfFirstInstruction { + opcode == Opcode.CHECK_CAST && + (this as? ReferenceInstruction)?.reference?.toString() == "Lcom/google/android/libraries/youtube/engagementpanel/size/EngagementPanelSizeBehavior;" + } >= 0 + } +) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt index 8cc697b71..d60e19839 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt @@ -1,16 +1,36 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.player.components.fingerprints.MppWatchWhileLayoutFingerprint.indexOfCallableInstruction import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton import app.revanced.util.containsWideLiteralInstructionValue +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 internal object MppWatchWhileLayoutFingerprint : MethodFingerprint( returnType = "V", opcodes = listOf(Opcode.NEW_ARRAY), - customFingerprint = { methodDef, _ -> - methodDef.definingClass.endsWith("/MppWatchWhileLayout;") - && methodDef.name == "onFinishInflate" - && methodDef.containsWideLiteralInstructionValue(MiniPlayerPlayPauseReplayButton) + customFingerprint = custom@{ methodDef, _ -> + if (!methodDef.definingClass.endsWith("/MppWatchWhileLayout;")) { + return@custom false + } + if (methodDef.name != "onFinishInflate") { + return@custom false + } + + methodDef.containsWideLiteralInstructionValue(MiniPlayerPlayPauseReplayButton) && + indexOfCallableInstruction(methodDef) >= 0 } -) +) { + fun indexOfCallableInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.returnType == "V" && + reference.parameterTypes.size == 1 && + reference.parameterTypes.firstOrNull() == "Ljava/util/concurrent/Callable;" + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt index 6fb14779c..537f12105 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt @@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.YtFillArrowShuffle import app.revanced.util.containsWideLiteralInstructionValue import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction @@ -19,7 +20,7 @@ internal object ShuffleClassReferenceFingerprint : MethodFingerprint( parameters = emptyList(), strings = listOf("Unknown shuffle mode"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionValue(45468) && + methodDef.containsWideLiteralInstructionValue(YtFillArrowShuffle) && indexOfOrdinalInstruction(methodDef) >= 0 && indexOfImageViewInstruction(methodDef) >= 0 } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt index e911ff8b8..ebfedb344 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt @@ -7,6 +7,7 @@ import app.revanced.patches.shared.mapping.ResourceMappingPatch import app.revanced.patches.shared.mapping.ResourceMappingPatch.getId import app.revanced.patches.shared.mapping.ResourceType.BOOL import app.revanced.patches.shared.mapping.ResourceType.COLOR +import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE import app.revanced.patches.shared.mapping.ResourceType.DIMEN import app.revanced.patches.shared.mapping.ResourceType.ID import app.revanced.patches.shared.mapping.ResourceType.LAYOUT @@ -57,6 +58,7 @@ object SharedResourceIdPatch : ResourcePatch() { var TouchOutside = -1L var TrimSilenceSwitch: Long = -1 var VarispeedUnavailableTitle = -1L + var YtFillArrowShuffle = -1L override fun execute(context: ResourceContext) { @@ -102,6 +104,7 @@ object SharedResourceIdPatch : ResourcePatch() { TouchOutside = getId(ID, "touch_outside") TrimSilenceSwitch = getId(ID, "trim_silence_switch") VarispeedUnavailableTitle = getId(STRING, "varispeed_unavailable_title") + YtFillArrowShuffle = getId(DRAWABLE, "yt_fill_arrow_shuffle_vd_theme_24") } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt index b5fb0b28f..c6dcd2f1e 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt @@ -132,8 +132,10 @@ object SettingsPatch : BaseResourcePatch( val playServicesVersion = node.textContent.toInt() + upward0627 = 234412000 <= playServicesVersion upward0636 = 240399000 <= playServicesVersion upward0642 = 240999000 <= playServicesVersion + upward0718 = 243699000 <= playServicesVersion break }