feat(youtube/patch-options): all patch options are now moved to the appropriate patch

This commit is contained in:
inotia00 2023-05-08 04:17:04 +09:00
parent e3b73716d2
commit 40e2761033
13 changed files with 191 additions and 299 deletions

View File

@ -1,135 +0,0 @@
package app.revanced.patches.shared.patch.options
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.*
import app.revanced.patches.shared.annotation.RVXCompatibility
@Patch
@Name("patch-options")
@Description("Create an options.toml file.")
@RVXCompatibility
@Version("0.0.1")
class PatchOptions : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
return PatchResultSuccess()
}
/*
* Custom Branding Name
*/
companion object : OptionsContainer() {
/**
* Custom Branding Name (YouTube)
*/
internal var YouTubeAppName: String? by option(
PatchOption.StringOption(
key = "YouTubeAppName",
default = "ReVanced Extended",
title = "Application Name of YouTube",
description = "The name of the YouTube it will show on your home screen."
)
)
/**
* Custom Package Name (YouTube)
*/
internal var YouTubePackageName: String? by option(
PatchOption.StringOption(
key = "YouTubePackageName",
default = "app.rvx.android.youtube",
title = "Package Name of YouTube",
description = "The package name of the YouTube. (NON-ROOT user only)"
)
)
/**
* Custom Branding Full Name (YouTube Music)
*/
internal var MusicAppNameFull: String? by option(
PatchOption.StringOption(
key = "MusicAppNameFull",
default = "ReVanced Music Extended",
title = "Application Name of YouTube Music",
description = "The name of the YouTube Music it will show on your notification panel."
)
)
/**
* Custom Branding Short Name (YouTube Music)
*/
internal var MusicAppNameShort: String? by option(
PatchOption.StringOption(
key = "MusicAppNameShort",
default = "YTM Extended",
title = "Application Name of YouTube Music",
description = "The name of the YouTube Music it will show on your home screen."
)
)
/**
* Custom Package Name (YouTube Music)
*/
internal var MusicPackageName: String? by option(
PatchOption.StringOption(
key = "MusicPackageName",
default = "app.rvx.android.apps.youtube.music",
title = "Package Name of YouTube Music",
description = "The package name of the YouTube Music. (NON-ROOT user only)"
)
)
/**
* Custom Double-tap to seek Values
*/
internal var CustomDoubleTapLengthArrays: String? by option(
PatchOption.StringOption(
key = "CustomDoubleTapLengthArrays",
default = "3, 5, 10, 15, 20, 30, 60, 120, 180",
title = "Double-tap to seek Values",
description = "A list of custom double-tap to seek lengths. Be sure to separate them with commas (,)."
)
)
/**
* Custom Speed Values
*/
internal var CustomSpeedArrays: String? by option(
PatchOption.StringOption(
key = "CustomSpeedArrays",
default = "0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 3.0, 5.0",
title = "Custom Speed Values",
description = "A list of custom video speeds. Be sure to separate them with commas (,)."
)
)
/**
* Theme
*/
internal var darkThemeBackgroundColor: String? by option(
PatchOption.StringOption(
key = "darkThemeBackgroundColor",
default = "@android:color/black",
title = "Background color for the dark theme",
description = "The background color of the dark theme. Can be a hex color or a resource reference."
)
)
/**
* Resumed progressbar color in playlists and history
*/
internal var resumedProgressBarColor: String? by option(
PatchOption.StringOption(
key = "resumedProgressBarColor",
default = "#ffff0000",
title = "Resumed progressbar color",
description = "Resumed progressbar color in playlists and history. Can be a hex color or a resource reference."
)
)
}
}

View File

@ -0,0 +1,47 @@
package app.revanced.patches.shared.patch.packagename
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.*
import app.revanced.patches.shared.annotation.RVXCompatibility
@Patch
@Name("custom-package-name")
@Description("Specifies the package name for YouTube and YT Music in the MicroG build.")
@RVXCompatibility
@Version("0.0.1")
class PackageNamePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
return PatchResultSuccess()
}
companion object : OptionsContainer() {
/**
* Custom Package Name (YouTube)
*/
internal var YouTubePackageName: String? by option(
PatchOption.StringOption(
key = "YouTubePackageName",
default = "app.rvx.android.youtube",
title = "Package Name of YouTube",
description = "The package name of the YouTube. (NON-ROOT user only)"
)
)
/**
* Custom Package Name (YouTube Music)
*/
internal var MusicPackageName: String? by option(
PatchOption.StringOption(
key = "MusicPackageName",
default = "app.rvx.android.apps.youtube.music",
title = "Package Name of YouTube Music",
description = "The package name of the YouTube Music. (NON-ROOT user only)"
)
)
}
}

