update to new options API

This commit is contained in:
oSumAtrIX
2026-01-06 16:24:40 +01:00
parent 30076b7a9b
commit cceb7a7c43
42 changed files with 148 additions and 215 deletions

View File

@@ -11,8 +11,8 @@ appcompat = "1.7.1"
okhttp = "5.3.2"
retrofit = "3.0.0"
guava = "33.5.0-jre"
protobuf-javalite = "4.33.1"
protoc = "4.33.1"
protobuf-javalite = "4.33.2"
protoc = "4.33.2"
protobuf = "0.9.5"
antlr4 = "4.13.2"
nanohttpd = "2.3.1"

View File

@@ -49,7 +49,10 @@ tasks {
kotlin {
compilerOptions {
freeCompilerArgs = listOf("-Xcontext-receivers")
freeCompilerArgs.addAll(
"-Xexplicit-backing-fields",
"-Xcontext-parameters"
)
}
}

View File

@@ -11,172 +11,148 @@ val spoofBuildInfoPatch = bytecodePatch(
use = false,
) {
val board by stringOption(
key = "board",
default = null,
title = "Board",
name = "Board",
description = "The name of the underlying board, like \"goldfish\".",
)
val bootloader by stringOption(
key = "bootloader",
default = null,
title = "Bootloader",
name = "Bootloader",
description = "The system bootloader version number.",
)
val brand by stringOption(
key = "brand",
default = null,
title = "Brand",
name = "Brand",
description = "The consumer-visible brand with which the product/hardware will be associated, if any.",
)
val cpuAbi by stringOption(
key = "cpu-abi",
default = null,
title = "CPU ABI",
name = "CPU ABI",
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead.",
)
val cpuAbi2 by stringOption(
key = "cpu-abi-2",
default = null,
title = "CPU ABI 2",
name = "CPU ABI 2",
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead.",
)
val device by stringOption(
key = "device",
default = null,
title = "Device",
name = "Device",
description = "The name of the industrial design.",
)
val display by stringOption(
key = "display",
default = null,
title = "Display",
name = "Display",
description = "A build ID string meant for displaying to the user.",
)
val fingerprint by stringOption(
key = "fingerprint",
default = null,
title = "Fingerprint",
name = "Fingerprint",
description = "A string that uniquely identifies this build.",
)
val hardware by stringOption(
key = "hardware",
default = null,
title = "Hardware",
name = "Hardware",
description = "The name of the hardware (from the kernel command line or /proc).",
)
val host by stringOption(
key = "host",
default = null,
title = "Host",
name = "Host",
description = "The host.",
)
val id by stringOption(
key = "id",
default = null,
title = "ID",
name = "ID",
description = "Either a changelist number, or a label like \"M4-rc20\".",
)
val manufacturer by stringOption(
key = "manufacturer",
default = null,
title = "Manufacturer",
name = "Manufacturer",
description = "The manufacturer of the product/hardware.",
)
val model by stringOption(
key = "model",
default = null,
title = "Model",
name = "Model",
description = "The end-user-visible name for the end product.",
)
val odmSku by stringOption(
key = "odm-sku",
default = null,
title = "ODM SKU",
name = "ODM SKU",
description = "The SKU of the device as set by the original design manufacturer (ODM).",
)
val product by stringOption(
key = "product",
default = null,
title = "Product",
name = "Product",
description = "The name of the overall product.",
)
val radio by stringOption(
key = "radio",
default = null,
title = "Radio",
name = "Radio",
description = "This field was deprecated in API level 15. " +
"The radio firmware version is frequently not available when this class is initialized, " +
"leading to a blank or \"unknown\" value for this string. Use getRadioVersion() instead.",
"The radio firmware version is frequently not available when this class is initialized, " +
"leading to a blank or \"unknown\" value for this string. Use getRadioVersion() instead.",
)
val serial by stringOption(
key = "serial",
default = null,
title = "Serial",
name = "Serial",
description = "This field was deprecated in API level 26. Use getSerial() instead.",
)
val sku by stringOption(
key = "sku",
default = null,
title = "SKU",
name = "SKU",
description = "The SKU of the hardware (from the kernel command line).",
)
val socManufacturer by stringOption(
key = "soc-manufacturer",
default = null,
title = "SOC manufacturer",
name = "SOC manufacturer",
description = "The manufacturer of the device's primary system-on-chip.",
)
val socModel by stringOption(
key = "soc-model",
default = null,
title = "SOC model",
name = "SOC model",
description = "The model name of the device's primary system-on-chip.",
)
val tags by stringOption(
key = "tags",
default = null,
title = "Tags",
name = "Tags",
description = "Comma-separated tags describing the build, like \"unsigned,debug\".",
)
val time by longOption(
key = "time",
default = null,
title = "Time",
name = "Time",
description = "The time at which the build was produced, given in milliseconds since the UNIX epoch.",
)
val type by stringOption(
key = "type",
default = null,
title = "Type",
name = "Type",
description = "The type of build, like \"user\" or \"eng\".",
)
val user by stringOption(
key = "user",
default = null,
title = "User",
name = "User",
description = "The user.",
)
@@ -210,5 +186,5 @@ val spoofBuildInfoPatch = bytecodePatch(
)
},
)
)
}

