feat(YouTube): Replace with a fingerprint that supports a wider range of versions (..20.12)

This commit is contained in:
inotia00 2025-03-24 21:26:57 +09:00
parent 529e0163cc
commit 8666d14297
18 changed files with 301 additions and 189 deletions

View File

@ -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
),

View File

@ -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(

View File

@ -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,9 +123,12 @@ 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
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(
@ -133,7 +137,6 @@ val layoutComponentsPatch = bytecodePatch(
"$GENERAL_CLASS_DESCRIPTOR->hideAccountList(Landroid/view/View;Ljava/lang/CharSequence;)V"
)
}
}
// for tablet and old clients
accountMenuFingerprint.matchOrThrow(accountMenuParentFingerprint).let {

View File

@ -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

View File

@ -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(

View File

@ -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+

View File

@ -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(

View File

@ -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(

View File

@ -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 ->

View File

@ -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",

View File

@ -132,9 +132,20 @@ val seekbarComponentsPatch = bytecodePatch(
// region patch for enable seekbar tapping patch
seekbarTappingFingerprint.matchOrThrow().let {
it.method.apply {
val tapSeekIndex = it.patternMatch!!.startIndex + 1
seekbarTappingFingerprint.methodOrThrow().apply {
val pointIndex = indexOfPointInstruction(this)
val pointInstruction = getInstruction<FiveRegisterInstruction>(pointIndex)
val freeRegister = pointInstruction.registerE
val xAxisRegister = pointInstruction.registerD
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
@ -174,19 +185,18 @@ val seekbarComponentsPatch = bytecodePatch(
throw PatchException("oMethod not found")
}
val insertIndex = it.patternMatch!!.startIndex + 2
val insertIndex = tapSeekIndex + 1
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
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

View File

@ -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",

View File

@ -8,16 +8,6 @@ import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
import app.revanced.util.getBooleanOptionValue
import org.w3c.dom.Element
val darkModeSplashScreenPatch = resourcePatch(
description = "darkModeSplashScreenPatch"
) {
dependsOn(versionCheckPatch)
finalize {
val restoreOldSplashAnimationIncluded = is_19_32_or_greater &&
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.
@ -27,6 +17,19 @@ val darkModeSplashScreenPatch = resourcePatch(
* 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 {
if (!is_19_32_or_greater) {
return@finalize
}
val restoreOldSplashAnimationIncluded = CUSTOM_BRANDING_ICON_FOR_YOUTUBE.included == true &&
customBrandingIconPatch.getBooleanOptionValue("restoreOldSplashAnimation").value == true
if (restoreOldSplashAnimationIncluded) {
document("res/values-night/styles.xml").use { document ->
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element

View File

@ -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
}
}

View File

@ -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"

View File

@ -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(

View File

@ -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(

View File

@ -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
}