View File

@ -5,25 +5,17 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.resources.ResourceHelper.updatePatchStatusLabel import app.revanced.util.resources.ResourceHelper.updatePatchStatusLabel
import org.w3c.dom.Element import org.w3c.dom.Element
@Patch @Patch
@Name("custom-branding-name") @Name("custom-branding-name")
@DependsOn( @DependsOn([SettingsPatch::class])
[
PatchOptions::class,
SettingsPatch::class
]
)
@Description("Changes the YouTube launcher name to your choice (defaults to ReVanced Extended).") @Description("Changes the YouTube launcher name to your choice (defaults to ReVanced Extended).")
@YouTubeCompatibility @YouTubeCompatibility
@Version("0.0.1") @Version("0.0.1")
@ -32,7 +24,7 @@ class CustomBrandingNamePatch : ResourcePatch {
// App name // App name
val resourceFileNames = arrayOf("strings.xml") val resourceFileNames = arrayOf("strings.xml")
val appName = PatchOptions.YouTubeAppName val appName = YouTubeAppName
context.forEach { context.forEach {
if (!it.name.startsWithAny(*resourceFileNames)) return@forEach if (!it.name.startsWithAny(*resourceFileNames)) return@forEach
@ -58,4 +50,14 @@ class CustomBrandingNamePatch : ResourcePatch {
return PatchResultSuccess() return PatchResultSuccess()
} }
companion object : OptionsContainer() {
var YouTubeAppName: String? by option(
PatchOption.StringOption(
key = "YouTubeAppName",
default = "ReVanced Extended",
title = "Application Name of YouTube",
description = "The name of the YouTube it will show on your home screen."
)
)
}
} }

View File