View File

@@ -1,18 +1,18 @@
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.intOption
import app.revanced.patcher.patch.stringOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
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.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.mutable.MutableMethod
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.Locale
import java.util.*
@Suppress("unused")
val spoofSimProviderPatch = bytecodePatch(
@@ -23,13 +23,11 @@ val spoofSimProviderPatch = bytecodePatch(
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }
fun isoCountryPatchOption(
key: String,
title: String,
name: String,
) = stringOption(
key,
name,
null,
countries,
title,
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
false,
validator = { it: String? -> it == null || it.uppercase() in countries.values },
@@ -37,39 +35,29 @@ val spoofSimProviderPatch = bytecodePatch(
fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999)
val networkCountryIso by isoCountryPatchOption(
"networkCountryIso",
"Network ISO country code",
)
val networkCountryIso by isoCountryPatchOption("Network ISO country code")
val networkOperator by intOption(
key = "networkOperator",
title = "MCC+MNC network operator code",
name = "MCC+MNC network operator code",
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the network operator.",
validator = { isMccMncValid(it) }
)
val networkOperatorName by stringOption(
key = "networkOperatorName",
title = "Network operator name",
name = "Network operator name",
description = "The full name of the network operator.",
)
val simCountryIso by isoCountryPatchOption(
"simCountryIso",
"SIM ISO country code",
)
val simCountryIso by isoCountryPatchOption("SIM ISO country code")
val simOperator by intOption(
key = "simOperator",
title = "MCC+MNC SIM operator code",
name = "MCC+MNC SIM operator code",
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the SIM operator.",
validator = { isMccMncValid(it) }
)
val simOperatorName by stringOption(
key = "simOperatorName",
title = "SIM operator name",
name = "SIM operator name",
description = "The full name of the SIM operator.",
)

View File

@@ -9,9 +9,6 @@ import app.revanced.util.getNode
import org.w3c.dom.Element
import java.io.File
val customNetworkSecurityPatch = resourcePatch(
name = "Custom network security",
description = "Allows trusting custom certificate authorities for a specific domain.",
@@ -19,24 +16,21 @@ val customNetworkSecurityPatch = resourcePatch(
) {
val targetDomains by stringsOption(
key = "targetDomains",
title = "Target domains",
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
)
val includeSubdomains by booleanOption(
key = "includeSubdomains",
title = "Include subdomains",
name = "Include subdomains",
description = "Applies the configuration to all subdomains of the target domains.",
default = false,
required = true
)
val customCAFilePaths by stringsOption(
key = "customCAFilePaths",
title = "Custom CA file paths",
name = "Custom CA file paths",
description = """
List of paths to files in PEM or DER format (one file path per entry).
@@ -51,37 +45,29 @@ val customNetworkSecurityPatch = resourcePatch(
)
val allowUserCerts by booleanOption(
key = "allowUserCerts",
title = "Trust user added CAs",
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
)
val allowSystemCerts by booleanOption(
key = "allowSystemCerts",
title = "Trust system CAs",
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
)
val allowCleartextTraffic by booleanOption(
key = "allowCleartextTraffic",
title = "Allow cleartext traffic (HTTP)",
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
)
val overridePins by booleanOption(
key = "overridePins",
title = "Override certificate pinning",
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
)

View File

@@ -28,7 +28,7 @@ val exportInternalDataDocumentsProviderPatch = resourcePatch(
.asSequence()
.any { it.attributes.getNamedItem("android:name")?.nodeValue == documentsProviderClass }
) {
return@execute
return@apply
}
val authority =

View File

@@ -14,8 +14,7 @@ val hexPatch = rawResourcePatch(
use = false,
) {
val replacements by stringsOption(
key = "replacements",
title = "Replacements",
name = "Replacements",
description = """
Hexadecimal patterns to search for and replace with another in a target file.

View File

@@ -33,10 +33,9 @@ val changePackageNamePatch = resourcePatch(
use = false,
) {
packageNameOption = stringOption(
key = "packageName",
default = "Default",
values = mapOf("Default" to "Default"),
title = "Package name",
name = "Package name",
description = "The name of the package to rename the app to.",
required = true,
) {
@@ -44,17 +43,15 @@ val changePackageNamePatch = resourcePatch(
}
val updatePermissions by booleanOption(
key = "updatePermissions",
default = false,
title = "Update permissions",
name = "Update permissions",
description = "Update compatibility receiver permissions. " +
"Enabling this can fix installation errors, but this can also break features in certain apps.",
)
val updateProviders by booleanOption(
key = "updateProviders",
default = false,
title = "Update providers",
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.",
)

View File

@@ -17,7 +17,7 @@ val removeShareTargetsPatch = resourcePatch(
try {
document("res/xml/shortcuts.xml")
} catch (_: FileNotFoundException) {
return@execute Logger.getLogger(this::class.java.name).warning(
return@apply Logger.getLogger(this::class.java.name).warning(
"The app has no shortcuts. No changes applied.")
}.use { document ->
val rootNode = document.getNode("shortcuts") as? Element ?: return@use

View File

@@ -22,8 +22,7 @@ val enableRomSignatureSpoofing = resourcePatch(
use = false,
) {
val signatureOrPath by stringOption(
key = "signatureOrApkFilePath",
title = "Signature or APK file path",
name = "Signature or APK file path",
validator = validator@{ signature ->
signature ?: return@validator false

View File

@@ -13,13 +13,12 @@ val changeVersionCodePatch = resourcePatch(
use = false,
) {
val versionCode by intOption(
key = "versionCode",
default = Int.MAX_VALUE,
values = mapOf(
"Lowest" to 1,
"Highest" to Int.MAX_VALUE,
),
title = "Version code",
name = "Version code",
description = "The version code to use. Using the highest value turns off app store " +
"updates and allows downgrading an existing app install to an older app version.",
required = true,

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.com.sbs.ondemand.tv
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch
import app.revanced.util.returnEarly

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.disneyplus.ads
package app.revanced.patches.disneyplus
import app.revanced.patcher.fingerprint

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.disneyplus.ads
package app.revanced.patches.disneyplus
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused")

View File

@@ -19,18 +19,16 @@ val spoofFeaturesPatch = bytecodePatch(
dependsOn(spoofBuildInfoPatch)
val featuresToEnable by stringsOption(
key = "featuresToEnable",
default = listOf(
"com.google.android.apps.photos.NEXUS_PRELOAD",
"com.google.android.apps.photos.nexus_preload",
),
title = "Features to enable",
name = "Features to enable",
description = "Google Pixel exclusive features to enable. Features up to Pixel XL enable the unlimited storage feature.",
required = true,
)
val featuresToDisable by stringsOption(
key = "featuresToDisable",
default = listOf(
"com.google.android.apps.photos.PIXEL_2017_PRELOAD",
"com.google.android.apps.photos.PIXEL_2018_PRELOAD",
@@ -49,7 +47,7 @@ val spoofFeaturesPatch = bytecodePatch(
"com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE",
"com.google.android.feature.PIXEL_2025_EXPERIENCE",
),
title = "Features to disable",
name = "Features to disable",
description = "Google Pixel exclusive features to disable." +
"Features after Pixel XL may have to be disabled for unlimited storage depending on the device.",
required = true,

View File

@@ -30,50 +30,44 @@ val hideNavigationButtonsPatch = bytecodePatch(
dependsOn(sharedExtensionPatch)
val hideHome by booleanOption(
key = "hideHome",
default = false,
title = "Hide Home",
name = "Hide Home",
description = "Permanently hides the Home button. App starts at next available tab." // On the "homecoming" / current instagram layout.
)
val hideReels by booleanOption(
key = "hideReels",
default = true,
title = "Hide Reels",
name = "Hide Reels",
description = "Permanently hides the Reels button."
)
val hideDirect by booleanOption(
key = "hideDirect",
default = false,
title = "Hide Direct",
name = "Hide Direct",
description = "Permanently hides the Direct button."
)
val hideSearch by booleanOption(
key = "hideSearch",
default = false,
title = "Hide Search",
name = "Hide Search",
description = "Permanently hides the Search button."
)
val hideProfile by booleanOption(
key = "hideProfile",
default = false,
title = "Hide Profile",
name = "Hide Profile",
description = "Permanently hides the Profile button."
)
val hideCreate by booleanOption(
key = "hideCreate",
default = true,
title = "Hide Create",
name = "Hide Create",
description = "Permanently hides the Create button."
)
apply {
if (!hideHome!! &&!hideReels!! && !hideDirect!! && !hideSearch!! && !hideProfile!! && !hideCreate!!) {
return@execute Logger.getLogger(this::class.java.name).warning(
return@apply Logger.getLogger(this::class.java.name).warning(
"No hide navigation buttons options are enabled. No changes made."
)
}

View File

@@ -23,9 +23,8 @@ val changeLinkSharingDomainPatch = bytecodePatch(
dependsOn(sharedExtensionPatch)
val customDomainHost by stringOption(
key = "domainName",
default = "imginn.com",
title = "Domain name",
name = "Domain name",
description = "The domain name to use when sharing links."
)

View File

@@ -1,7 +1,7 @@
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
package app.revanced.patches.instagram.reels
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.instagram.reels.clipsSwipeRefreshLayoutOnInterceptTouchEventFingerprint
import app.revanced.patches.instagram.reels.clipsViewPagerImplGetViewAtIndexFingerprint
import app.revanced.util.returnEarly
@Suppress("unused")

View File

@@ -1,6 +1,5 @@
package app.revanced.patches.piccomafr.misc
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.stringOption
import app.revanced.util.returnEarly
@@ -32,9 +31,8 @@ val spoofAndroidDeviceIdPatch = bytecodePatch(
)
val androidDeviceId by stringOption(
key = "android-device-id",
name = "Android device ID",
default = "0011223344556677",
title = "Android device ID",
description = "The Android device ID to spoof to.",
required = true,
) { it!!.matches("[A-Fa-f0-9]{16}".toRegex()) }

View File

@@ -20,15 +20,13 @@ fun spoofClientPatch(
) {
block(
stringOption(
"client-id",
null,
null,
"OAuth client ID",
"The Reddit OAuth client ID. " +
"You can get your client ID from https://www.reddit.com/prefs/apps. " +
"The application type has to be \"Installed app\" " +
"and the redirect URI has to be set to \"$redirectUri\".",
true,
name = "OAuth client ID",
values = null,
description = "The Reddit OAuth client ID. " +
"You can get your client ID from https://www.reddit.com/prefs/apps. " +
"The application type has to be \"Installed app\" " +
"and the redirect URI has to be set to \"$redirectUri\".",
required = true,
),
)
}

View File

@@ -1,11 +1,11 @@
package app.revanced.patches.reddit.customclients.infinityforreddit.api
import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.toInstructions
import app.revanced.patcher.extensions.toInstructions
import app.revanced.patches.reddit.customclients.spoofClientPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
val spoofClientPatch = spoofClientPatch(redirectUri = "infinity://localhost") { clientIdOption ->
compatibleWith(

View File

@@ -65,7 +65,8 @@ private val USER_CUSTOM_ADAPTIVE_FILE_NAMES = arrayOf(
"$LAUNCHER_ADAPTIVE_FOREGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.png"
)
private const val USER_CUSTOM_MONOCHROME_FILE_NAME = "$LAUNCHER_ADAPTIVE_MONOCHROME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.xml"
private const val USER_CUSTOM_MONOCHROME_FILE_NAME =
"$LAUNCHER_ADAPTIVE_MONOCHROME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.xml"
private const val USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME = "${NOTIFICATION_ICON_NAME}_$CUSTOM_USER_ICON_STYLE_NAME.xml"
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/patches/CustomBrandingPatch;"
@@ -92,14 +93,12 @@ internal fun baseCustomBrandingPatch(
"Branding cannot be changed for mounted (root) installations."
) {
val customName by stringOption(
key = "customName",
title = "App name",
name = "App name",
description = "Custom app name."
)
val customIcon by stringOption(
key = "customIcon",
title = "Custom icon",
name = "Custom icon",
description = """
Folder with images to use as a custom icon.
@@ -193,7 +192,7 @@ internal fun baseCustomBrandingPatch(
addResources(addResourcePatchName, "layout.branding.customBrandingPatch")
preferenceScreen.addPreferences(
if (customName != null ) {
if (customName != null) {
ListPreference(
key = "revanced_custom_branding_name",
entriesKey = "revanced_custom_branding_name_custom_entries",
@@ -332,7 +331,7 @@ internal fun baseCustomBrandingPatch(
"@string/revanced_custom_branding_name_entry_2"
)
for (appNameIndex in 1 .. numberOfPresetAppNames) {
for (appNameIndex in 1..numberOfPresetAppNames) {
fun aliasName(name: String): String = ".revanced_" + name + '_' + appNameIndex
val useCustomNameLabel = (useCustomName && appNameIndex == numberOfPresetAppNames)
@@ -413,8 +412,8 @@ internal fun baseCustomBrandingPatch(
var copiedFiles = false
// For each source folder, copy the files to the target resource directories.
iconPathFile.listFiles {
file -> file.isDirectory && file.name in mipmapDirectories
iconPathFile.listFiles { file ->
file.isDirectory && file.name in mipmapDirectories
}!!.forEach { dpiSourceFolder ->
val targetDpiFolder = resourceDirectory.resolve(dpiSourceFolder.name)
if (!targetDpiFolder.exists()) {
@@ -427,8 +426,9 @@ internal fun baseCustomBrandingPatch(
}!!
if (customFiles.isNotEmpty() && customFiles.size != USER_CUSTOM_ADAPTIVE_FILE_NAMES.size) {
throw PatchException("Must include all required icon files " +
"but only found " + customFiles.map { it.name })
throw PatchException(
"Must include all required icon files " +
"but only found " + customFiles.map { it.name })
}
customFiles.forEach { imgSourceFile ->
@@ -456,9 +456,11 @@ internal fun baseCustomBrandingPatch(
}
if (!copiedFiles) {
throw PatchException("Expected to find directories and files: "
+ USER_CUSTOM_ADAPTIVE_FILE_NAMES.contentToString()
+ "\nBut none were found in the provided option file path: " + iconPathFile.absolutePath)
throw PatchException(
"Expected to find directories and files: "
+ USER_CUSTOM_ADAPTIVE_FILE_NAMES.contentToString()
+ "\nBut none were found in the provided option file path: " + iconPathFile.absolutePath
)
}
}

View File

@@ -70,7 +70,7 @@ internal val darkThemeBackgroundColorOption = stringOption(
"Dark orange" to "#291800",
"Dark red" to "#290000",
),
title = "Dark theme background color",
name = "Dark theme background color",
description = THEME_COLOR_OPTION_DESCRIPTION
)

View File

@@ -59,13 +59,12 @@ fun gmsCoreSupportPatch(
"using a GmsCore instead of Google Play Services.",
) {
val gmsCoreVendorGroupIdOption = stringOption(
key = "gmsCoreVendorGroupId",
default = "app.revanced",
values =
mapOf(
"ReVanced" to "app.revanced",
),
title = "GmsCore vendor group ID",
name = "GmsCore vendor group ID",
description = "The vendor's group ID for GmsCore.",
required = true,
) { it!!.matches(Regex(PACKAGE_NAME_REGEX_PATTERN)) }
@@ -83,7 +82,7 @@ fun gmsCoreSupportPatch(
val transformations = mutableListOf<() -> Unit>()
classDefs.forEach { classDef ->
val mutableClass by lazy { classDef.getOrReplaceMutable() }
val mutableClass by lazy { classDefs.getOrReplaceMutable(classDef) }
classDef.methods.forEach classLoop@{ method ->
val implementation = method.implementation ?: return@classLoop

View File

@@ -14,7 +14,7 @@ val disableLicenseCheckPatch = bytecodePatch(
apply {
if (processLicenseResponseFingerprint.methodOrNull == null || validateLicenseResponseFingerprint.methodOrNull == null) {
return@execute Logger.getLogger(this::class.java.name)
return@apply Logger.getLogger(this::class.java.name)
.warning("Could not find Pairip licensing check. No changes applied.")
}

View File

@@ -87,43 +87,38 @@ val customThemePatch = resourcePatch(
dependsOn(customThemeBytecodePatch)
val backgroundColor by stringOption(
key = "backgroundColor",
default = "@android:color/black",
title = "Primary background color",
name = "Primary background color",
description = "The background color. Can be a hex color or a resource reference.",
required = true,
)
val overridePlayerGradientColor by booleanOption(
key = "overridePlayerGradientColor",
default = false,
title = "Override player gradient color",
name = "Override player gradient color",
description =
"Apply primary background color to the player gradient color, which changes dynamically with the song.",
required = false,
)
val backgroundColorSecondary by stringOption(
key = "backgroundColorSecondary",
default = "#FF121212",
title = "Secondary background color",
name = "Secondary background color",
description = "The secondary background color. (e.g. playlist list in home, player artist, song credits). " +
"Can be a hex color or a resource reference.\",",
required = true,
)
val accentColor by stringOption(
key = "accentColor",
default = "#FF1ED760",
title = "Accent color",
name = "Accent color",
description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.",
required = true,
)
val accentColorPressed by stringOption(
key = "accentColorPressed",
default = "#FF1ABC54",
title = "Pressed accent color",
name = "Pressed accent color",
description = "The color when accented buttons are pressed, by default slightly darker than accent. " +
"Can be a hex color or a resource reference.",
required = true,

View File

@@ -30,9 +30,8 @@ val changeLyricsProviderPatch = bytecodePatch(
compatibleWith("com.spotify.music")
val lyricsProviderHost by stringOption(
key = "lyricsProviderHost",
default = "lyrics.natanchiodi.fr",
title = "Lyrics provider host",
name = "Lyrics provider host",
description = "The domain name or IP address of a custom lyrics provider.",
required = false,
) {

View File

@@ -19,9 +19,8 @@ import java.util.logging.Logger
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch;"
internal val domainNameOption = stringOption(
key = "domainName",
default = "fxtwitter.com",
title = "Domain name",
name = "Domain name",
description = "The domain name to use when sharing links.",
required = true,
) {

View File

@@ -16,9 +16,8 @@ val hideNavigationButtonsPatch = bytecodePatch(
val hideOptions = AllowedNavigationItems.entries.associateWith {
booleanOption(
key = it.key,
name = it.optionName,
default = it.defaultHideOption,
title = it.title,
description = it.description,
)
}
@@ -28,7 +27,7 @@ val hideNavigationButtonsPatch = bytecodePatch(
val allowedItems = hideOptions.filter { (option, enabled) -> enabled.value != true }
if (allowedItems.size == AllowedNavigationItems.entries.size) {
return@execute Logger.getLogger(this::class.java.name).warning(
return@apply Logger.getLogger(this::class.java.name).warning(
"No hide navigation buttons options are enabled. No changes applied."
)
}
@@ -67,8 +66,7 @@ private enum class AllowedNavigationItems(
CAMERA(true, "Camera", 6),
MARKETPLACE(true, "Marketplace", 8);
val key = "hide$itemName"
val title = "Hide $itemName"
val optionName = "Hide $itemName"
val description = "Permanently hides the $itemName button."
fun buildAllowInstruction(): String =

View File

@@ -43,7 +43,7 @@ val disableDoubleTapActionsPatch = bytecodePatch(
// Show a message if users have version constrain off and are patching the oldest version,
// just to prevent spamming a cryptic error message the user may not understand
// and don't add in app settings that won't work.
return@execute Logger.getLogger(this::class.java.name).warning(
return@apply Logger.getLogger(this::class.java.name).warning(
"Disable double tap actions requires 20.14.43+"
)
}

View File

@@ -31,7 +31,7 @@ val seekbarThumbnailsPatch = bytecodePatch(
if (is_20_09_or_greater) {
// High quality seekbar thumbnails is partially broken in 20.09
// and the code is completely removed in 20.10+
return@execute
return@apply
}
addResources("youtube", "layout.seekbar.seekbarThumbnailsPatch")

View File

@@ -111,8 +111,7 @@ val changeHeaderPatch = resourcePatch(
)
val custom by stringOption(
key = "custom",
title = "Custom header logo",
name = "Custom header logo",
description = """
Folder with images to use as a custom header logo.

View File

@@ -1,11 +1,23 @@
package app.revanced.patches.youtube.layout.hide.infocards
import app.revanced.patcher.accessFlags
import app.revanced.patcher.fingerprint
import app.revanced.patcher.addString
import app.revanced.patcher.firstMethodBuilder
import app.revanced.patcher.instructions
import app.revanced.patcher.parameterTypes
import app.revanced.patcher.returnType
import app.revanced.patcher.string
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val infocardsIncognitoMatch = firstMethodBuilder {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returnType("V")
parameterTypes("L", "J")
instructions(string("vibrator"))
}
internal val infocardsIncognitoFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/Boolean;")

View File

@@ -25,11 +25,9 @@ internal var drawerResourceId = -1L
private set
private val hideInfocardsResourcePatch = resourcePatch {
dependsOn(resourceMappingPatch
)
apply {
dependsOn(resourceMappingPatch)
apply {
drawerResourceId = getResourceId(
ResourceType.ID,
"info_cards_drawer_header",

View File

@@ -27,16 +27,14 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import java.util.logging.Logger
internal val hideShortsAppShortcutOption = booleanOption(
key = "hideShortsAppShortcut",
name = "Hide Shorts app shortcut",
default = false,
title = "Hide Shorts app shortcut",
description = "Permanently hides the shortcut to open Shorts when long pressing the app icon in your launcher.",
)
internal val hideShortsWidgetOption = booleanOption(
key = "hideShortsWidget",
name = "Hide Shorts widget",
default = false,
title = "Hide Shorts widget",
description = "Permanently hides the launcher widget Shorts button.",
)

View File

@@ -51,7 +51,7 @@ val wideSearchbarPatch = bytecodePatch(
// YT removed the legacy text search text field all code required to use it.
// This functionality could be restored by adding a search text field to the toolbar
// with a listener that artificially clicks the toolbar search button.
return@execute Logger.getLogger(this::class.java.name).warning(
return@apply Logger.getLogger(this::class.java.name).warning(
"Wide searchbar is not compatible with 20.31+"
)
}

View File

@@ -151,7 +151,7 @@ val seekbarColorPatch = bytecodePatch(
// region apply seekbar custom color to splash screen animation.
if (!is_19_34_or_greater) {
return@execute // 19.25 does not have a cairo launch animation.
return@apply // 19.25 does not have a cairo launch animation.
}
// Hook the splash animation to set the a seekbar color.

View File

@@ -46,7 +46,7 @@ val themePatch = baseThemePatch(
"Light orange" to "#FFE6CC",
"Light red" to "#FFD6D6",
),
title = "Light theme background color",
name = "Light theme background color",
description = THEME_COLOR_OPTION_DESCRIPTION
)

View File

@@ -38,7 +38,7 @@ val fixPlaybackSpeedWhilePlayingPatch = bytecodePatch {
apply {
if (!is_19_34_or_greater) {
return@execute
return@apply
}
playbackSpeedInFeedsFingerprint.method.apply {

View File

@@ -207,7 +207,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
}
if (is_20_39_or_greater) {
return@execute Logger.getLogger(this::class.java.name).warning(
return@apply Logger.getLogger(this::class.java.name).warning(
"20.39+ Navigation tab activity button selected state is not yet fixed."
)
}

View File

@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeH
import app.revanced.patches.youtube.misc.settings.settingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
internal var videoQualityBottomSheetListFragmentTitle = -1L
internal var videoQualityBottomSheetListFragmentname = -1L
private set
internal var videoQualityQuickMenuAdvancedMenuDescription = -1L
private set
@@ -48,7 +48,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
)
// Used for the old type of the video quality menu.
videoQualityBottomSheetListFragmentTitle = getResourceId(
videoQualityBottomSheetListFragmentname = getResourceId(
ResourceType.LAYOUT,
"video_quality_bottom_sheet_list_fragment_title",
)

View File

@@ -1,10 +1,6 @@
package app.revanced.util
import app.revanced.patcher.FingerprintBuilder
import com.android.tools.smali.dexlib2.mutable.MutableClassDef
import com.android.tools.smali.dexlib2.mutable.MutableField
import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable
import com.android.tools.smali.dexlib2.mutable.MutableMethod
import app.revanced.patcher.extensions.*
import app.revanced.patcher.firstClassDefMutable
import app.revanced.patcher.firstClassDefMutableOrNull
@@ -26,6 +22,10 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.mutable.MutableClassDef
import com.android.tools.smali.dexlib2.mutable.MutableField
import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable
import com.android.tools.smali.dexlib2.mutable.MutableMethod
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.*
@@ -805,7 +805,7 @@ fun BytecodePatchContext.forEachInstructionAsSequence(
block: (classDef: MutableClassDef, method: MutableMethod, matchingIndex: Int, instruction: Instruction) -> Unit,
) {
classDefs.asSequence().flatMap { classDef ->
val mutableClassDef by lazy { classDef.getOrReplaceMutable() }
val mutableClassDef by lazy { classDefs.getOrReplaceMutable(classDef) }
classDef.methods.asSequence().flatMap { method ->
val instructions =