mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-04-29 22:24:31 +02:00
feat(YouTube): Replace with a fingerprint that supports a wider range of versions (..20.12)
This commit is contained in:
parent
529e0163cc
commit
8666d14297
@ -57,8 +57,6 @@ internal val showDialogCommandFingerprint = legacyFingerprint(
|
||||
name = "showDialogCommandFingerprint",
|
||||
returnType = "V",
|
||||
opcodes = listOf(
|
||||
Opcode.IF_EQ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IGET, // get dialog code
|
||||
),
|
||||
|
@ -6,6 +6,7 @@ import app.revanced.patches.youtube.utils.resourceid.compactListItem
|
||||
import app.revanced.patches.youtube.utils.resourceid.editSettingsAction
|
||||
import app.revanced.patches.youtube.utils.resourceid.fab
|
||||
import app.revanced.patches.youtube.utils.resourceid.toolTipContentView
|
||||
import app.revanced.patches.youtube.utils.resourceid.ytCallToAction
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
@ -19,13 +20,7 @@ internal val accountListFingerprint = legacyFingerprint(
|
||||
name = "accountListFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL or AccessFlags.SYNTHETIC,
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IGET
|
||||
)
|
||||
literals = listOf(ytCallToAction),
|
||||
)
|
||||
|
||||
internal val accountListParentFingerprint = legacyFingerprint(
|
||||
|
@ -20,6 +20,7 @@ import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.accountSwitcherAccessibility
|
||||
import app.revanced.patches.youtube.utils.resourceid.fab
|
||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.ytCallToAction
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
||||
@ -122,17 +123,19 @@ val layoutComponentsPatch = bytecodePatch(
|
||||
// region patch for hide account menu
|
||||
|
||||
// for you tab
|
||||
accountListFingerprint.matchOrThrow(accountListParentFingerprint).let {
|
||||
it.method.apply {
|
||||
val targetIndex = it.patternMatch!!.startIndex + 3
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideAccountList(Landroid/view/View;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
accountListFingerprint.methodOrThrow(accountListParentFingerprint).apply {
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(ytCallToAction)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(literalIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setText"
|
||||
}
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideAccountList(Landroid/view/View;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
}
|
||||
|
||||
// for tablet and old clients
|
||||
|
@ -272,10 +272,11 @@ val toolBarComponentsPatch = bytecodePatch(
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
getReference<FieldReference>()?.type == "Landroid/widget/ImageView;"
|
||||
}
|
||||
val jumpIndex = indexOfFirstInstructionOrThrow(replaceIndex) {
|
||||
val uriIndex = indexOfFirstInstructionOrThrow(replaceIndex) {
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
getReference<MethodReference>()?.toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"
|
||||
} + 4
|
||||
}
|
||||
val jumpIndex = indexOfFirstInstructionOrThrow(uriIndex, Opcode.CONST_4)
|
||||
val replaceIndexInstruction = getInstruction<TwoRegisterInstruction>(replaceIndex)
|
||||
val freeRegister = replaceIndexInstruction.registerA
|
||||
val classRegister = replaceIndexInstruction.registerB
|
||||
|
@ -10,11 +10,12 @@ import app.revanced.patches.youtube.utils.resourceid.endScreenElementLayoutCircl
|
||||
import app.revanced.patches.youtube.utils.resourceid.endScreenElementLayoutIcon
|
||||
import app.revanced.patches.youtube.utils.resourceid.endScreenElementLayoutVideo
|
||||
import app.revanced.patches.youtube.utils.resourceid.offlineActionsVideoDeletedUndoSnackbarText
|
||||
import app.revanced.patches.youtube.utils.resourceid.scrubbing
|
||||
import app.revanced.patches.youtube.utils.resourceid.verticalTouchOffsetToEnterFineScrubbing
|
||||
import app.revanced.patches.youtube.utils.resourceid.seekEasyHorizontalTouchOffsetToStartScrubbing
|
||||
import app.revanced.patches.youtube.utils.resourceid.suggestedAction
|
||||
import app.revanced.patches.youtube.utils.resourceid.tapBloomView
|
||||
import app.revanced.patches.youtube.utils.resourceid.touchArea
|
||||
import app.revanced.patches.youtube.utils.resourceid.verticalTouchOffsetToStartFineScrubbing
|
||||
import app.revanced.patches.youtube.utils.resourceid.videoZoomSnapIndicator
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
@ -126,6 +127,9 @@ internal val crowdfundingBoxFingerprint = legacyFingerprint(
|
||||
literals = listOf(donationCompanion),
|
||||
)
|
||||
|
||||
/**
|
||||
* ~ YouTube 20.11
|
||||
*/
|
||||
internal val filmStripOverlayConfigFingerprint = legacyFingerprint(
|
||||
name = "filmStripOverlayConfigFingerprint",
|
||||
returnType = "Z",
|
||||
@ -140,11 +144,48 @@ internal val filmStripOverlayInteractionFingerprint = legacyFingerprint(
|
||||
parameters = listOf("L")
|
||||
)
|
||||
|
||||
internal val filmStripOverlayParentFingerprint = legacyFingerprint(
|
||||
name = "filmStripOverlayParentFingerprint",
|
||||
internal val filmStripOverlayEnterParentFingerprint = legacyFingerprint(
|
||||
name = "filmStripOverlayEnterParentFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
literals = listOf(scrubbing),
|
||||
literals = listOf(verticalTouchOffsetToEnterFineScrubbing),
|
||||
)
|
||||
|
||||
/**
|
||||
* YouTube 20.12 ~
|
||||
*/
|
||||
internal val filmStripOverlayMotionEventPrimaryFingerprint = legacyFingerprint(
|
||||
name = "filmStripOverlayMotionEventPrimaryFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/view/MotionEvent;"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* YouTube 20.12 ~
|
||||
*/
|
||||
internal val filmStripOverlayMotionEventSecondaryFingerprint = legacyFingerprint(
|
||||
name = "filmStripOverlayMotionEventSecondaryFingerprint",
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/view/MotionEvent;"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.NEG_FLOAT,
|
||||
),
|
||||
)
|
||||
|
||||
internal val filmStripOverlayStartParentFingerprint = legacyFingerprint(
|
||||
name = "filmStripOverlayStartParentFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
literals = listOf(verticalTouchOffsetToStartFineScrubbing),
|
||||
)
|
||||
|
||||
internal val filmStripOverlayPreviewFingerprint = legacyFingerprint(
|
||||
|
@ -32,6 +32,7 @@ import app.revanced.patches.youtube.utils.playservice.is_19_18_or_greater
|
||||
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
|
||||
import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater
|
||||
import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater
|
||||
import app.revanced.patches.youtube.utils.playservice.is_20_12_or_greater
|
||||
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.darkBackground
|
||||
import app.revanced.patches.youtube.utils.resourceid.fadeDurationFast
|
||||
@ -399,18 +400,6 @@ val playerComponentsPatch = bytecodePatch(
|
||||
return ""
|
||||
}
|
||||
|
||||
fun MutableMethod.hookFilmstripOverlay() {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideFilmstripOverlay()Z
|
||||
move-result v0
|
||||
if-eqz v0, :shown
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
""", ExternalLabel("shown", getInstruction(0))
|
||||
)
|
||||
}
|
||||
|
||||
// region patch for custom player overlay opacity
|
||||
|
||||
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
||||
@ -581,12 +570,68 @@ val playerComponentsPatch = bytecodePatch(
|
||||
|
||||
// region patch for hide filmstrip overlay
|
||||
|
||||
arrayOf(
|
||||
filmStripOverlayConfigFingerprint,
|
||||
fun MutableMethod.hookFilmstripOverlay(
|
||||
index: Int = 0,
|
||||
register: Int = 0
|
||||
) {
|
||||
val stringInstructions = if (returnType == "Z")
|
||||
"""
|
||||
const/4 v$register, 0x0
|
||||
return v$register
|
||||
"""
|
||||
else if (returnType == "V")
|
||||
"""
|
||||
return-void
|
||||
"""
|
||||
else
|
||||
throw Exception("This case should never happen.")
|
||||
|
||||
addInstructionsWithLabels(
|
||||
index, """
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideFilmstripOverlay()Z
|
||||
move-result v$register
|
||||
if-eqz v$register, :shown
|
||||
""" + stringInstructions + """
|
||||
:shown
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
val filmStripOverlayFingerprints = mutableListOf(
|
||||
filmStripOverlayInteractionFingerprint,
|
||||
filmStripOverlayPreviewFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.methodOrThrow(filmStripOverlayParentFingerprint).hookFilmstripOverlay()
|
||||
)
|
||||
|
||||
if (is_20_12_or_greater) {
|
||||
filmStripOverlayMotionEventPrimaryFingerprint.matchOrThrow(filmStripOverlayStartParentFingerprint).let {
|
||||
it.method.apply {
|
||||
val index = it.patternMatch!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
hookFilmstripOverlay(index, register)
|
||||
}
|
||||
}
|
||||
|
||||
filmStripOverlayMotionEventSecondaryFingerprint.matchOrThrow(filmStripOverlayStartParentFingerprint).let {
|
||||
it.method.apply {
|
||||
val index = it.patternMatch!!.startIndex + 2
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index, """
|
||||
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->hideFilmstripOverlay(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filmStripOverlayFingerprints += filmStripOverlayConfigFingerprint
|
||||
}
|
||||
|
||||
filmStripOverlayFingerprints.forEach { fingerprint ->
|
||||
fingerprint.methodOrThrow(filmStripOverlayEnterParentFingerprint).hookFilmstripOverlay()
|
||||
}
|
||||
|
||||
// Removed in YouTube 20.05+
|
||||
|
@ -1,8 +1,10 @@
|
||||
package app.revanced.patches.youtube.player.flyoutmenu.hide
|
||||
|
||||
import app.revanced.patches.youtube.utils.indexOfAddHeaderViewInstruction
|
||||
import app.revanced.patches.youtube.utils.resourceid.bottomSheetFooterText
|
||||
import app.revanced.patches.youtube.utils.resourceid.subtitleMenuSettingsFooterInfo
|
||||
import app.revanced.patches.youtube.utils.resourceid.videoQualityBottomSheet
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
@ -18,33 +20,18 @@ internal val advancedQualityBottomSheetFingerprint = legacyFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L", "L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.CONST,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_16,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CONST_STRING
|
||||
),
|
||||
literals = listOf(videoQualityBottomSheet),
|
||||
customFingerprint = custom@{ method, _ ->
|
||||
if (!method.containsLiteralInstruction(videoQualityBottomSheet)) {
|
||||
return@custom false
|
||||
}
|
||||
if (indexOfAddHeaderViewInstruction(method) < 0) {
|
||||
return@custom false
|
||||
}
|
||||
val implementation = method.implementation
|
||||
?: return@custom false
|
||||
|
||||
implementation.instructions.elementAt(0).opcode == Opcode.IGET_OBJECT
|
||||
}
|
||||
)
|
||||
|
||||
internal val captionsBottomSheetFingerprint = legacyFingerprint(
|
||||
|
@ -10,6 +10,7 @@ import app.revanced.patches.shared.litho.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.indexOfAddHeaderViewInstruction
|
||||
import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_PLAYER_FLYOUT_MENU
|
||||
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.utils.playservice.is_18_39_or_greater
|
||||
@ -25,7 +26,6 @@ import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
||||
import app.revanced.util.fingerprint.injectLiteralInstructionViewCall
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
@ -75,10 +75,7 @@ val playerFlyoutMenuPatch = bytecodePatch(
|
||||
qualityMenuViewInflateFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.methodOrThrow().apply {
|
||||
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "addHeaderView"
|
||||
}
|
||||
val insertIndex = indexOfAddHeaderViewInstruction(this)
|
||||
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
|
@ -50,6 +50,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstructio
|
||||
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.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
@ -145,10 +146,15 @@ val miniplayerPatch = bytecodePatch(
|
||||
// region Legacy tablet Miniplayer hooks.
|
||||
|
||||
miniplayerOverrideFingerprint.matchOrThrow().let {
|
||||
val appNameStringIndex = it.stringMatches!!.first().index + 2
|
||||
|
||||
it.method.apply {
|
||||
val walkerMethod = getWalkerMethod(appNameStringIndex)
|
||||
val stringIndex = it.stringMatches!!.first().index
|
||||
val walkerIndex = indexOfFirstInstructionOrThrow(stringIndex) {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.returnType == "Z" &&
|
||||
reference.parameterTypes.size == 1 &&
|
||||
reference.parameterTypes.firstOrNull() == "Landroid/content/Context;"
|
||||
}
|
||||
val walkerMethod = getWalkerMethod(walkerIndex)
|
||||
|
||||
walkerMethod.apply {
|
||||
findReturnIndicesReversed().forEach { index ->
|
||||
|
@ -7,9 +7,13 @@ import app.revanced.patches.youtube.utils.resourceid.ytTextSecondary
|
||||
import app.revanced.patches.youtube.utils.resourceid.ytYoutubeMagenta
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import app.revanced.util.or
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import kotlin.collections.listOf
|
||||
|
||||
internal val shortsSeekbarColorFingerprint = legacyFingerprint(
|
||||
@ -113,27 +117,21 @@ internal val seekbarTappingFingerprint = legacyFingerprint(
|
||||
name = "seekbarTappingFingerprint",
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INT_TO_FLOAT,
|
||||
Opcode.INT_TO_FLOAT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ
|
||||
),
|
||||
customFingerprint = { method, _ -> method.name == "onTouchEvent" }
|
||||
parameters = listOf("Landroid/view/MotionEvent;"),
|
||||
customFingerprint = { method, classDef ->
|
||||
classDef.interfaces.contains("Landroid/view/View${'$'}OnLayoutChangeListener;") &&
|
||||
classDef.fields.find { it.type == "[Lcom/google/android/libraries/youtube/player/features/overlay/timebar/TimelineMarker;" } != null &&
|
||||
method.name == "onTouchEvent" &&
|
||||
indexOfPointInstruction(method) >= 0
|
||||
}
|
||||
)
|
||||
|
||||
internal fun indexOfPointInstruction(method: Method) =
|
||||
method.indexOfFirstInstructionReversed {
|
||||
opcode == Opcode.INVOKE_DIRECT &&
|
||||
getReference<MethodReference>()?.toString() == "Landroid/graphics/Point;-><init>(II)V"
|
||||
}
|
||||
|
||||
internal val seekbarThumbnailsQualityFingerprint = legacyFingerprint(
|
||||
name = "seekbarThumbnailsQualityFingerprint",
|
||||
returnType = "Z",
|
||||
|
@ -132,60 +132,70 @@ val seekbarComponentsPatch = bytecodePatch(
|
||||
|
||||
// region patch for enable seekbar tapping patch
|
||||
|
||||
seekbarTappingFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val tapSeekIndex = it.patternMatch!!.startIndex + 1
|
||||
val tapSeekClass = getInstruction(tapSeekIndex)
|
||||
.getReference<MethodReference>()!!
|
||||
.definingClass
|
||||
seekbarTappingFingerprint.methodOrThrow().apply {
|
||||
val pointIndex = indexOfPointInstruction(this)
|
||||
val pointInstruction = getInstruction<FiveRegisterInstruction>(pointIndex)
|
||||
val freeRegister = pointInstruction.registerE
|
||||
val xAxisRegister = pointInstruction.registerD
|
||||
|
||||
val tapSeekMethods = findMethodsOrThrow(tapSeekClass)
|
||||
var pMethodCall = ""
|
||||
var oMethodCall = ""
|
||||
|
||||
for (method in tapSeekMethods) {
|
||||
if (method.implementation == null)
|
||||
continue
|
||||
|
||||
val instructions = method.implementation!!.instructions
|
||||
// here we make sure we actually find the method because it has more than 7 instructions
|
||||
if (instructions.count() != 10)
|
||||
continue
|
||||
|
||||
// we know that the 7th instruction has the opcode CONST_4
|
||||
val instruction = instructions.elementAt(6)
|
||||
if (instruction.opcode != Opcode.CONST_4)
|
||||
continue
|
||||
|
||||
// the literal for this instruction has to be either 1 or 2
|
||||
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
|
||||
|
||||
// method founds
|
||||
if (literal == 1)
|
||||
pMethodCall = "${method.definingClass}->${method.name}(I)V"
|
||||
else if (literal == 2)
|
||||
oMethodCall = "${method.definingClass}->${method.name}(I)V"
|
||||
}
|
||||
|
||||
if (pMethodCall.isEmpty()) {
|
||||
throw PatchException("pMethod not found")
|
||||
}
|
||||
if (oMethodCall.isEmpty()) {
|
||||
throw PatchException("oMethod not found")
|
||||
}
|
||||
|
||||
val insertIndex = it.patternMatch!!.startIndex + 2
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSeekbarTapping()Z
|
||||
move-result v0
|
||||
if-eqz v0, :disabled
|
||||
invoke-virtual { p0, v2 }, $pMethodCall
|
||||
invoke-virtual { p0, v2 }, $oMethodCall
|
||||
""", ExternalLabel("disabled", getInstruction(insertIndex))
|
||||
)
|
||||
val tapSeekIndex = indexOfFirstInstructionOrThrow(pointIndex) {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
reference?.returnType == "V" &&
|
||||
reference.parameterTypes.isEmpty()
|
||||
}
|
||||
val thisInstanceRegister = getInstruction<FiveRegisterInstruction>(tapSeekIndex).registerC
|
||||
|
||||
val tapSeekClass = getInstruction(tapSeekIndex)
|
||||
.getReference<MethodReference>()!!
|
||||
.definingClass
|
||||
|
||||
val tapSeekMethods = findMethodsOrThrow(tapSeekClass)
|
||||
var pMethodCall = ""
|
||||
var oMethodCall = ""
|
||||
|
||||
for (method in tapSeekMethods) {
|
||||
if (method.implementation == null)
|
||||
continue
|
||||
|
||||
val instructions = method.implementation!!.instructions
|
||||
// here we make sure we actually find the method because it has more than 7 instructions
|
||||
if (instructions.count() != 10)
|
||||
continue
|
||||
|
||||
// we know that the 7th instruction has the opcode CONST_4
|
||||
val instruction = instructions.elementAt(6)
|
||||
if (instruction.opcode != Opcode.CONST_4)
|
||||
continue
|
||||
|
||||
// the literal for this instruction has to be either 1 or 2
|
||||
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
|
||||
|
||||
// method founds
|
||||
if (literal == 1)
|
||||
pMethodCall = "${method.definingClass}->${method.name}(I)V"
|
||||
else if (literal == 2)
|
||||
oMethodCall = "${method.definingClass}->${method.name}(I)V"
|
||||
}
|
||||
|
||||
if (pMethodCall.isEmpty()) {
|
||||
throw PatchException("pMethod not found")
|
||||
}
|
||||
if (oMethodCall.isEmpty()) {
|
||||
throw PatchException("oMethod not found")
|
||||
}
|
||||
|
||||
val insertIndex = tapSeekIndex + 1
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSeekbarTapping()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $pMethodCall
|
||||
invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $oMethodCall
|
||||
""", ExternalLabel("disabled", getInstruction(insertIndex))
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
@ -109,25 +109,26 @@ internal val qualityMenuViewInflateFingerprint = legacyFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L", "L"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_SUPER,
|
||||
Opcode.CONST,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_16,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST
|
||||
),
|
||||
literals = listOf(videoQualityBottomSheet),
|
||||
customFingerprint = custom@{ method, _ ->
|
||||
if (!method.containsLiteralInstruction(videoQualityBottomSheet)) {
|
||||
return@custom false
|
||||
}
|
||||
if (indexOfAddHeaderViewInstruction(method) < 0) {
|
||||
return@custom false
|
||||
}
|
||||
val implementation = method.implementation
|
||||
?: return@custom false
|
||||
|
||||
implementation.instructions.elementAt(0).opcode == Opcode.INVOKE_SUPER
|
||||
}
|
||||
)
|
||||
|
||||
internal fun indexOfAddHeaderViewInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "addHeaderView"
|
||||
}
|
||||
|
||||
internal val rollingNumberTextViewAnimationUpdateFingerprint = legacyFingerprint(
|
||||
name = "rollingNumberTextViewAnimationUpdateFingerprint",
|
||||
returnType = "V",
|
||||
|
@ -8,25 +8,28 @@ import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||
import app.revanced.util.getBooleanOptionValue
|
||||
import org.w3c.dom.Element
|
||||
|
||||
/**
|
||||
* Fix the splash screen dark mode background color.
|
||||
* In earlier versions of the app this is white and makes no sense for dark mode.
|
||||
* This is only required for 19.32 and greater, but is applied to all targets.
|
||||
* Only dark mode needs this fix as light mode correctly uses the custom color.
|
||||
*
|
||||
* This is a bug in unpatched YouTube.
|
||||
* Should always be applied even if the `Theme` patch is excluded.
|
||||
*/
|
||||
val darkModeSplashScreenPatch = resourcePatch(
|
||||
description = "darkModeSplashScreenPatch"
|
||||
) {
|
||||
dependsOn(versionCheckPatch)
|
||||
|
||||
finalize {
|
||||
val restoreOldSplashAnimationIncluded = is_19_32_or_greater &&
|
||||
CUSTOM_BRANDING_ICON_FOR_YOUTUBE.included == true &&
|
||||
if (!is_19_32_or_greater) {
|
||||
return@finalize
|
||||
}
|
||||
|
||||
val restoreOldSplashAnimationIncluded = CUSTOM_BRANDING_ICON_FOR_YOUTUBE.included == true &&
|
||||
customBrandingIconPatch.getBooleanOptionValue("restoreOldSplashAnimation").value == true
|
||||
|
||||
/**
|
||||
* Fix the splash screen dark mode background color.
|
||||
* In earlier versions of the app this is white and makes no sense for dark mode.
|
||||
* This is only required for 19.32 and greater, but is applied to all targets.
|
||||
* Only dark mode needs this fix as light mode correctly uses the custom color.
|
||||
*
|
||||
* This is a bug in unpatched YouTube.
|
||||
* Should always be applied even if the `Theme` patch is excluded.
|
||||
*/
|
||||
if (restoreOldSplashAnimationIncluded) {
|
||||
document("res/values-night/styles.xml").use { document ->
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
|
@ -71,6 +71,8 @@ var is_20_09_or_greater = false
|
||||
private set
|
||||
var is_20_10_or_greater = false
|
||||
private set
|
||||
var is_20_12_or_greater = false
|
||||
private set
|
||||
|
||||
val versionCheckPatch = resourcePatch(
|
||||
description = "versionCheckPatch",
|
||||
@ -119,5 +121,6 @@ val versionCheckPatch = resourcePatch(
|
||||
is_20_05_or_greater = 250605000 <= playStoreServicesVersion
|
||||
is_20_09_or_greater = 251006000 <= playStoreServicesVersion
|
||||
is_20_10_or_greater = 251105000 <= playStoreServicesVersion
|
||||
is_20_12_or_greater = 251305000 <= playStoreServicesVersion
|
||||
}
|
||||
}
|
||||
|
@ -193,8 +193,6 @@ var rightComment = -1L
|
||||
private set
|
||||
var scrimOverlay = -1L
|
||||
private set
|
||||
var scrubbing = -1L
|
||||
private set
|
||||
var seekEasyHorizontalTouchOffsetToStartScrubbing = -1L
|
||||
private set
|
||||
var seekUndoEduOverlayStub = -1L
|
||||
@ -225,6 +223,10 @@ var videoQualityBottomSheet = -1L
|
||||
private set
|
||||
var varispeedUnavailableTitle = -1L
|
||||
private set
|
||||
var verticalTouchOffsetToEnterFineScrubbing = -1L
|
||||
private set
|
||||
var verticalTouchOffsetToStartFineScrubbing = -1L
|
||||
private set
|
||||
var videoQualityUnavailableAnnouncement = -1L
|
||||
private set
|
||||
var videoZoomSnapIndicator = -1L
|
||||
@ -235,6 +237,8 @@ var youTubeControlsOverlaySubtitleButton = -1L
|
||||
private set
|
||||
var youTubeLogo = -1L
|
||||
private set
|
||||
var ytCallToAction = -1L
|
||||
private set
|
||||
var ytFillBell = -1L
|
||||
private set
|
||||
var ytOutlineLibrary = -1L
|
||||
@ -620,10 +624,6 @@ internal val sharedResourceIdPatch = resourcePatch(
|
||||
ID,
|
||||
"scrim_overlay"
|
||||
]
|
||||
scrubbing = resourceMappings[
|
||||
DIMEN,
|
||||
"vertical_touch_offset_to_enter_fine_scrubbing"
|
||||
]
|
||||
seekEasyHorizontalTouchOffsetToStartScrubbing = resourceMappings[
|
||||
DIMEN,
|
||||
"seek_easy_horizontal_touch_offset_to_start_scrubbing"
|
||||
@ -684,6 +684,14 @@ internal val sharedResourceIdPatch = resourcePatch(
|
||||
STRING,
|
||||
"varispeed_unavailable_title"
|
||||
]
|
||||
verticalTouchOffsetToEnterFineScrubbing = resourceMappings[
|
||||
DIMEN,
|
||||
"vertical_touch_offset_to_enter_fine_scrubbing"
|
||||
]
|
||||
verticalTouchOffsetToStartFineScrubbing = resourceMappings[
|
||||
DIMEN,
|
||||
"vertical_touch_offset_to_start_fine_scrubbing"
|
||||
]
|
||||
videoQualityUnavailableAnnouncement = resourceMappings[
|
||||
STRING,
|
||||
"video_quality_unavailable_announcement"
|
||||
@ -704,6 +712,10 @@ internal val sharedResourceIdPatch = resourcePatch(
|
||||
ID,
|
||||
"youtube_logo"
|
||||
]
|
||||
ytCallToAction = resourceMappings[
|
||||
ATTR,
|
||||
"ytCallToAction"
|
||||
]
|
||||
ytFillBell = resourceMappings[
|
||||
DRAWABLE,
|
||||
"yt_fill_bell_black_24"
|
||||
|
@ -7,6 +7,7 @@ import app.revanced.util.or
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
/**
|
||||
* This fingerprint is compatible with YouTube v18.30.xx+
|
||||
@ -54,7 +55,14 @@ internal val rollingNumberMeasureTextParentFingerprint = legacyFingerprint(
|
||||
internal val rollingNumberSetterFingerprint = legacyFingerprint(
|
||||
name = "rollingNumberSetterFingerprint",
|
||||
opcodes = listOf(Opcode.CHECK_CAST),
|
||||
literals = listOf(45427773L),
|
||||
customFingerprint = { method, _ ->
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.CONST_STRING &&
|
||||
getReference<StringReference>()
|
||||
?.string.toString()
|
||||
.startsWith("RollingNumberType required properties missing! Need")
|
||||
} >= 0
|
||||
}
|
||||
)
|
||||
|
||||
internal val shortsTextViewFingerprint = legacyFingerprint(
|
||||
|
@ -2,9 +2,12 @@ package app.revanced.patches.youtube.video.playback
|
||||
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.or
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
internal val av1CodecFingerprint = legacyFingerprint(
|
||||
name = "av1CodecFingerprint",
|
||||
@ -61,16 +64,17 @@ internal val playbackSpeedChangedFromRecyclerViewFingerprint = legacyFingerprint
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
),
|
||||
customFingerprint = { method, _ ->
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET &&
|
||||
getReference<FieldReference>()?.type == "F"
|
||||
} >= 0
|
||||
}
|
||||
)
|
||||
|
||||
internal val playbackSpeedInitializeFingerprint = legacyFingerprint(
|
||||
|
@ -29,7 +29,7 @@ internal val videoIdFingerprint = legacyFingerprint(
|
||||
?: return@custom false
|
||||
val instructions = implementation.instructions
|
||||
val instructionCount = instructions.count()
|
||||
if (instructionCount < 30) {
|
||||
if (instructionCount < 25) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user