@ -4,33 +4,27 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.OptionsContainer
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.resources.ResourceHelper.addEntryValues import app.revanced.util.resources.ResourceHelper.addEntryValues
import app.revanced.util.resources.ResourceUtils import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.copyXmlNode
@Patch @Patch
@Name("custom-double-tap-length") @Name("custom-double-tap-length")
@Description("Add 'double-tap to seek' value.") @Description("Add 'double-tap to seek' value.")
@DependsOn( @DependsOn([SettingsPatch::class])
[
PatchOptions::class,
SettingsPatch::class
]
)
@YouTubeCompatibility @YouTubeCompatibility
@Version("0.0.1") @Version("0.0.1")
class DoubleTapLengthPatch : ResourcePatch { class DoubleTapLengthPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
val arrayPath = "res/values-v21/arrays.xml"
val entriesName = "double_tap_length_entries"
val entryValueName = "double_tap_length_values"
/** /**
* Copy arrays * Copy arrays
@ -43,15 +37,15 @@ class DoubleTapLengthPatch : ResourcePatch {
) )
) )
val speed = PatchOptions.CustomDoubleTapLengthArrays val length = DoubleTapLengthArrays
?: return PatchResultError("Invalid double-tap length array.") ?: return PatchResultError("Invalid double-tap length array.")
val splits = speed.replace(" ","").split(",") val splits = length.replace(" ","").split(",")
if (splits.isEmpty()) throw IllegalArgumentException("Invalid speed elements") if (splits.isEmpty()) throw IllegalArgumentException("Invalid double-tap length elements")
val speedElements = splits.map { it } val lengthElements = splits.map { it }
for (index in 0 until splits.count()) { for (index in 0 until splits.count()) {
context.addEntryValues(TARGET_ARRAY_PATH, speedElements[index], TARGET_ENTRY_VALUE_NAME) context.addEntryValues(arrayPath, lengthElements[index], entryValueName)
context.addEntryValues(TARGET_ARRAY_PATH, speedElements[index], TARGET_ENTRIES_NAME) context.addEntryValues(arrayPath, lengthElements[index], entriesName)
} }
SettingsPatch.updatePatchStatus("custom-double-tap-length") SettingsPatch.updatePatchStatus("custom-double-tap-length")
@ -59,9 +53,14 @@ class DoubleTapLengthPatch : ResourcePatch {
return PatchResultSuccess() return PatchResultSuccess()
} }
private companion object { companion object : OptionsContainer() {
private const val TARGET_ARRAY_PATH = "res/values-v21/arrays.xml" var DoubleTapLengthArrays: String? by option(
private const val TARGET_ENTRIES_NAME = "double_tap_length_entries" PatchOption.StringOption(
private const val TARGET_ENTRY_VALUE_NAME = "double_tap_length_values" key = "DoubleTapLengthArrays",
default = "3, 5, 10, 15, 20, 30, 60, 120, 180",
title = "Double-tap to seek Values",
description = "A list of custom double-tap to seek lengths. Be sure to separate them with commas (,)."
)
)
} }
} }

View File

@ -4,13 +4,10 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions
import app.revanced.patches.youtube.layout.etc.theme.patch.GeneralThemePatch.Companion.isMonetPatchIncluded import app.revanced.patches.youtube.layout.etc.theme.patch.GeneralThemePatch.Companion.isMonetPatchIncluded
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.resources.ResourceHelper.updatePatchStatusTheme import app.revanced.util.resources.ResourceHelper.updatePatchStatusTheme
@ -22,7 +19,6 @@ import org.w3c.dom.Element
@DependsOn( @DependsOn(
[ [
GeneralThemePatch::class, GeneralThemePatch::class,
PatchOptions::class,
SettingsPatch::class SettingsPatch::class
] ]
) )
@ -31,9 +27,7 @@ import org.w3c.dom.Element
class ThemePatch : ResourcePatch { class ThemePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
arrayOf("values", "values-v31").forEach { arrayOf("values", "values-v31").forEach { context.setTheme(it) }
context.setTheme(it)
}
val currentTheme = if (isMonetPatchIncluded) "mix" else "amoled" val currentTheme = if (isMonetPatchIncluded) "mix" else "amoled"
@ -41,22 +35,32 @@ class ThemePatch : ResourcePatch {
return PatchResultSuccess() return PatchResultSuccess()
} }
private companion object {
private fun ResourceContext.setTheme(valuesPath: String) {
this.xmlEditor["res/$valuesPath/colors.xml"].use { editor ->
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
for (i in 0 until resourcesNode.childNodes.length) { private fun ResourceContext.setTheme(valuesPath: String) {
val node = resourcesNode.childNodes.item(i) as? Element ?: continue this.xmlEditor["res/$valuesPath/colors.xml"].use { editor ->
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
node.textContent = when (node.getAttribute("name")) { for (i in 0 until resourcesNode.childNodes.length) {
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3", val node = resourcesNode.childNodes.item(i) as? Element ?: continue
"yt_black4", "yt_status_bar_background_dark", "material_grey_850" -> PatchOptions.darkThemeBackgroundColor!!
else -> continue node.textContent = when (node.getAttribute("name")) {
} "yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3",
"yt_black4", "yt_status_bar_background_dark", "material_grey_850" -> darkThemeBackgroundColor
else -> continue
} }
} }
} }
} }
companion object : OptionsContainer() {
var darkThemeBackgroundColor: String? by option(
PatchOption.StringOption(
key = "darkThemeBackgroundColor",
default = "@android:color/black",
title = "Background color for the dark theme",
description = "The background color of the dark theme. Can be a hex color or a resource reference."
)
)
}
} }

View File

@ -5,13 +5,10 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions
import app.revanced.patches.youtube.layout.seekbar.seekbarcolor.bytecode.patch.SeekbarColorBytecodePatch import app.revanced.patches.youtube.layout.seekbar.seekbarcolor.bytecode.patch.SeekbarColorBytecodePatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import org.w3c.dom.Element import org.w3c.dom.Element
@ -21,7 +18,6 @@ import org.w3c.dom.Element
@Description("Change seekbar color and progressbar color.") @Description("Change seekbar color and progressbar color.")
@DependsOn( @DependsOn(
[ [
PatchOptions::class,
SeekbarColorBytecodePatch::class, SeekbarColorBytecodePatch::class,
SettingsPatch::class SettingsPatch::class
] ]
@ -31,14 +27,14 @@ import org.w3c.dom.Element
class ThemePatch : ResourcePatch { class ThemePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
context.xmlEditor[RESOURCE_FILE_PATH].use { context.xmlEditor["res/drawable/resume_playback_progressbar_drawable.xml"].use {
it.file.doRecursively { it.file.doRecursively {
arrayOf("color").forEach replacement@{ replacement -> arrayOf("color").forEach replacement@{ replacement ->
if (it !is Element) return@replacement if (it !is Element) return@replacement
it.getAttributeNode("android:$replacement")?.let { attribute -> it.getAttributeNode("android:$replacement")?.let { attribute ->
if (attribute.textContent.startsWith("@color/")) if (attribute.textContent.startsWith("@color/"))
attribute.textContent = PatchOptions.resumedProgressBarColor!! attribute.textContent = resumedProgressBarColor
} }
} }
} }
@ -58,7 +54,15 @@ class ThemePatch : ResourcePatch {
return PatchResultSuccess() return PatchResultSuccess()
} }
private companion object {
const val RESOURCE_FILE_PATH = "res/drawable/resume_playback_progressbar_drawable.xml" companion object : OptionsContainer() {
var resumedProgressBarColor: String? by option(
PatchOption.StringOption(
key = "resumedProgressBarColor",
default = "#ffff0000",
title = "Resumed progressbar color",
description = "Resumed progressbar color in playlists and history. Can be a hex color or a resource reference."
)
)
} }
} }

View File

@ -8,7 +8,7 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions import app.revanced.patches.shared.patch.packagename.PackageNamePatch
import app.revanced.patches.youtube.misc.clientspoof.patch.ClientSpoofPatch import app.revanced.patches.youtube.misc.clientspoof.patch.ClientSpoofPatch
import app.revanced.patches.youtube.misc.microg.bytecode.fingerprints.* import app.revanced.patches.youtube.misc.microg.bytecode.fingerprints.*
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
@ -19,7 +19,7 @@ import app.revanced.util.microg.MicroGBytecodeHelper
@DependsOn( @DependsOn(
[ [
ClientSpoofPatch::class, ClientSpoofPatch::class,
PatchOptions::class PackageNamePatch::class
] ]
) )
@YouTubeCompatibility @YouTubeCompatibility
@ -36,7 +36,7 @@ class MicroGBytecodePatch : BytecodePatch(
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
val packageName = PatchOptions.YouTubePackageName!! val packageName = PackageNamePatch.YouTubePackageName!!
// apply common microG patch // apply common microG patch
MicroGBytecodeHelper.patchBytecode( MicroGBytecodeHelper.patchBytecode(

View File

@ -10,7 +10,7 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions import app.revanced.patches.shared.patch.packagename.PackageNamePatch
import app.revanced.patches.youtube.misc.microg.bytecode.patch.MicroGBytecodePatch import app.revanced.patches.youtube.misc.microg.bytecode.patch.MicroGBytecodePatch
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME
@ -26,9 +26,9 @@ import app.revanced.util.resources.ResourceHelper.setMicroG
@Description("Allows ReVanced to run without root and under a different package name with MicroG.") @Description("Allows ReVanced to run without root and under a different package name with MicroG.")
@DependsOn( @DependsOn(
[ [
PackageNamePatch::class,
SettingsPatch::class, SettingsPatch::class,
MicroGBytecodePatch::class, MicroGBytecodePatch::class,
PatchOptions::class
] ]
) )
@YouTubeCompatibility @YouTubeCompatibility
@ -36,7 +36,7 @@ import app.revanced.util.resources.ResourceHelper.setMicroG
class MicroGPatch : ResourcePatch { class MicroGPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
val packageName = PatchOptions.YouTubePackageName!! val packageName = PackageNamePatch.YouTubePackageName!!
/* /*
* Add settings * Add settings

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.customspeed.bytecode.fingerprints package app.revanced.patches.youtube.video.customspeed.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.customspeed.bytecode.fingerprints package app.revanced.patches.youtube.video.customspeed.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.customspeed.bytecode.fingerprints package app.revanced.patches.youtube.video.customspeed.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode

View File

@ -1,22 +1,25 @@
package app.revanced.patches.youtube.video.customspeed.bytecode.patch package app.revanced.patches.youtube.video.customspeed.patch
import app.revanced.extensions.toErrorResult import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.patches.youtube.video.customspeed.bytecode.fingerprints.* import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch.Companion.contexts
import app.revanced.patches.youtube.video.customspeed.fingerprints.*
import app.revanced.util.integrations.Constants.VIDEO_PATH import app.revanced.util.integrations.Constants.VIDEO_PATH
import app.revanced.util.resources.ResourceHelper.addEntries
import app.revanced.util.resources.ResourceHelper.addEntryValues
import app.revanced.util.resources.ResourceUtils.copyXmlNode
import org.jf.dexlib2.builder.instruction.BuilderArrayPayload import org.jf.dexlib2.builder.instruction.BuilderArrayPayload
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@ -24,11 +27,13 @@ import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
@Name("custom-speed-bytecode-patch") @Patch
@DependsOn([PatchOptions::class]) @Name("custom-video-speed")
@Description("Adds more video speed options.")
@DependsOn([SettingsPatch::class])
@YouTubeCompatibility @YouTubeCompatibility
@Version("0.0.1") @Version("0.0.1")
class CustomVideoSpeedBytecodePatch : BytecodePatch( class CustomVideoSpeedPatch : BytecodePatch(
listOf( listOf(
SpeedArrayGeneratorFingerprint, SpeedArrayGeneratorFingerprint,
SpeedLimiterFingerprint, SpeedLimiterFingerprint,
@ -36,10 +41,27 @@ class CustomVideoSpeedBytecodePatch : BytecodePatch(
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
val speed = PatchOptions.CustomSpeedArrays val arrayPath = "res/values/arrays.xml"
val entriesName = "revanced_custom_video_speed_entry"
val entryValueName = "revanced_custom_video_speed_entry_value"
val speed = CustomSpeedArrays
?: return PatchResultError("Invalid video speed array.") ?: return PatchResultError("Invalid video speed array.")
val splits = speed.replace(" ","").split(",") val splits = speed.replace(" ","").split(",")
if (splits.isEmpty()) throw IllegalArgumentException("Invalid speed elements") if (splits.isEmpty()) throw IllegalArgumentException("Invalid speed elements")
val speedElements = splits.map { it }
for (index in 0 until splits.count()) {
contexts.addEntries(
arrayPath, speedElements[index] + "x",
entriesName
)
contexts.addEntryValues(
arrayPath, speedElements[index],
entryValueName
)
}
val videoSpeedsArray = splits.map { it.toFloat().toRawBits() } val videoSpeedsArray = splits.map { it.toFloat().toRawBits() }
SpeedArrayGeneratorFingerprint.result?.let { result -> SpeedArrayGeneratorFingerprint.result?.let { result ->
@ -55,7 +77,7 @@ class CustomVideoSpeedBytecodePatch : BytecodePatch(
addInstructions( addInstructions(
sizeCallIndex + 2, sizeCallIndex + 2,
""" """
invoke-static {}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->isCustomVideoSpeedEnabled()Z invoke-static {}, $VIDEO_PATH/VideoSpeedPatch;->isCustomVideoSpeedEnabled()Z
move-result v9 move-result v9
if-eqz v9, :defaultspeed if-eqz v9, :defaultspeed
const/4 v$sizeCallResultRegister, 0x0 const/4 v$sizeCallResultRegister, 0x0
@ -67,7 +89,7 @@ class CustomVideoSpeedBytecodePatch : BytecodePatch(
val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
val videoSpeedsArrayType = "$INTEGRATIONS_VIDEO_SPEED_ENTRIES_CLASS_DESCRIPTOR->videoSpeed:[F" val videoSpeedsArrayType = "$VIDEO_PATH/VideoSpeedEntries;->videoSpeed:[F"
addInstructions( addInstructions(
arrayLengthConstIndex + 1, arrayLengthConstIndex + 1,
@ -111,11 +133,11 @@ class CustomVideoSpeedBytecodePatch : BytecodePatch(
replaceInstruction( replaceInstruction(
limiterMinConstIndex, limiterMinConstIndex,
"const/high16 v$limiterMinConstDestination, ${hexFloat(speedLimitMin)}" "const/high16 v$limiterMinConstDestination, ${hexFloat(0.0f)}"
) )
replaceInstruction( replaceInstruction(
limiterMaxConstIndex, limiterMaxConstIndex,
"const/high16 v$limiterMaxConstDestination, ${hexFloat(speedLimitMax)}" "const/high16 v$limiterMaxConstDestination, ${hexFloat(100.0f)}"
) )
} }
} ?: return SpeedLimiterFingerprint.toErrorResult() } ?: return SpeedLimiterFingerprint.toErrorResult()
@ -139,16 +161,36 @@ class CustomVideoSpeedBytecodePatch : BytecodePatch(
} }
} ?: return VideoSpeedEntriesFingerprint.toErrorResult() } ?: return VideoSpeedEntriesFingerprint.toErrorResult()
/**
* Copy arrays
*/
contexts.copyXmlNode("youtube/customspeed/host", "values/arrays.xml", "resources")
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: VIDEO_SETTINGS",
"SETTINGS: CUSTOM_VIDEO_SPEED"
)
)
SettingsPatch.updatePatchStatus("custom-video-speed")
return PatchResultSuccess() return PatchResultSuccess()
} }
companion object {
const val INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR =
"$VIDEO_PATH/VideoSpeedPatch;"
const val INTEGRATIONS_VIDEO_SPEED_ENTRIES_CLASS_DESCRIPTOR = companion object : OptionsContainer() {
"$VIDEO_PATH/VideoSpeedEntries;" var CustomSpeedArrays: String? by option(
PatchOption.StringOption(
const val speedLimitMin = 0.0f key = "CustomSpeedArrays",
const val speedLimitMax = 100f default = "0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 3.0, 5.0",
title = "Custom Speed Values",
description = "A list of custom video speeds. Be sure to separate them with commas (,)."
)
)
} }
} }

