unofficial 20.37 support

This commit is contained in:
LisoUseInAIKyrios
2025-09-14 03:38:13 +04:00
parent a352a05db6
commit 77864f41f4
10 changed files with 109 additions and 27 deletions

View File

@@ -23,4 +23,6 @@ public class VersionCheckPatch {
public static final boolean IS_20_21_OR_GREATER = isVersionOrGreater("20.21.00");
public static final boolean IS_20_22_OR_GREATER = isVersionOrGreater("20.22.00");
public static final boolean IS_20_37_OR_GREATER = isVersionOrGreater("20.37.00");
}

View File

@@ -21,6 +21,7 @@ import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerT
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_2;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_3;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_4;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.TABLET;
import static app.revanced.extension.youtube.patches.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
import static app.revanced.extension.youtube.patches.components.PlayerFlyoutMenuItemsFilter.HideAudioFlyoutMenuAvailability;
@@ -47,6 +48,7 @@ import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrow
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailStillTime;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider.SwipeOverlayStyle;
@@ -478,6 +480,13 @@ public class Settings extends BaseSettings {
migrateOldSettingToNew(DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU, ADVANCED_VIDEO_QUALITY_MENU);
migrateOldSettingToNew(DEPRECATED_AUTO_CAPTIONS, DISABLE_AUTO_CAPTIONS);
// 20.37+ YT removed parts of the code for the legacy tablet miniplayer.
// This check must remain until the Tablet type is eventually removed.
if (VersionCheckPatch.IS_20_37_OR_GREATER && MINIPLAYER_TYPE.get() == TABLET) {
Logger.printInfo(() -> "Resetting miniplayer tablet type");
MINIPLAYER_TYPE.resetToDefault();
}
// Migrate renamed enum.
//noinspection deprecation
if (MINIPLAYER_TYPE.get() == MiniplayerType.PHONE) {

View File

@@ -1549,6 +1549,7 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat
public static final fun is_20_30_or_greater ()Z
public static final fun is_20_31_or_greater ()Z
public static final fun is_20_34_or_greater ()Z
public static final fun is_20_37_or_greater ()Z
}
public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt {

View File

@@ -174,6 +174,9 @@ internal val miniplayerOverrideNoContextFingerprint by fingerprint {
)
}
/**
* 20.36 and lower. Codes appears to be removed in 20.37+
*/
internal val miniplayerResponseModelSizeCheckFingerprint by fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L")

View File

@@ -99,8 +99,14 @@ val miniplayerPatch = bytecodePatch(
preferences +=
if (is_20_03_or_greater) {
if (is_20_37_or_greater) {
ListPreference("revanced_miniplayer_type")
} else if (is_20_03_or_greater) {
ListPreference(
key = "revanced_miniplayer_type",
entriesKey = "revanced_miniplayer_type_legacy_20_03_entries",
entryValuesKey = "revanced_miniplayer_type_legacy_20_03_entry_values"
)
} else if (is_19_43_or_greater) {
ListPreference(
key = "revanced_miniplayer_type",
@@ -210,7 +216,7 @@ val miniplayerPatch = bytecodePatch(
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$extensionMethod(F)F
move-result v$register
""",
"""
)
}
}
@@ -226,30 +232,41 @@ val miniplayerPatch = bytecodePatch(
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getModernMiniplayerOverrideType(I)I
move-result v$register
""",
"""
)
}
// region Enable tablet miniplayer.
// Parts of the YT code is removed in 20.37+ and the legacy player no longer works.
miniplayerOverrideNoContextFingerprint.match(
miniplayerDimensionsCalculatorParentFingerprint.originalClassDef,
).method.apply {
findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) }
}
// endregion
// region Legacy tablet miniplayer hooks.
miniplayerOverrideFingerprint.let {
val appNameStringIndex = it.instructionMatches.last().index
navigate(it.originalMethod).to(appNameStringIndex).stop().apply {
findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) }
if (!is_20_37_or_greater) {
miniplayerOverrideNoContextFingerprint.match(
miniplayerDimensionsCalculatorParentFingerprint.originalClassDef,
).method.apply {
findReturnIndicesReversed().forEach { index ->
insertLegacyTabletMiniplayerOverride(
index
)
}
}
}
miniplayerResponseModelSizeCheckFingerprint.let {
it.method.insertLegacyTabletMiniplayerOverride(it.instructionMatches.last().index)
// endregion
// region Legacy tablet miniplayer hooks.
miniplayerOverrideFingerprint.let {
val appNameStringIndex = it.instructionMatches.last().index
navigate(it.originalMethod).to(appNameStringIndex).stop().apply {
findReturnIndicesReversed().forEach { index ->
insertLegacyTabletMiniplayerOverride(
index
)
}
}
}
miniplayerResponseModelSizeCheckFingerprint.let {
it.method.insertLegacyTabletMiniplayerOverride(it.instructionMatches.last().index)
}
}
// endregion

View File

