mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-27 04:31:03 +00:00
suppress and other migratios
This commit is contained in:
@@ -9,23 +9,24 @@ import app.revanced.util.getNode
|
||||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Custom network security` = creatingResourcePatch(
|
||||
description = "Allows trusting custom certificate authorities for a specific domain.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
|
||||
val targetDomains by stringsOption(
|
||||
name = "Target domains",
|
||||
description = "List of domains to which the custom trust configuration will be applied (one domain per entry).",
|
||||
default = listOf("example.com"),
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val includeSubdomains by booleanOption(
|
||||
name = "Include subdomains",
|
||||
description = "Applies the configuration to all subdomains of the target domains.",
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val customCAFilePaths by stringsOption(
|
||||
@@ -40,35 +41,35 @@ val `Custom network security` = creatingResourcePatch(
|
||||
CA files will be bundled in res/raw/ of resulting APK
|
||||
""".trimIndentMultiline(),
|
||||
default = null,
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
|
||||
val allowUserCerts by booleanOption(
|
||||
name = "Trust user added CAs",
|
||||
description = "Makes an app trust certificates from the Android user store for the specified domains, and if the option \"Include Subdomains\" is enabled then also the subdomains.",
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val allowSystemCerts by booleanOption(
|
||||
name = "Trust system CAs",
|
||||
description = "Makes an app trust certificates from the Android system store for the specified domains, and and if the option \"Include Subdomains\" is enabled then also the subdomains.",
|
||||
default = true,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val allowCleartextTraffic by booleanOption(
|
||||
name = "Allow cleartext traffic (HTTP)",
|
||||
description = "Allows unencrypted HTTP traffic for the specified domains, and if \"Include Subdomains\" is enabled then also the subdomains.",
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val overridePins by booleanOption(
|
||||
name = "Override certificate pinning",
|
||||
description = "Overrides certificate pinning for the specified domains and their subdomains if the option \"Include Subdomains\" is enabled to allow inspecting app traffic via a proxy.",
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
fun generateNetworkSecurityConfig(): String {
|
||||
@@ -113,55 +114,47 @@ ${trustAnchorsXML.trimEnd()}
|
||||
</trust-anchors>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
|
||||
apply {
|
||||
val nscFileNameBare = "network_security_config"
|
||||
val resXmlDir = "res/xml"
|
||||
val resRawDir = "res/raw"
|
||||
val nscFileNameWithSuffix = "$nscFileNameBare.xml"
|
||||
|
||||
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val applicationNode = document.getNode("application") as Element
|
||||
applicationNode.setAttribute("android:networkSecurityConfig", "@xml/$nscFileNameBare")
|
||||
}
|
||||
|
||||
|
||||
File(get(resXmlDir), nscFileNameWithSuffix).apply {
|
||||
writeText(generateNetworkSecurityConfig())
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (customCAFilePath in customCAFilePaths ?: emptyList()) {
|
||||
val file = File(customCAFilePath)
|
||||
if (!file.exists()) {
|
||||
throw PatchException(
|
||||
"The custom CA file path cannot be found: " +
|
||||
file.absolutePath
|
||||
file.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
if (!file.isFile) {
|
||||
throw PatchException(
|
||||
"The custom CA file path must be a file: "
|
||||
+ file.absolutePath
|
||||
"The custom CA file path must be a file: " +
|
||||
file.absolutePath,
|
||||
)
|
||||
}
|
||||
val caFileNameWithoutSuffix = customCAFilePath.substringAfterLast('/').substringBefore('.')
|
||||
val caFile = File(customCAFilePath)
|
||||
File(
|
||||
get(resRawDir),
|
||||
caFileNameWithoutSuffix
|
||||
caFileNameWithoutSuffix,
|
||||
).writeText(
|
||||
caFile.readText()
|
||||
caFile.readText(),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,10 @@ fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Change package name` = creatingResourcePatch(
|
||||
description = "Appends \".revanced\" to the package name by default. " +
|
||||
"Changing the package name of the app can lead to unexpected issues.",
|
||||
"Changing the package name of the app can lead to unexpected issues.",
|
||||
use = false,
|
||||
) {
|
||||
packageNameOption = stringOption(
|
||||
@@ -45,14 +46,14 @@ val `Change package name` = creatingResourcePatch(
|
||||
default = false,
|
||||
name = "Update permissions",
|
||||
description = "Update compatibility receiver permissions. " +
|
||||
"Enabling this can fix installation errors, but this can also break features in certain apps.",
|
||||
"Enabling this can fix installation errors, but this can also break features in certain apps.",
|
||||
)
|
||||
|
||||
val updateProviders by booleanOption(
|
||||
default = false,
|
||||
name = "Update providers",
|
||||
description = "Update provider names declared by the app. " +
|
||||
"Enabling this can fix installation errors, but this can also break features in certain apps.",
|
||||
"Enabling this can fix installation errors, but this can also break features in certain apps.",
|
||||
)
|
||||
|
||||
afterDependents {
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.patches.mifitness.misc.login
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Fix login` by creatingBytecodePatch(
|
||||
description = "Fixes login for uncertified Mi Fitness app",
|
||||
) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Remove background playback restrictions` by creatingBytecodePatch(
|
||||
description = "Removes restrictions on background playback, including playing kids videos in the background.",
|
||||
) {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package app.revanced.patches.shared.layout.theme
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.allOf
|
||||
import app.revanced.patcher.field
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
@@ -16,6 +19,7 @@ internal val BytecodePatchContext.lithoOnBoundsChangeMethod by gettingFirstMetho
|
||||
returnType("V")
|
||||
parameterTypes("Landroid/graphics/Rect;")
|
||||
instructions(
|
||||
allOf(Opcode.IPUT_OBJECT(), field { definingClass type == "Landroid/graphics/Path;" }),
|
||||
fieldAccess(
|
||||
opcode = Opcode.IPUT_OBJECT,
|
||||
definingClass = "this",
|
||||
|
||||
@@ -7,22 +7,22 @@ import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodDeclaratively {
|
||||
internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodDeclaratively(
|
||||
"This should never happen.",
|
||||
"MetadataValueReader",
|
||||
"com.google.android.gms",
|
||||
) {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("I")
|
||||
parameterTypes("L", "I")
|
||||
strings(
|
||||
"This should never happen.",
|
||||
"MetadataValueReader",
|
||||
"com.google.android.gms",
|
||||
)
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclaratively {
|
||||
internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclaratively(
|
||||
"Google Play Services not available",
|
||||
) {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("V")
|
||||
parameterTypes("L", "I")
|
||||
strings("Google Play Services not available")
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.gmsCoreSupportMethod by gettingFirstMethodDeclaratively {
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
package app.revanced.patches.tiktok.misc.settings
|
||||
|
||||
internal val BytecodePatchContext.addSettingsEntryMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/SettingNewVersionFragment;") &&
|
||||
method.name == "initUnitManger"
|
||||
}
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val BytecodePatchContext.addSettingsEntryMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("initUnitManger")
|
||||
definingClass { endsWith("/SettingNewVersionFragment;") }
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.adPersonalizationActivityOnCreateMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/AdPersonalizationActivity;") &&
|
||||
method.name == "onCreate"
|
||||
}
|
||||
internal val BytecodePatchContext.adPersonalizationActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("onCreate")
|
||||
definingClass { endsWith("/AdPersonalizationActivity;") }
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.settingsEntryMethod by gettingFirstMethodDeclaratively {
|
||||
strings("pls pass item or extends the EventUnit")
|
||||
}
|
||||
internal val BytecodePatchContext.settingsEntryMethod by gettingFirstMethodDeclaratively(
|
||||
"pls pass item or extends the EventUnit",
|
||||
)
|
||||
|
||||
internal val BytecodePatchContext.settingsEntryInfoMethod by gettingFirstMethodDeclaratively {
|
||||
strings(
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package app.revanced.patches.tiktok.misc.settings
|
||||
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.*
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.shared.layout.branding.addBrandLicensePatch
|
||||
import app.revanced.patches.tiktok.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/tiktok/settings/TikTokActivityHook;"
|
||||
@@ -37,16 +34,16 @@ val Settings by creatingBytecodePatch(
|
||||
"Ljava/lang/String;" +
|
||||
")Ljava/lang/Object;"
|
||||
|
||||
fun String.toClassName(): String = substring(1, this.length - 1).replace("/", ".")
|
||||
fun String.toClassName() = substring(1, this.length - 1).replace("/", ".")
|
||||
|
||||
// Find the class name of classes which construct a settings entry
|
||||
val settingsButtonClass = settingsEntryMethod.originalClassDef.type.toClassName()
|
||||
val settingsButtonInfoClass = settingsEntryInfoMethod.originalClassDef.type.toClassName()
|
||||
val settingsButtonClass = settingsEntryMethod.immutableClassDef.type.toClassName()
|
||||
val settingsButtonInfoClass = settingsEntryInfoMethod.immutableClassDef.type.toClassName()
|
||||
|
||||
// Create a settings entry for 'revanced settings' and add it to settings fragment
|
||||
addSettingsEntryMethod.apply {
|
||||
val markIndex = implementation!!.instructions.indexOfFirst {
|
||||
it.opcode == Opcode.IGET_OBJECT && ((it as Instruction22c).reference as FieldReference).name == "headerUnit"
|
||||
val markIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET_OBJECT && fieldReference?.name == "headerUnit"
|
||||
}
|
||||
|
||||
val getUnitManager = getInstruction(markIndex + 2)
|
||||
@@ -67,24 +64,22 @@ val Settings by creatingBytecodePatch(
|
||||
const-string v1, "$settingsButtonInfoClass"
|
||||
invoke-static {v0, v1}, $createSettingsEntryMethodDescriptor
|
||||
move-result-object v0
|
||||
check-cast v0, ${settingsEntryMethod.originalClassDef.type}
|
||||
check-cast v0, ${settingsEntryMethod.immutableClassDef.type}
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Initialize the settings menu once the replaced setting entry is clicked.
|
||||
adPersonalizationActivityOnCreateMethod.apply {
|
||||
val initializeSettingsIndex = implementation!!.instructions.indexOfFirst {
|
||||
it.opcode == Opcode.INVOKE_SUPER
|
||||
} + 1
|
||||
val initializeSettingsIndex = indexOfFirstInstruction(Opcode.INVOKE_SUPER) + 1
|
||||
|
||||
val thisRegister = getInstruction<Instruction35c>(initializeSettingsIndex - 1).registerC
|
||||
val thisRegister = getInstruction<FiveRegisterInstruction>(initializeSettingsIndex - 1).registerC
|
||||
val usableRegister = implementation!!.registerCount - parameters.size - 2
|
||||
|
||||
addInstructionsWithLabels(
|
||||
initializeSettingsIndex,
|
||||
"""
|
||||
invoke-static {v$thisRegister}, $initializeSettingsMethodDescriptor
|
||||
invoke-static { v$thisRegister }, $initializeSettingsMethodDescriptor
|
||||
move-result v$usableRegister
|
||||
if-eqz v$usableRegister, :do_not_open
|
||||
return-void
|
||||
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.twitch.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitch.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.settings.Settings
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Block audio ads` by creatingBytecodePatch(
|
||||
description = "Blocks audio ads in streams and VODs.",
|
||||
) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patches.twitch.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitch.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.settings.Settings
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Block embedded ads` by creatingBytecodePatch(
|
||||
description = "Blocks embedded stream ads using services like Luminous or PurpleAdBlocker.",
|
||||
) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import app.revanced.patches.twitch.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitch.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.settings.Settings
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Block video ads` by creatingBytecodePatch(
|
||||
description = "Blocks video ads in streams and VODs.",
|
||||
) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import app.revanced.patches.twitch.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitch.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.settings.Settings
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Show deleted messages` by creatingBytecodePatch(
|
||||
description = "Shows deleted chat messages behind a clickable spoiler.",
|
||||
) {
|
||||
@@ -33,7 +34,7 @@ val `Show deleted messages` by creatingBytecodePatch(
|
||||
addResources("twitch", "chat.antidelete.showDeletedMessagesPatch")
|
||||
|
||||
PreferenceScreen.CHAT.GENERAL.addPreferences(
|
||||
ListPreference("revanced_show_deleted_messages")
|
||||
ListPreference("revanced_show_deleted_messages"),
|
||||
)
|
||||
|
||||
// Spoiler mode: Force set hasModAccess member to true in constructor
|
||||
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.twitch.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.settings.Settings
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Auto claim channel points` by creatingBytecodePatch(
|
||||
description = "Automatically claim Channel Points.",
|
||||
) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patches.twitch.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitch.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.settings.Settings
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Debug mode` by creatingBytecodePatch(
|
||||
description = "Enables Twitch's internal debugging mode.",
|
||||
use = false,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package app.revanced.patches.twitch.misc.settings
|
||||
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
@@ -13,6 +15,7 @@ import app.revanced.patches.twitch.misc.extension.sharedExtensionPatch
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
|
||||
private const val REVANCED_SETTINGS_MENU_ITEM_NAME = "RevancedSettings"
|
||||
private const val REVANCED_SETTINGS_MENU_ITEM_ID = 0x7
|
||||
@@ -68,23 +71,22 @@ val Settings by creatingBytecodePatch(
|
||||
)
|
||||
|
||||
// Hook onCreate to handle fragment creation.
|
||||
val insertIndex = settingsActivityOnCreateFingerprint.method.implementation!!.instructions.size - 2
|
||||
settingsActivityOnCreateFingerprint.method.addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { p0 }, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingsCreation(Landroidx/appcompat/app/AppCompatActivity;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :no_rv_settings_init
|
||||
return-void
|
||||
""",
|
||||
ExternalLabel(
|
||||
"no_rv_settings_init",
|
||||
settingsActivityOnCreateFingerprint.method.getInstruction(insertIndex),
|
||||
),
|
||||
)
|
||||
settingsActivityOnCreateMethod.apply {
|
||||
val insertIndex = instructions.size - 2
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { p0 }, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingsCreation(Landroidx/appcompat/app/AppCompatActivity;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :no_rv_settings_init
|
||||
return-void
|
||||
""",
|
||||
ExternalLabel("no_rv_settings_init", getInstruction(insertIndex)),
|
||||
)
|
||||
}
|
||||
|
||||
// Create new menu item for settings menu.
|
||||
fun Fingerprint.injectMenuItem(
|
||||
fun MutableMethod.injectMenuItem(
|
||||
name: String,
|
||||
value: Int,
|
||||
titleResourceName: String,
|
||||
@@ -93,7 +95,7 @@ val Settings by creatingBytecodePatch(
|
||||
// Add new static enum member field
|
||||
classDef.staticFields.add(
|
||||
ImmutableField(
|
||||
method.definingClass,
|
||||
definingClass,
|
||||
name,
|
||||
MENU_ITEM_ENUM_CLASS_DESCRIPTOR,
|
||||
AccessFlags.PUBLIC.value or
|
||||
@@ -107,8 +109,8 @@ val Settings by creatingBytecodePatch(
|
||||
)
|
||||
|
||||
// Add initializer for the new enum member
|
||||
method.addInstructions(
|
||||
method.implementation!!.instructions.size - 4,
|
||||
addInstructions(
|
||||
instructions.size - 4,
|
||||
"""
|
||||
new-instance v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR
|
||||
const-string v1, "$titleResourceName"
|
||||
@@ -125,7 +127,7 @@ val Settings by creatingBytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
settingsMenuItemEnumFingerprint.injectMenuItem(
|
||||
settingsMenuItemEnumMethod.injectMenuItem(
|
||||
REVANCED_SETTINGS_MENU_ITEM_NAME,
|
||||
REVANCED_SETTINGS_MENU_ITEM_ID,
|
||||
REVANCED_SETTINGS_MENU_ITEM_TITLE_RES,
|
||||
@@ -133,7 +135,7 @@ val Settings by creatingBytecodePatch(
|
||||
)
|
||||
|
||||
// Intercept settings menu creation and add new menu item.
|
||||
menuGroupsUpdatedFingerprint.method.addInstructions(
|
||||
menuGroupsUpdatedMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
sget-object v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR->$REVANCED_SETTINGS_MENU_ITEM_NAME:$MENU_ITEM_ENUM_CLASS_DESCRIPTOR
|
||||
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Video ads` by creatingBytecodePatch(
|
||||
description = "Adds an option to remove ads in the video player.",
|
||||
) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/RemoveViewerDiscretionDialogPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Remove viewer discretion dialog` by creatingBytecodePatch(
|
||||
description = "Adds an option to remove the dialog that appears when opening a video that has been age-restricted " +
|
||||
"by accepting it automatically. This does not bypass the age restriction.",
|
||||
|
||||
@@ -3,6 +3,9 @@ package app.revanced.patches.youtube.interaction.seekbar
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.after
|
||||
import app.revanced.patcher.afterAtMost
|
||||
import app.revanced.patcher.allOf
|
||||
import app.revanced.patcher.custom
|
||||
import app.revanced.patcher.field
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||
@@ -10,13 +13,16 @@ import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.method
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.newInstance
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.patcher.type
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_19_or_greater
|
||||
@@ -126,24 +132,22 @@ internal val BytecodePatchContext.onTouchEventHandlerMethod by gettingFirstMetho
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.seekbarTappingMethod by gettingFirstMethodDeclaratively {
|
||||
name("onTouchEvent")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("Z")
|
||||
parameterTypes("Landroid/view/MotionEvent;")
|
||||
instructions(
|
||||
Int.MAX_VALUE(),
|
||||
|
||||
newInstance("Landroid/graphics/Point;"),
|
||||
methodCall(smali = "Landroid/graphics/Point;-><init>(II)V", after()),
|
||||
Int.MAX_VALUE.toLong()(),
|
||||
allOf(Opcode.NEW_INSTANCE, type("Landroid/graphics/Point;")),
|
||||
after(method { toString() == "Landroid/graphics/Point;-><init>(II)V" }),
|
||||
methodCall(
|
||||
smali = "Lj\$/util/Optional;->of(Ljava/lang/Object;)Lj\$/util/Optional;",
|
||||
after(),
|
||||
),
|
||||
after(Opcode.MOVE_RESULT_OBJECT()),
|
||||
fieldAccess(opcode = Opcode.IPUT_OBJECT, type = "Lj\$/util/Optional;", after()),
|
||||
|
||||
after(allOf(Opcode.IPUT_OBJECT(), field { type == "Lj\$/util/Optional;" })),
|
||||
afterAtMost(10, Opcode.INVOKE_VIRTUAL()),
|
||||
)
|
||||
custom { method, _ -> method.name == "onTouchEvent" }
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.slideToSeekMethod by gettingFirstMethodDeclaratively {
|
||||
|
||||
@@ -12,6 +12,7 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableAutoCaptionsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable auto captions` by creatingBytecodePatch(
|
||||
description = "Adds an option to disable captions from being automatically enabled.",
|
||||
) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import java.util.logging.Logger
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Hide video action buttons` by creatingResourcePatch(
|
||||
description = "Adds options to hide action buttons (such as the Download button) under videos.",
|
||||
) {
|
||||
@@ -29,7 +30,7 @@ val `Hide video action buttons` by creatingResourcePatch(
|
||||
"20.14.43",
|
||||
"20.21.37",
|
||||
// 20.22+ does not yet support hiding all player buttons.
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
@@ -48,9 +49,9 @@ val `Hide video action buttons` by creatingResourcePatch(
|
||||
// the buffer is the same for all buttons.
|
||||
Logger.getLogger(this::class.java.name).warning(
|
||||
"\n!!!" +
|
||||
"\n!!! Not all player action buttons can be set hidden when patching 20.22+" +
|
||||
"\n!!! Patch 20.21.37 or lower if you want to hide player action buttons" +
|
||||
"\n!!!"
|
||||
"\n!!! Not all player action buttons can be set hidden when patching 20.22+" +
|
||||
"\n!!! Patch 20.21.37 or lower if you want to hide player action buttons" +
|
||||
"\n!!!",
|
||||
)
|
||||
} else {
|
||||
preferences.addAll(
|
||||
@@ -65,15 +66,15 @@ val `Hide video action buttons` by creatingResourcePatch(
|
||||
SwitchPreference("revanced_hide_shop_button"),
|
||||
SwitchPreference("revanced_hide_stop_ads_button"),
|
||||
SwitchPreference("revanced_hide_thanks_button"),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
PreferenceScreenPreference(
|
||||
"revanced_hide_buttons_screen",
|
||||
preferences = preferences
|
||||
)
|
||||
preferences = preferences,
|
||||
),
|
||||
)
|
||||
|
||||
addLithoFilter("Lapp/revanced/extension/youtube/patches/components/ButtonsFilter;")
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package app.revanced.patches.youtube.layout.buttons.navigation
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.after
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val BytecodePatchContext.addCreateButtonViewMethod by gettingFirstMethodDeclaratively {
|
||||
internal val addCreateButtonViewMethodMatch = firstMethodComposite {
|
||||
instructions(
|
||||
"Android Wear"(),
|
||||
Opcode.IF_EQZ(),
|
||||
addString("Android Automotive", after()),
|
||||
after("Android Automotive"()),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/NavigationButtonsPatch;"
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Navigation buttons` by creatingBytecodePatch(
|
||||
description = "Adds options to hide and change navigation buttons (such as the Shorts button).",
|
||||
) {
|
||||
@@ -81,20 +82,18 @@ val `Navigation buttons` by creatingBytecodePatch(
|
||||
)
|
||||
|
||||
// Switch create with notifications button.
|
||||
addCreateButtonViewMethod.let {
|
||||
it.method.apply {
|
||||
val conditionalCheckIndex = it.instructionMatches[1].index
|
||||
val conditionRegister =
|
||||
getInstruction<OneRegisterInstruction>(conditionalCheckIndex).registerA
|
||||
addCreateButtonViewMethodMatch.method.apply {
|
||||
val conditionalCheckIndex = addCreateButtonViewMethodMatch.indices[1]
|
||||
val conditionRegister =
|
||||
getInstruction<OneRegisterInstruction>(conditionalCheckIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
conditionalCheckIndex,
|
||||
"""
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->switchCreateWithNotificationButton()Z
|
||||
move-result v$conditionRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
conditionalCheckIndex,
|
||||
"""
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->switchCreateWithNotificationButton()Z
|
||||
move-result v$conditionRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Hide navigation button labels.
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableFullscreenAmbientModePatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable fullscreen ambient mode` by creatingBytecodePatch(
|
||||
description = "Adds an option to disable the ambient mode when in fullscreen.",
|
||||
) {
|
||||
|
||||
@@ -79,6 +79,7 @@ private const val CUSTOM_FILTER_CLASS_NAME =
|
||||
private const val KEYWORD_FILTER_CLASS_NAME =
|
||||
"Lapp/revanced/extension/youtube/patches/components/KeywordContentFilter;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Hide layout components` by creatingBytecodePatch(
|
||||
description = "Adds options to hide general layout components.",
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Hide player flyout menu items` by creatingBytecodePatch(
|
||||
description = "Adds options to hide menu items that appear when pressing the gear icon in the video player.",
|
||||
) {
|
||||
@@ -27,7 +28,7 @@ val `Hide player flyout menu items` by creatingBytecodePatch(
|
||||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
@@ -50,7 +51,7 @@ val `Hide player flyout menu items` by creatingBytecodePatch(
|
||||
SwitchPreference("revanced_hide_player_flyout_lock_screen"),
|
||||
SwitchPreference(
|
||||
key = "revanced_hide_player_flyout_audio_track",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.HideAudioFlyoutMenuPreference"
|
||||
tag = "app.revanced.extension.youtube.settings.preference.HideAudioFlyoutMenuPreference",
|
||||
),
|
||||
SwitchPreference("revanced_hide_player_flyout_watch_in_vr"),
|
||||
SwitchPreference("revanced_hide_player_flyout_sleep_timer"),
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableRollingNumberAnimationsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable rolling number animations` by creatingBytecodePatch(
|
||||
description = "Adds an option to disable rolling number animations of video view count, user likes, and upload time.",
|
||||
) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableSignInToTvPopupPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable sign in to TV popup` by creatingBytecodePatch(
|
||||
description = "Adds an option to disable the popup asking to sign into a TV on the same local network.",
|
||||
) {
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.hide.time
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.after
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -20,20 +11,11 @@ internal val BytecodePatchContext.timeCounterMethod by gettingFirstMethodDeclara
|
||||
parameterTypes()
|
||||
instructions(
|
||||
Opcode.SUB_LONG_2ADDR(),
|
||||
methodCall(
|
||||
opcode = Opcode.INVOKE_STATIC,
|
||||
returnType = "Ljava/lang/CharSequence;",
|
||||
after(),
|
||||
),
|
||||
after(allOf(Opcode.INVOKE_STATIC(), method { returnType == "Ljava/lang/CharSequence;" })),
|
||||
after(Opcode.MOVE_RESULT_OBJECT()),
|
||||
fieldAccess(opcode = Opcode.IGET_WIDE, type = "J", after()),
|
||||
fieldAccess(opcode = Opcode.IGET_WIDE, type = "J", after()),
|
||||
after(allOf(Opcode.IGET_WIDE(), field { type == "J" })),
|
||||
after(allOf(Opcode.IGET_WIDE(), field { type == "J" })),
|
||||
after(Opcode.SUB_LONG_2ADDR()),
|
||||
|
||||
methodCall(
|
||||
opcode = Opcode.INVOKE_STATIC,
|
||||
returnType = "Ljava/lang/CharSequence;",
|
||||
afterAtMost(5),
|
||||
),
|
||||
afterAtMost(5, allOf(Opcode.INVOKE_STATIC(), method { returnType == "Ljava/lang/CharSequence;" })),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/HideTimestampPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Hide timestamp` by creatingBytecodePatch(
|
||||
description = "Adds an option to hide the timestamp in the bottom left of the video player.",
|
||||
) {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package app.revanced.patches.youtube.layout.panels.popup
|
||||
|
||||
internal val BytecodePatchContext.engagementPanelControllerMethod by gettingFirstMethodDeclaratively {
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val BytecodePatchContext.engagementPanelControllerMethod by gettingFirstMutableMethodDeclaratively(
|
||||
"EngagementPanelController: cannot show EngagementPanel before EngagementPanelController.init() has been called.",
|
||||
"[EngagementPanel] Cannot show EngagementPanel before EngagementPanelController.init() has been called.",
|
||||
) {
|
||||
returnType("L")
|
||||
strings(
|
||||
"EngagementPanelController: cannot show EngagementPanel before EngagementPanelController.init() has been called.",
|
||||
"[EngagementPanel] Cannot show EngagementPanel before EngagementPanelController.init() has been called.",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/DisablePlayerPopupPanelsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable player popup panels` by creatingBytecodePatch(
|
||||
description = "Adds an option to disable panels (such as live chat) from opening automatically.",
|
||||
) {
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.after
|
||||
import app.revanced.patcher.afterAtMost
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.literal
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -24,7 +14,7 @@ internal val BytecodePatchContext.openVideosFullscreenPortraitMethod by gettingF
|
||||
instructions(
|
||||
Opcode.MOVE_RESULT(), // Conditional check to modify.
|
||||
// Open videos fullscreen portrait feature flag.
|
||||
literal(45666112L, afterAtMost(5)), // Cannot be more than 5.
|
||||
afterAtMost(5, 45666112L()), // Cannot be more than 5.
|
||||
afterAtMost(10, Opcode.MOVE_RESULT()),
|
||||
)
|
||||
}
|
||||
@@ -51,11 +41,10 @@ internal val BytecodePatchContext.openVideosFullscreenPortraitLegacyMethod by ge
|
||||
)
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.openVideosFullscreenHookPatchExtensionMethod by gettingFirstMethodDeclaratively {
|
||||
internal val BytecodePatchContext.openVideosFullscreenHookPatchExtensionMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("isFullScreenPatchIncluded")
|
||||
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("Z")
|
||||
parameterTypes()
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "isFullScreenPatchIncluded" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter;"
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Return YouTube Dislike` by creatingBytecodePatch(
|
||||
description = "Adds an option to show the dislike count of videos with Return YouTube Dislike.",
|
||||
) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.logging.Logger
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/WideSearchbarPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Wide search bar` by creatingBytecodePatch(
|
||||
description = "Adds an option to replace the search icon with a wide search bar. " +
|
||||
"This will hide the YouTube logo when active.",
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.shortsautoplay
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.afterAtMost
|
||||
import app.revanced.patcher.field
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.method
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.parameterTypes
|
||||
@@ -13,7 +16,7 @@ import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val BytecodePatchContext.reelEnumConstructorMethod by gettingFirstMethodDeclaratively {
|
||||
internal val reelEnumConstructorMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
instructions(
|
||||
"REEL_LOOP_BEHAVIOR_UNKNOWN"(),
|
||||
@@ -38,24 +41,23 @@ internal val BytecodePatchContext.reelPlaybackRepeatParentMethod by gettingFirst
|
||||
internal val BytecodePatchContext.reelPlaybackRepeatMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("V")
|
||||
parameterTypes("L")
|
||||
instructions(
|
||||
methodCall(smali = "Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z"),
|
||||
)
|
||||
instructions(method { toString() == "Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z" })
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.reelPlaybackMethod by gettingFirstMethodDeclaratively {
|
||||
internal val reelPlaybackMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameterTypes("J")
|
||||
returnType("V")
|
||||
|
||||
val methodParametersPrefix = listOf("I", "L", "L")
|
||||
instructions(
|
||||
fieldAccess(
|
||||
definingClass = "Ljava/util/concurrent/TimeUnit;",
|
||||
name = "MILLISECONDS",
|
||||
),
|
||||
methodCall(
|
||||
name = "<init>",
|
||||
parameters = listOf("I", "L", "L"),
|
||||
afterAtMost(15),
|
||||
field { definingClass == "Ljava/util/concurrent/TimeUnit;" && name == "MILLISECONDS" },
|
||||
afterAtMost(
|
||||
15,
|
||||
method {
|
||||
name == "<init>" &&
|
||||
parameterTypes.zip(methodParametersPrefix).all { (a, b) -> a.startsWith(b) }
|
||||
},
|
||||
),
|
||||
methodCall(
|
||||
opcode = Opcode.INVOKE_VIRTUAL,
|
||||
|
||||
@@ -4,6 +4,8 @@ import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.methodReference
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
@@ -72,11 +74,11 @@ val `Shorts autoplay` by creatingBytecodePatch(
|
||||
|
||||
var reelEnumClass: String
|
||||
|
||||
reelEnumConstructorMethod.let {
|
||||
reelEnumClass = it.originalClassDef.type
|
||||
reelEnumConstructorMethodMatch.apply {
|
||||
reelEnumClass = immutableClassDef.type
|
||||
|
||||
it.method.addInstructions(
|
||||
it.indices.last(),
|
||||
method.addInstructions(
|
||||
indices.last(),
|
||||
"""
|
||||
# Pass the first enum value to extension.
|
||||
# Any enum value of this type will work.
|
||||
@@ -87,7 +89,7 @@ val `Shorts autoplay` by creatingBytecodePatch(
|
||||
}
|
||||
|
||||
reelPlaybackRepeatMethod.match(
|
||||
reelPlaybackRepeatParentMethod.originalClassDef,
|
||||
reelPlaybackRepeatParentMethod.immutableClassDef,
|
||||
).method.apply {
|
||||
// The behavior enums are looked up from an ordinal value to an enum type.
|
||||
findInstructionIndicesReversedOrThrow {
|
||||
@@ -112,10 +114,10 @@ val `Shorts autoplay` by creatingBytecodePatch(
|
||||
// Manually restore the removed 'Autoplay' code.
|
||||
if (is_20_09_or_greater) {
|
||||
// Variable names are only a rough guess of what these methods do.
|
||||
val userActionMethodReference = reelPlaybackMethod.instructionMatches[1]
|
||||
.getInstruction<ReferenceInstruction>().reference as MethodReference
|
||||
val reelSequenceControllerMethodReference = reelPlaybackMethod.instructionMatches[2]
|
||||
.getInstruction<ReferenceInstruction>().reference as MethodReference
|
||||
val userActionMethodReference =
|
||||
reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch.indices[1]).methodReference
|
||||
val reelSequenceControllerMethodReference =
|
||||
reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch.indices[2]).methodReference
|
||||
|
||||
reelPlaybackRepeatMethod.apply {
|
||||
// Find the first call modified by extension code above.
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.spoofappversion
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -19,21 +11,22 @@ internal val BytecodePatchContext.toolBarButtonMethod by gettingFirstMethodDecla
|
||||
returnType("V")
|
||||
instructions(
|
||||
ResourceType.ID("menu_item_view"),
|
||||
methodCall(returnType = "I", opcode = Opcode.INVOKE_INTERFACE),
|
||||
allOf(Opcode.INVOKE_VIRTUAL(), method { returnType == "I" }),
|
||||
after(Opcode.MOVE_RESULT()),
|
||||
fieldAccess(type = "Landroid/widget/ImageView;", opcode = Opcode.IGET_OBJECT, afterAtMost(6)),
|
||||
methodCall("Landroid/content/res/Resources;", "getDrawable", afterAtMost(8)),
|
||||
methodCall("Landroid/widget/ImageView;", "setImageDrawable", afterAtMost(4)),
|
||||
afterAtMost(6, allOf(Opcode.IGET_OBJECT(), field { type == "Landroid/widget/ImageView;" })),
|
||||
afterAtMost(8, method { name == "getDrawable" && definingClass == "Landroid/content/res/Resources;" }),
|
||||
afterAtMost(4, method { name == "setImageDrawable" && definingClass == "Landroid/widget/ImageView;" }),
|
||||
)
|
||||
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;"
|
||||
}
|
||||
// 20.37+ has second parameter of "Landroid/content/Context;"
|
||||
custom { parameterTypes.count() in 1..2 && parameterTypes.first() == "Landroid/view/MenuItem;" }
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.spoofAppVersionMethod by gettingFirstMethodDeclaratively {
|
||||
internal val BytecodePatchContext.spoofAppVersionMethod by gettingFirstMethodDeclaratively(
|
||||
// Instead of applying a bytecode patch, it might be possible to only rely on code from the extension and
|
||||
// manually set the desired version string as this keyed value in the SharedPreferences.
|
||||
// But, this bytecode patch is simple and it works.
|
||||
"pref_override_build_version_name",
|
||||
) {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("L")
|
||||
parameterTypes("L")
|
||||
@@ -42,8 +35,4 @@ internal val BytecodePatchContext.spoofAppVersionMethod by gettingFirstMethodDec
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_STRING,
|
||||
)
|
||||
// Instead of applying a bytecode patch, it might be possible to only rely on code from the extension and
|
||||
// manually set the desired version string as this keyed value in the SharedPreferences.
|
||||
// But, this bytecode patch is simple and it works.
|
||||
strings("pref_override_build_version_name")
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/spoof/SpoofAppVersionPatch;"
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Spoof app version` by creatingBytecodePatch(
|
||||
description = "Adds an option to trick YouTube into thinking you are running an older version of the app. " +
|
||||
"This can be used to restore old UI elements and features.",
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ChangeStartPagePatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Change start page` by creatingBytecodePatch(
|
||||
description = "Adds an option to set which page the app opens in instead of the homepage.",
|
||||
) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable resuming Shorts on startup` by creatingBytecodePatch(
|
||||
description = "Adds an option to disable the Shorts player from resuming on app startup when Shorts were last being watched.",
|
||||
) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/AlternativeThumbnailsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Alternative thumbnails` by creatingBytecodePatch(
|
||||
description = "Adds options to replace video thumbnails using the DeArrow API or image captures from the video.",
|
||||
) {
|
||||
@@ -36,7 +37,7 @@ val `Alternative thumbnails` by creatingBytecodePatch(
|
||||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
@@ -48,27 +49,27 @@ val `Alternative thumbnails` by creatingBytecodePatch(
|
||||
ListPreference(
|
||||
key = "revanced_alt_thumbnail_home",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values
|
||||
entryValuesKey = values,
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_alt_thumbnail_subscription",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values
|
||||
entryValuesKey = values,
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_alt_thumbnail_library",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values
|
||||
entryValuesKey = values,
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_alt_thumbnail_player",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values
|
||||
entryValuesKey = values,
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_alt_thumbnail_search",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values
|
||||
entryValuesKey = values,
|
||||
),
|
||||
NonInteractivePreference(
|
||||
"revanced_alt_thumbnail_dearrow_about",
|
||||
|
||||
@@ -13,9 +13,10 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/BypassImageRegionRestrictionsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Bypass image region restrictions` by creatingBytecodePatch(
|
||||
description = "Adds an option to use a different host for user avatar and channel images " +
|
||||
"and can fix missing images that are blocked in some countries.",
|
||||
"and can fix missing images that are blocked in some countries.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
@@ -30,7 +31,7 @@ val `Bypass image region restrictions` by creatingBytecodePatch(
|
||||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
||||
@@ -26,6 +26,7 @@ internal var prefBackgroundAndOfflineCategoryId = -1L
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/BackgroundPlaybackPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Remove background playback restrictions` by creatingBytecodePatch(
|
||||
description = "Removes restrictions on background playback, including playing kids videos in the background.",
|
||||
) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/spoof/SpoofDeviceDimensionsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Spoof device dimensions` by creatingBytecodePatch(
|
||||
description = "Adds an option to spoof the device dimensions which can unlock higher video qualities.",
|
||||
) {
|
||||
|
||||
@@ -19,13 +19,13 @@ internal val fixContentProviderPatch = bytecodePatch {
|
||||
)
|
||||
|
||||
apply {
|
||||
unstableContentProviderMethod.let {
|
||||
val insertIndex = it.instructionMatches.first().index
|
||||
unstableContentProviderMethodMatch.let {
|
||||
val insertIndex = it.indices.first()
|
||||
|
||||
it.method.apply {
|
||||
val register = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
|
||||
it.method.addInstruction(
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->removeNullMapEntries(Ljava/util/Map;)V",
|
||||
)
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
package app.revanced.patches.youtube.misc.fix.contentprovider
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.patcher.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val BytecodePatchContext.unstableContentProviderMethod by gettingFirstMethodDeclaratively {
|
||||
internal val unstableContentProviderMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("Landroid/content/ContentResolver;", "[Ljava/lang/String;")
|
||||
instructions(
|
||||
// Early targets use HashMap and later targets use ConcurrentMap.
|
||||
methodCall(
|
||||
name = "putAll",
|
||||
parameters = listOf("Ljava/util/Map;"),
|
||||
),
|
||||
method { name == "putAll" && parameterTypes.count() == 1 && parameterTypes.first() == "Ljava/util/Map;" },
|
||||
"ContentProvider query returned null cursor"(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/BypassURLRedirectsPatch;"
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Bypass URL redirects` by creatingBytecodePatch(
|
||||
description = "Adds an option to bypass URL redirects and open the original URL directly.",
|
||||
) {
|
||||
@@ -41,22 +42,20 @@ val `Bypass URL redirects` by creatingBytecodePatch(
|
||||
|
||||
arrayOf(
|
||||
if (is_20_37_or_greater) {
|
||||
(abUriParserMethod to 2)
|
||||
(abUriParserMethodMatch to 2)
|
||||
} else {
|
||||
(abUriParserLegacyMethod to 2)
|
||||
(abUriParserLegacyMethodMatch to 2)
|
||||
},
|
||||
httpUriParserMethod to 0,
|
||||
).forEach { (fingerprint, index) ->
|
||||
fingerprint.method.apply {
|
||||
val insertIndex = fingerprint.instructionMatches[index].index
|
||||
val uriStringRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||
httpUriParserMethodMatch to 0,
|
||||
).forEach { (match, index) ->
|
||||
val insertIndex = match.indices[index]
|
||||
val uriStringRegister = match.method.getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||
|
||||
replaceInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$uriStringRegister }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;",
|
||||
)
|
||||
}
|
||||
match.method.replaceInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$uriStringRegister }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@ package app.revanced.patches.youtube.misc.links
|
||||
import app.revanced.patcher.StringComparisonType
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
/**
|
||||
* 20.36 and lower.
|
||||
*/
|
||||
internal val BytecodePatchContext.abUriParserLegacyMethod by gettingFirstMethodDeclaratively {
|
||||
internal val abUriParserLegacyMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("Ljava/lang/Object;")
|
||||
parameterTypes("Ljava/lang/Object;")
|
||||
@@ -28,7 +28,7 @@ internal val BytecodePatchContext.abUriParserLegacyMethod by gettingFirstMethodD
|
||||
/**
|
||||
* 20.37+
|
||||
*/
|
||||
internal val BytecodePatchContext.abUriParserMethod by gettingFirstMethodDeclaratively {
|
||||
internal val abUriParserMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("Ljava/lang/Object;")
|
||||
parameterTypes("Ljava/lang/Object;")
|
||||
@@ -42,7 +42,7 @@ internal val BytecodePatchContext.abUriParserMethod by gettingFirstMethodDeclara
|
||||
)
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.httpUriParserMethod by gettingFirstMethodDeclaratively {
|
||||
internal val httpUriParserMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("Landroid/net/Uri;")
|
||||
parameterTypes("Ljava/lang/String;")
|
||||
|
||||
@@ -10,6 +10,7 @@ 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.reference.StringReference
|
||||
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Open links externally` by creatingBytecodePatch(
|
||||
description = "Adds an option to always open links in your browser instead of the in-app browser.",
|
||||
) {
|
||||
@@ -44,7 +45,7 @@ val `Open links externally` by creatingBytecodePatch(
|
||||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
package app.revanced.patches.youtube.misc.litho.filter
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -23,26 +14,27 @@ internal val BytecodePatchContext.componentCreateMethod by gettingFirstMethodDec
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.lithoFilterMethod by gettingFirstMethodDeclaratively {
|
||||
definingClass { endsWith("/LithoFilterPatch;") }
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("/LithoFilterPatch;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.protobufBufferReferenceMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("[B")
|
||||
|
||||
var methodDefiningClass = ""
|
||||
custom {
|
||||
methodDefiningClass = definingClass
|
||||
true
|
||||
}
|
||||
|
||||
instructions(
|
||||
fieldAccess(
|
||||
opcode = Opcode.IGET_OBJECT,
|
||||
definingClass = "this",
|
||||
type = "Lcom/google/android/libraries/elements/adl/UpbMessage;",
|
||||
),
|
||||
methodCall(
|
||||
definingClass = "Lcom/google/android/libraries/elements/adl/UpbMessage;",
|
||||
name = "jniDecode",
|
||||
allOf(
|
||||
Opcode.IGET_OBJECT(),
|
||||
field { definingClass == methodDefiningClass && type == "Lcom/google/android/libraries/elements/adl/UpbMessage;" },
|
||||
),
|
||||
method { definingClass == "Lcom/google/android/libraries/elements/adl/UpbMessage;" && name == "jniDecode" },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -61,20 +53,16 @@ internal val BytecodePatchContext.protobufBufferReferenceLegacyMethod by getting
|
||||
internal val BytecodePatchContext.emptyComponentMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.CONSTRUCTOR)
|
||||
parameterTypes()
|
||||
instructions(
|
||||
"EmptyComponent"(),
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.methods.filter { AccessFlags.STATIC.isSet(it.accessFlags) }.size == 1
|
||||
}
|
||||
instructions("EmptyComponent"())
|
||||
custom { immutableClassDef.methods.filter { AccessFlags.STATIC.isSet(it.accessFlags) }.size == 1 }
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.lithoThreadExecutorMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameterTypes("I", "I", "I")
|
||||
custom { method, classDef ->
|
||||
classDef.superclass == "Ljava/util/concurrent/ThreadPoolExecutor;" &&
|
||||
method.containsLiteralInstruction(1L) // 1L = default thread timeout.
|
||||
custom {
|
||||
immutableClassDef.superclass == "Ljava/util/concurrent/ThreadPoolExecutor;" &&
|
||||
containsLiteralInstruction(1L) // 1L = default thread timeout.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/LoopVideoPatch;"
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val `Loop video` by creatingBytecodePatch(
|
||||
description = "Adds an option to loop videos and display loop video button in the video player.",
|
||||
) {
|
||||
|
||||
@@ -122,7 +122,7 @@ internal fun getSeekbarOnDrawMethodMatch() = firstMethodComposite {
|
||||
)
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.subtitleButtonControllerMethod by gettingFirstMethodDeclaratively {
|
||||
internal val BytecodePatchContext.subtitleButtonControllerMethod by gettingFirstMutableMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;")
|
||||
|
||||
Reference in New Issue
Block a user