View File

@ -1,71 +0,0 @@
package app.revanced.patches.youtube.video.customspeed.resource.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.options.PatchOptions
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.patches.youtube.video.customspeed.bytecode.patch.CustomVideoSpeedBytecodePatch
import app.revanced.util.resources.ResourceHelper.addEntries
import app.revanced.util.resources.ResourceHelper.addEntryValues
import app.revanced.util.resources.ResourceUtils.copyXmlNode
@Patch
@Name("custom-video-speed")
@Description("Adds more video speed options.")
@DependsOn(
[
CustomVideoSpeedBytecodePatch::class,
PatchOptions::class,
SettingsPatch::class
]
)
@YouTubeCompatibility
@Version("0.0.1")
class CustomVideoSpeedPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
/*
* Copy arrays
*/
context.copyXmlNode("youtube/customspeed/host", "values/arrays.xml", "resources")
val speed = PatchOptions.CustomSpeedArrays
?: return PatchResultError("Invalid video speed array.")
val splits = speed.replace(" ","").split(",")
if (splits.isEmpty()) throw IllegalArgumentException("Invalid speed elements")
val speedElements = splits.map { it }
for (index in 0 until splits.count()) {
context.addEntries(TARGET_ARRAY_PATH, speedElements[index] + "x", TARGET_ENTRIES_NAME)
context.addEntryValues(TARGET_ARRAY_PATH, speedElements[index], TARGET_ENTRY_VALUE_NAME)
}
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: VIDEO_SETTINGS",
"SETTINGS: CUSTOM_VIDEO_SPEED"
)
)
SettingsPatch.updatePatchStatus("custom-video-speed")
return PatchResultSuccess()
}
private companion object {
private const val TARGET_ARRAY_PATH = "res/values/arrays.xml"
private const val TARGET_ENTRIES_NAME = "revanced_custom_video_speed_entry"
private const val TARGET_ENTRY_VALUE_NAME = "revanced_custom_video_speed_entry_value"
}
}