@@ -10,17 +10,22 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val toolBarButtonFingerprint by fingerprint {
returns("V")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("Landroid/view/MenuItem;")
returns("V")
instructions(
resourceLiteral(ResourceType.ID, "menu_item_view"),
methodCall(returnType = "I", opcode = Opcode.INVOKE_INTERFACE),
opcode(Opcode.MOVE_RESULT, maxAfter = 0), // Value is zero if resource does not exist.
opcode(Opcode.MOVE_RESULT, maxAfter = 0),
fieldAccess(type = "Landroid/widget/ImageView;", opcode = Opcode.IGET_OBJECT, maxAfter = 6),
methodCall("Landroid/content/res/Resources;", "getDrawable", maxAfter = 8),
methodCall("Landroid/widget/ImageView;", "setImageDrawable", maxAfter = 4)
)
custom { method, _ ->
// 20.37+ has second parameter of "Landroid/content/Context;"
val parameterCount = method.parameterTypes.count()
(parameterCount == 1 || parameterCount == 2)
&& method.parameterTypes.firstOrNull() == "Landroid/view/MenuItem;"
}
}
internal val spoofAppVersionFingerprint by fingerprint {

View File

@@ -7,6 +7,7 @@ import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_20_37_or_greater
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@@ -42,7 +43,11 @@ val bypassURLRedirectsPatch = bytecodePatch(
)
arrayOf(
abUriParserFingerprint to 2,
if (is_20_37_or_greater) {
(abUriParserFingerprint to 2)
} else {
(abUriParserLegacyFingerprint to 2)
},
httpUriParserFingerprint to 0
).forEach { (fingerprint, index) ->
fingerprint.method.apply {

View File

@@ -1,13 +1,14 @@
package app.revanced.patches.youtube.misc.links
import app.revanced.patcher.checkCast
import app.revanced.patcher.fieldAccess
import app.revanced.patcher.fingerprint
import app.revanced.patcher.methodCall
import app.revanced.patcher.string
import com.android.tools.smali.dexlib2.AccessFlags
internal val abUriParserFingerprint by fingerprint {
/**
* 20.36 and lower.
*/
internal val abUriParserLegacyFingerprint by fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/Object;")
parameters("Ljava/lang/Object;")
@@ -18,6 +19,23 @@ internal val abUriParserFingerprint by fingerprint {
)
}
/**
* 20.37+
*/
internal val abUriParserFingerprint by fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/Object;")
parameters("Ljava/lang/Object;")
instructions(
// Method is a switch statement of unrelated code,
// and there's no strings or anything unique to fingerprint.
methodCall(smali = "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;"),
methodCall(smali = "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;"),
methodCall(smali = "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"),
methodCall(smali = "Ljava/util/List;->get(I)Ljava/lang/Object;"),
)
}
internal val httpUriParserFingerprint by fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Landroid/net/Uri;")

View File

@@ -79,6 +79,8 @@ var is_20_31_or_greater = false
private set
var is_20_34_or_greater = false
private set
var is_20_37_or_greater = false
private set
val versionCheckPatch = resourcePatch(
description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.",
@@ -122,5 +124,6 @@ val versionCheckPatch = resourcePatch(
is_20_30_or_greater = 253105000 <= playStoreServicesVersion
is_20_31_or_greater = 253205000 <= playStoreServicesVersion
is_20_34_or_greater = 253505000 <= playStoreServicesVersion
is_20_37_or_greater = 253805000 <= playStoreServicesVersion
}
}

View File

@@ -218,13 +218,32 @@
<item>@string/revanced_miniplayer_type_entry_0</item>
<item>@string/revanced_miniplayer_type_entry_1</item>
<item>@string/revanced_miniplayer_type_entry_2</item>
<item>@string/revanced_miniplayer_type_entry_3</item>
<!-- YT legacy tablet code is partially removed in 20.37+ -->
<item>@string/revanced_miniplayer_type_entry_4</item>
<item>@string/revanced_miniplayer_type_entry_5</item>
<item>@string/revanced_miniplayer_type_entry_6</item>
<item>@string/revanced_miniplayer_type_entry_7</item>
</string-array>
<string-array name="revanced_miniplayer_type_entry_values">
<item>DISABLED</item>
<item>DEFAULT</item>
<item>MINIMAL</item>
<item>MODERN_1</item>
<item>MODERN_2</item>
<item>MODERN_3</item>
<item>MODERN_4</item>
</string-array>
<string-array name="revanced_miniplayer_type_legacy_20_03_entries">
<item>@string/revanced_miniplayer_type_entry_0</item>
<item>@string/revanced_miniplayer_type_entry_1</item>
<item>@string/revanced_miniplayer_type_entry_2</item>
<item>@string/revanced_miniplayer_type_entry_3</item>
<item>@string/revanced_miniplayer_type_entry_4</item>
<item>@string/revanced_miniplayer_type_entry_5</item>
<item>@string/revanced_miniplayer_type_entry_6</item>
<item>@string/revanced_miniplayer_type_entry_7</item>
</string-array>
<string-array name="revanced_miniplayer_type_legacy_20_03_entry_values">
<item>DISABLED</item>
<item>DEFAULT</item>
<item>MINIMAL</item>