mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-15 21:52:27 +01:00
Compare commits
39 Commits
v2.5.1-dev
...
v2.11.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1eedc02ab | ||
|
|
9be32e10f6 | ||
|
|
87996f67a8 | ||
|
|
0822383271 | ||
|
|
0934af1ccd | ||
|
|
b3ad6fb8af | ||
|
|
87f5ebce9b | ||
|
|
a35d7c8951 | ||
|
|
3c8d3edff4 | ||
|
|
c35734bec2 | ||
|
|
e2b634053b | ||
|
|
3e6df0c96d | ||
|
|
7a2ea95e55 | ||
|
|
add3058d24 | ||
|
|
ef888f6b59 | ||
|
|
9b077d6ada | ||
|
|
93d4cee16e | ||
|
|
bc3b654357 | ||
|
|
64b4c92ca0 | ||
|
|
cd66ee4e57 | ||
|
|
f527226757 | ||
|
|
ec0b17a4d8 | ||
|
|
63598d0d42 | ||
|
|
14f6b66135 | ||
|
|
18893c005e | ||
|
|
73b51a0687 | ||
|
|
c4de003fc1 | ||
|
|
45b8ad099e | ||
|
|
8c40ff4852 | ||
|
|
f304c866f1 | ||
|
|
9adf42c308 | ||
|
|
2391db0f53 | ||
|
|
9809e4dfd0 | ||
|
|
b191efea2d | ||
|
|
c5ec801b90 | ||
|
|
95f22bc2a1 | ||
|
|
0098f25bfb | ||
|
|
9395e0835e | ||
|
|
d59d6b7022 |
@@ -7,7 +7,11 @@
|
||||
}
|
||||
],
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer",
|
||||
["@semantic-release/commit-analyzer", {
|
||||
"releaseRules": [
|
||||
{"type": "build", "release": "patch"}
|
||||
]
|
||||
}],
|
||||
"@semantic-release/release-notes-generator",
|
||||
"@semantic-release/changelog",
|
||||
"gradle-semantic-release-plugin",
|
||||
@@ -15,6 +19,7 @@
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
"gradle.properties"
|
||||
]
|
||||
|
||||
128
CHANGELOG.md
128
CHANGELOG.md
@@ -1,3 +1,131 @@
|
||||
# [2.11.0](https://github.com/revanced/revanced-patches/compare/v2.10.2...v2.11.0) (2022-07-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `autorepeat-by-default` patch ([#106](https://github.com/revanced/revanced-patches/issues/106)) ([e0ac9f3](https://github.com/revanced/revanced-patches/commit/e0ac9f385fc360f4dd2451e26676633120356c10))
|
||||
|
||||
## [2.10.2](https://github.com/revanced/revanced-patches/compare/v2.10.1...v2.10.2) (2022-07-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* trigger release on `build` commits ([be8bd1b](https://github.com/revanced/revanced-patches/commit/be8bd1b2a4b91f9763448661a802a5dc4a6b1d1d))
|
||||
|
||||
## [2.10.1](https://github.com/revanced/revanced-patches/compare/v2.10.0...v2.10.1) (2022-07-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* patch description consistency ([#134](https://github.com/revanced/revanced-patches/issues/134)) ([da5896d](https://github.com/revanced/revanced-patches/commit/da5896dde0a2b2b9ffe65e486402e4ef92ec1ce9))
|
||||
|
||||
# [2.10.0](https://github.com/revanced/revanced-patches/compare/v2.9.4...v2.10.0) (2022-07-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* implement `wide-searchbar` Patch ([#130](https://github.com/revanced/revanced-patches/issues/130)) ([332f4d1](https://github.com/revanced/revanced-patches/commit/332f4d12d06316d65db252a280fe1f263e65c3a8))
|
||||
|
||||
## [2.9.4](https://github.com/revanced/revanced-patches/compare/v2.9.3...v2.9.4) (2022-07-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add 17.25.34 as supported version for swipe-controls patch ([4d84c19](https://github.com/revanced/revanced-patches/commit/4d84c1914f8ecf51cee25667219bc6cf635a6c1c))
|
||||
|
||||
## [2.9.3](https://github.com/revanced/revanced-patches/compare/v2.9.2...v2.9.3) (2022-07-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Readd `swipe-controls` patch ([#123](https://github.com/revanced/revanced-patches/issues/123)) ([7f2a2b2](https://github.com/revanced/revanced-patches/commit/7f2a2b2ee4e6045d53aba4e7705431b643981107))
|
||||
|
||||
## [2.9.2](https://github.com/revanced/revanced-patches/compare/v2.9.1...v2.9.2) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* revert `swipe-controls` patch ([66e1f33](https://github.com/revanced/revanced-patches/commit/66e1f3384a58361737ba889d946be875b23f3163))
|
||||
|
||||
## [2.9.1](https://github.com/revanced/revanced-patches/compare/v2.9.0...v2.9.1) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make `minimized-playback-manager-fingerprint` unique ([#120](https://github.com/revanced/revanced-patches/issues/120)) ([cd5e911](https://github.com/revanced/revanced-patches/commit/cd5e911f4ed9ad95b02c13c30cd9466d250e8904))
|
||||
|
||||
# [2.9.0](https://github.com/revanced/revanced-patches/compare/v2.8.2...v2.9.0) (2022-07-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `swipe-controls` patch ([#115](https://github.com/revanced/revanced-patches/issues/115)) ([1d0a7dc](https://github.com/revanced/revanced-patches/commit/1d0a7dcc0cc3ea2bcd8ce0221d5e2f53d6eb0ae5))
|
||||
|
||||
## [2.8.2](https://github.com/revanced/revanced-patches/compare/v2.8.1...v2.8.2) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* show minimized playback options in settings ([#118](https://github.com/revanced/revanced-patches/issues/118)) ([6e1a538](https://github.com/revanced/revanced-patches/commit/6e1a538d34291d75f19bf66a188bc69241de3a7a))
|
||||
|
||||
## [2.8.1](https://github.com/revanced/revanced-patches/compare/v2.8.0...v2.8.1) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove unnecessary version constraints ([#117](https://github.com/revanced/revanced-patches/issues/117)) ([1cddf8d](https://github.com/revanced/revanced-patches/commit/1cddf8d9063da3bbdba0fd7080c8c93768b83a4c))
|
||||
|
||||
# [2.8.0](https://github.com/revanced/revanced-patches/compare/v2.7.0...v2.8.0) (2022-07-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `enable-debugging` patch ([#116](https://github.com/revanced/revanced-patches/issues/116)) ([bb355e7](https://github.com/revanced/revanced-patches/commit/bb355e7b7e78e602a10b346fe7e5795463615a81))
|
||||
|
||||
# [2.7.0](https://github.com/revanced/revanced-patches/compare/v2.6.0...v2.7.0) (2022-07-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `hdr-max-brightness` patch ([#105](https://github.com/revanced/revanced-patches/issues/105)) ([1310573](https://github.com/revanced/revanced-patches/commit/131057366a777786d6016d3385584b4e17bc4a8b))
|
||||
* `hide-infocard-suggestions` patch ([#107](https://github.com/revanced/revanced-patches/issues/107)) ([31a767a](https://github.com/revanced/revanced-patches/commit/31a767adbb152906303ab0ae5250769fc38d0625))
|
||||
|
||||
# [2.6.0](https://github.com/revanced/revanced-patches/compare/v2.5.0...v2.6.0) (2022-07-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* freezing panels when watching video in fullscreen ([#89](https://github.com/revanced/revanced-patches/issues/89)) ([f5d4f6c](https://github.com/revanced/revanced-patches/commit/f5d4f6c3419916c6a9cf67babc6be8a64c854d3b))
|
||||
* invalid version in compatibility annotation ([#90](https://github.com/revanced/revanced-patches/issues/90)) ([df43547](https://github.com/revanced/revanced-patches/commit/df435475cdd0494a1e4ea9e2980c2998c9bc7048))
|
||||
* remove refreshing home screen not working ([6c24ebe](https://github.com/revanced/revanced-patches/commit/6c24ebef2fb4f0d58e369ac5bf63e4cab6ca0e80))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* migrate to breaking changes of patcher ([d9147cd](https://github.com/revanced/revanced-patches/commit/d9147cd60c0c25d0c5cc05409b8889dfacd89af9))
|
||||
|
||||
# [2.6.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.6.0-dev.1...v2.6.0-dev.2) (2022-07-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove refreshing home screen not working ([ec7ae90](https://github.com/revanced/revanced-patches/commit/ec7ae900181b6456c692adb3b5bb337e81bc5fea))
|
||||
|
||||
# [2.6.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.5.1-dev.1...v2.6.0-dev.1) (2022-07-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* migrate to breaking changes of patcher ([a116852](https://github.com/revanced/revanced-patches/commit/a11685263fb2274c67684258e73c5247502cb010))
|
||||
|
||||
## [2.5.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.5.0...v2.5.1-dev.1) (2022-06-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* freezing panels when watching video in fullscreen ([#89](https://github.com/revanced/revanced-patches/issues/89)) ([f5d4f6c](https://github.com/revanced/revanced-patches/commit/f5d4f6c3419916c6a9cf67babc6be8a64c854d3b))
|
||||
* invalid version in compatibility annotation ([#90](https://github.com/revanced/revanced-patches/issues/90)) ([df43547](https://github.com/revanced/revanced-patches/commit/df435475cdd0494a1e4ea9e2980c2998c9bc7048))
|
||||
|
||||
# [2.5.0](https://github.com/revanced/revanced-patches/compare/v2.4.0...v2.5.0) (2022-06-30)
|
||||
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Repo for all ReVanced patches
|
||||
# ReVanced Patches
|
||||
🧩 Official patches by ReVanced
|
||||
|
||||
@@ -22,7 +22,7 @@ repositories {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
|
||||
implementation("app.revanced:revanced-patcher:2.1.2")
|
||||
implementation("app.revanced:revanced-patcher:2.4.0")
|
||||
implementation("app.revanced:multidexlib2:2.5.2.r2")
|
||||
}
|
||||
|
||||
@@ -49,12 +49,19 @@ tasks {
|
||||
}
|
||||
}
|
||||
}
|
||||
register<JavaExec>("generateReadme") {
|
||||
description = "Generate README.md"
|
||||
dependsOn(build)
|
||||
|
||||
classpath = sourceSets["main"].runtimeClasspath
|
||||
mainClass.set("app.revanced.patches.meta.ReadmeGenerator")
|
||||
}
|
||||
// Dummy task to fix the Gradle semantic-release plugin.
|
||||
// Remove this if you forked it to support building only.
|
||||
// Tracking issue: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
||||
register<DefaultTask>("publish") {
|
||||
group = "publish"
|
||||
description = "Dummy task"
|
||||
dependsOn(named("generateDex"))
|
||||
dependsOn(named("generateDex"), named("generateReadme"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
kotlin.code.style = official
|
||||
version = 2.5.0
|
||||
version = 2.11.0
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
package app.revanced.extensions
|
||||
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.toInstruction
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.MutableMethodImplementation
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction11n
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
import org.w3c.dom.Node
|
||||
|
||||
internal fun MutableMethodImplementation.injectHideCall(
|
||||
@@ -14,6 +25,115 @@ internal fun MutableMethodImplementation.injectHideCall(
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an event hook at the top of the method. If the hook returns true, the event is consumed and the method will return with true
|
||||
*
|
||||
* the hook method MUST return a boolean and MUST take two parameters, like so:
|
||||
* fun hook(thisRef: Object, eventData: Object): Boolean {}
|
||||
*
|
||||
* The final injected code will resemble the following logic:
|
||||
* if( YouHook(this, event) ) { return true; }
|
||||
* ...
|
||||
*
|
||||
* @param hookRef reference to the hook method
|
||||
*/
|
||||
internal fun MutableMethod.injectConsumableEventHook(hookRef: ImmutableMethodReference) {
|
||||
val isStaticMethod = AccessFlags.STATIC.isSet(this.accessFlags)
|
||||
this.implementation?.let { impl ->
|
||||
// create label to index 0 to continue to the normal program flow
|
||||
val lblContinueNormalFlow = impl.newLabelForIndex(0)
|
||||
|
||||
// define registers
|
||||
/** V0 */
|
||||
val regV0 = 0
|
||||
|
||||
/** this */
|
||||
val regP0 = impl.registerCount - this.parameters.size - (if (isStaticMethod) 0 else 1)
|
||||
|
||||
/** motionEvent */
|
||||
val regP1 = regP0 + 1
|
||||
|
||||
// insert instructions at the start of the method:
|
||||
// if( Hook(this, event) ) { return true; }
|
||||
impl.addInstructions(
|
||||
0, listOf(
|
||||
// invoke-static { p0, p1 } <hook>
|
||||
BuilderInstruction35c(
|
||||
Opcode.INVOKE_STATIC,
|
||||
2,
|
||||
regP0,
|
||||
regP1,
|
||||
0, 0, 0,
|
||||
hookRef
|
||||
),
|
||||
|
||||
// move-result v0
|
||||
BuilderInstruction11x(
|
||||
Opcode.MOVE_RESULT,
|
||||
regV0
|
||||
),
|
||||
|
||||
// if-eqz v0, :continue_normal_flow
|
||||
BuilderInstruction21t(
|
||||
Opcode.IF_EQZ,
|
||||
regV0,
|
||||
lblContinueNormalFlow
|
||||
),
|
||||
|
||||
// const/4 v0, 0x1
|
||||
BuilderInstruction11n(
|
||||
Opcode.CONST_4,
|
||||
regV0,
|
||||
0x1
|
||||
),
|
||||
|
||||
// return v0
|
||||
BuilderInstruction11x(
|
||||
Opcode.RETURN,
|
||||
regV0
|
||||
)
|
||||
|
||||
// :continue_normal_flow
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert instructions into a named method
|
||||
*
|
||||
* @param targetClass the name of the class of which the method is a member
|
||||
* @param targetMethod the name of the method to insert into
|
||||
* @param index index to insert the instructions at. If the index is negative, it is used as an offset to the last method (so -1 inserts at the end of the method)
|
||||
* @param instructions the smali instructions to insert (they'll be compiled by MutableMethod.addInstructions)
|
||||
*/
|
||||
internal fun BytecodeData.injectIntoNamedMethod(
|
||||
targetClass: String,
|
||||
targetMethod: String,
|
||||
index: Int,
|
||||
instructions: String
|
||||
) {
|
||||
var injections = 0
|
||||
this.classes.filter { it.type.endsWith("$targetClass;") }.forEach { classDef ->
|
||||
this.proxy(classDef).resolve().methods.filter { it.name == targetMethod }.forEach { methodDef ->
|
||||
// if index is negative, interpret as an offset from the back
|
||||
var insertIndex = index
|
||||
if (insertIndex < 0) {
|
||||
insertIndex += methodDef.implementation!!.instructions.size
|
||||
}
|
||||
|
||||
// insert instructions
|
||||
methodDef.addInstructions(insertIndex, instructions)
|
||||
injections++
|
||||
}
|
||||
}
|
||||
|
||||
// fail if nothing was injected
|
||||
if (injections <= 0) {
|
||||
throw PatchResultError("failed to inject into $targetClass.$targetMethod: no targets were found")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Node.doRecursively(action: (Node) -> Unit) {
|
||||
action(this)
|
||||
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
|
||||
|
||||
55
src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
Normal file
55
src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
Normal file
@@ -0,0 +1,55 @@
|
||||
package app.revanced.patches.meta
|
||||
|
||||
import java.io.File
|
||||
import kotlin.io.writeText
|
||||
import kotlin.collections.first
|
||||
import app.revanced.patcher.util.patch.implementation.JarPatchBundle
|
||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||
import app.revanced.patcher.extensions.PatchExtensions.description
|
||||
|
||||
class ReadmeGenerator {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
//should be moved to a file?
|
||||
val generalReadme =
|
||||
"""
|
||||
# ReVanced Patches
|
||||
🧩 Official patches by ReVanced
|
||||
|
||||
# Patch list
|
||||
""".trimIndent()
|
||||
|
||||
val tableHeader =
|
||||
"""
|
||||
| 💊 Patch | 📜 Description | 🎯 Target Package | 🏹 Target Version |
|
||||
|:-----:|:-----------:|:--------------:|:----------------------:|
|
||||
""".trimIndent()
|
||||
|
||||
val readmeFile = File("README.md")
|
||||
|
||||
val buildDir = File("build/libs/")
|
||||
val buildJar = buildDir.listFiles().first { it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar") }
|
||||
|
||||
val bundle = JarPatchBundle(buildJar.absolutePath).loadPatches()
|
||||
|
||||
val builder = StringBuilder()
|
||||
|
||||
builder.appendLine(generalReadme)
|
||||
builder.appendLine(tableHeader)
|
||||
|
||||
for (patch in bundle) {
|
||||
val humanName =
|
||||
patch.patchName.split('-').map { it.replaceFirstChar { it.uppercase() } }.joinToString(" ")
|
||||
|
||||
val compatiblePackage = patch.compatiblePackages?.first()
|
||||
val latestVersion = compatiblePackage?.versions?.maxByOrNull { it.replace(".", "").toInt() } ?: "all"
|
||||
|
||||
builder.appendLine("|$humanName|${patch.description}|`${compatiblePackage?.name}`|$latestVersion|")
|
||||
}
|
||||
|
||||
readmeFile.writeText(builder.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.music.audio.exclusiveaudio.patch
|
||||
|
||||
import AudioOnlyEnablerFingerprint
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
@@ -13,11 +12,12 @@ import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
||||
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AudioOnlyEnablerFingerprint
|
||||
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.ExclusiveAudioFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("exclusive-audio-playback")
|
||||
@Description("Add the option to play music without video.")
|
||||
@Description("Adds the option to play music without video.")
|
||||
@ExclusiveAudioCompatibility
|
||||
@Version("0.0.1")
|
||||
class ExclusiveAudioPatch : BytecodePatch(
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@Name("upgrade-button-remover")
|
||||
@Description("Remove the upgrade tab from the pivot bar in YouTube music.")
|
||||
@Description("Removes the upgrade tab from the pivot bar in YouTube music.")
|
||||
@RemoveUpgradeButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class RemoveUpgradeButtonPatch : BytecodePatch(
|
||||
|
||||
@@ -21,7 +21,6 @@ import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensi
|
||||
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.insertBlocks
|
||||
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.toDescriptor
|
||||
import app.revanced.patches.youtube.ad.general.bytecode.utils.MethodUtils.createMutableMethod
|
||||
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralResourceAdsPatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
@@ -40,15 +39,13 @@ import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
||||
@Patch
|
||||
@Dependencies(
|
||||
dependencies = [ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class, GeneralResourceAdsPatch::class]
|
||||
dependencies = [ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class]
|
||||
)
|
||||
@Name("general-ads")
|
||||
@Description("Patch to remove general ads in bytecode.")
|
||||
@Description("Removes general ads in bytecode.")
|
||||
@GeneralAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class GeneralBytecodeAdsPatch : BytecodePatch(
|
||||
listOf()
|
||||
) {
|
||||
class GeneralBytecodeAdsPatch : BytecodePatch() {
|
||||
// a constant used by litho
|
||||
private val lithoConstant = 0xaed2868
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package app.revanced.patches.youtube.ad.general.resource.patch
|
||||
|
||||
import app.revanced.extensions.doRecursively
|
||||
import app.revanced.extensions.startsWithAny
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Dependencies(dependencies = [FixLocaleConfigErrorPatch::class])
|
||||
@Name("general-resource-ads")
|
||||
@Description("Patch to remove general ads in resources.")
|
||||
@GeneralAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class GeneralResourceAdsPatch : ResourcePatch() {
|
||||
// list of resource file names which need to be hidden
|
||||
private val resourceFileNames = arrayOf(
|
||||
"compact_promoted_video_item.xml",
|
||||
"inline_muted_metadata_swap.xml",
|
||||
"interstitial_promo_view.xml",
|
||||
"pip_ad_overlay.xml",
|
||||
"promoted_",
|
||||
"watch_metadata_companion_cards.xml",
|
||||
//"watch_while_activity.xml" // FIXME: find out why patching this resource fails
|
||||
)
|
||||
|
||||
// the attributes to change the value of
|
||||
private val replacements = arrayOf(
|
||||
"height",
|
||||
"width",
|
||||
"marginTop",
|
||||
)
|
||||
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
data.forEach {
|
||||
if (!it.name.startsWithAny(*resourceFileNames)) return@forEach
|
||||
|
||||
// for each file in the "layouts" directory replace all necessary attributes content
|
||||
data.getXmlEditor(it.absolutePath).use { editor ->
|
||||
editor.file.doRecursively { node ->
|
||||
replacements.forEach replacement@{ replacement ->
|
||||
if (node !is Element) return@replacement
|
||||
|
||||
node.getAttributeNode("android:layout_$replacement")?.let { attribute ->
|
||||
attribute.textContent = "1.0dip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.ad.infocardsuggestions.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.25.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class HideInfocardSuggestionsCompatibility
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfocardSuggestionsCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("hide-infocard-suggestions-fingerprint")
|
||||
@MatchingMethod("Liff;", "i")
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@HideInfocardSuggestionsCompatibility
|
||||
@Version("0.0.1")
|
||||
object HideInfocardSuggestionsFingerprint : MethodFingerprint(
|
||||
"Ljava/lang/Boolean;",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
null,
|
||||
listOf("vibrator"),
|
||||
null
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfocardSuggestionsCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("hide-infocard-suggestions-parent-fingerprint")
|
||||
@MatchingMethod("Liff;", "lE")
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@HideInfocardSuggestionsCompatibility
|
||||
@Version("0.0.1")
|
||||
object HideInfocardSuggestionsParentFingerprint : MethodFingerprint(
|
||||
"Ljava/lang/String;",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
listOf(),
|
||||
null,
|
||||
listOf("player_overlay_info_card_teaser"),
|
||||
null
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
package app.revanced.patches.youtube.ad.infocardsuggestions.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfocardSuggestionsCompatibility
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsFingerprint
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("hide-infocard-suggestions")
|
||||
@Description("Hides infocards in videos.")
|
||||
@HideInfocardSuggestionsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideInfocardSuggestionsPatch : BytecodePatch(
|
||||
listOf(
|
||||
HideInfocardSuggestionsParentFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val parentResult = HideInfocardSuggestionsParentFingerprint.result
|
||||
?: return PatchResultError("Parent fingerprint not resolved!")
|
||||
|
||||
|
||||
HideInfocardSuggestionsFingerprint.resolve(data, parentResult.classDef)
|
||||
val result = HideInfocardSuggestionsFingerprint.result
|
||||
?: return PatchResultError("Required parent method could not be found.")
|
||||
|
||||
val method = result.mutableMethod
|
||||
val implementation = method.implementation
|
||||
?: return PatchResultError("Implementation not found.")
|
||||
|
||||
val index = implementation.instructions.indexOfFirst { ((it as? BuilderInstruction35c)?.reference.toString() == "Landroid/view/View;->setVisibility(I)V") }
|
||||
val register = "v" + (implementation.instructions.get(index) as FiveRegisterInstruction).registerD
|
||||
|
||||
method.removeInstruction(index)
|
||||
|
||||
method.addInstructions(
|
||||
index, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideInfoCardSuggestionsPatch;->hideInfoCardSuggestions()I
|
||||
move-result $register
|
||||
invoke-virtual {p1, $register}, Landroid/view/View;->setVisibility(I)V
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
package app.revanced.patches.youtube.ad.video.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.youtube.ad.video.patch
|
||||
|
||||
import ShowVideoAdsFingerprint
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
@@ -14,12 +13,13 @@ import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility
|
||||
import app.revanced.patches.youtube.ad.video.fingerprints.ShowVideoAdsConstructorFingerprint
|
||||
import app.revanced.patches.youtube.ad.video.fingerprints.ShowVideoAdsFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("video-ads")
|
||||
@Description("Patch to remove ads in the YouTube video player.")
|
||||
@Description("Removes ads in the YouTube video player.")
|
||||
@VideoAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class VideoAdsPatch : BytecodePatch(
|
||||
@@ -40,4 +40,4 @@ class VideoAdsPatch : BytecodePatch(
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.interaction.fenster.annotation
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.24.34", "17.25.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class FensterCompatibility
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.patches.youtube.interaction.fenster.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.interaction.fenster.annotation.FensterCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("update-player-type-fingerprint")
|
||||
@MatchingMethod(
|
||||
"LYoutubePlayerOverlaysLayout;",
|
||||
"nM"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@FensterCompatibility
|
||||
@Version("0.0.1")
|
||||
object UpdatePlayerTypeFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_NE,
|
||||
Opcode.RETURN_VOID,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.RETURN_VOID,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,121 @@
|
||||
package app.revanced.patches.youtube.interaction.fenster.patch
|
||||
|
||||
import app.revanced.extensions.injectConsumableEventHook
|
||||
import app.revanced.extensions.injectIntoNamedMethod
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.interaction.fenster.annotation.FensterCompatibility
|
||||
import app.revanced.patches.youtube.interaction.fenster.fingerprints.UpdatePlayerTypeFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
||||
@Patch
|
||||
@Name("fenster-swipe-controls")
|
||||
@Description("Adds volume and brightness swipe controls.")
|
||||
@FensterCompatibility
|
||||
@Version("0.0.1")
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
class FensterPatch : BytecodePatch(
|
||||
listOf(
|
||||
UpdatePlayerTypeFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
// hook WatchWhileActivity.onStart (main activity lifecycle hook)
|
||||
data.injectIntoNamedMethod(
|
||||
"com/google/android/apps/youtube/app/watchwhile/WatchWhileActivity",
|
||||
"onStart",
|
||||
0,
|
||||
"invoke-static { p0 }, Lapp/revanced/integrations/patches/FensterSwipePatch;->WatchWhileActivity_onStartHookEX(Ljava/lang/Object;)V"
|
||||
)
|
||||
|
||||
// hook YoutubePlayerOverlaysLayout.onFinishInflate (player overlays init hook)
|
||||
data.injectIntoNamedMethod(
|
||||
"com/google/android/apps/youtube/app/common/player/overlay/YouTubePlayerOverlaysLayout",
|
||||
"onFinishInflate",
|
||||
-2,
|
||||
"invoke-static { p0 }, Lapp/revanced/integrations/patches/FensterSwipePatch;->YouTubePlayerOverlaysLayout_onFinishInflateHookEX(Ljava/lang/Object;)V"
|
||||
)
|
||||
|
||||
// hook YoutubePlayerOverlaysLayout.UpdatePlayerType
|
||||
injectUpdatePlayerTypeHook(
|
||||
UpdatePlayerTypeFingerprint.result!!,
|
||||
"com/google/android/apps/youtube/app/common/player/overlay/YouTubePlayerOverlaysLayout"
|
||||
)
|
||||
|
||||
// hook NextGenWatchLayout.onTouchEvent and NextGenWatchLayout.onInterceptTouchEvent (player touch event hook)
|
||||
injectWatchLayoutTouchHooks(
|
||||
data,
|
||||
"com/google/android/apps/youtube/app/watch/nextgenwatch/ui/NextGenWatchLayout"
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
private fun injectUpdatePlayerTypeHook(fingerPrintResult: MethodFingerprintResult, targetClass: String) {
|
||||
// validate fingerprint found the right class
|
||||
if (!fingerPrintResult.classDef.type.endsWith("$targetClass;")) {
|
||||
throw PatchResultError("$targetClass.UpdatePlayerType fingerprint could not be validated")
|
||||
}
|
||||
|
||||
// insert the hook
|
||||
fingerPrintResult.mutableMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static { p1 }, Lapp/revanced/integrations/patches/FensterSwipePatch;->YouTubePlayerOverlaysLayout_updatePlayerTypeHookEX(Ljava/lang/Object;)V"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject onTouch event hooks into the watch layout class
|
||||
*
|
||||
* @param data bytecode data
|
||||
* @param targetClass watch layout class name
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun injectWatchLayoutTouchHooks(data: BytecodeData, targetClass: String) {
|
||||
var touchHooksCount = 0
|
||||
data.classes.filter { it.type.endsWith("$targetClass;") }.forEach { classDef ->
|
||||
// hook onTouchEvent
|
||||
data.proxy(classDef).resolve().methods.filter { it.name == "onTouchEvent" }.forEach { methodDef ->
|
||||
touchHooksCount++
|
||||
methodDef.injectConsumableEventHook(
|
||||
ImmutableMethodReference(
|
||||
"Lapp/revanced/integrations/patches/FensterSwipePatch;",
|
||||
"NextGenWatchLayout_onTouchEventHookEX",
|
||||
listOf("Ljava/lang/Object;", "Ljava/lang/Object;"),
|
||||
"Z"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// hook onInterceptTouchEvent
|
||||
data.proxy(classDef).resolve().methods.filter { it.name == "onInterceptTouchEvent" }.forEach { methodDef ->
|
||||
touchHooksCount++
|
||||
methodDef.injectConsumableEventHook(
|
||||
ImmutableMethodReference(
|
||||
"Lapp/revanced/integrations/patches/FensterSwipePatch;",
|
||||
"NextGenWatchLayout_onInterceptTouchEventHookEX",
|
||||
listOf("Ljava/lang/Object;", "Ljava/lang/Object;"),
|
||||
"Z"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// fail if no touch hooks were inserted
|
||||
if (touchHooksCount <= 0) {
|
||||
throw PatchResultError("failed to inject onTouchEvent hook into NextGenWatchLayout: none found")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("seekbar-tapping")
|
||||
@Description("Enable tapping on the seekbar of the YouTube player.")
|
||||
@Description("Enables tapping on the seekbar of the YouTube player.")
|
||||
@SeekbarTappingCompatibility
|
||||
@Version("0.0.1")
|
||||
class EnableSeekbarTappingPatch : BytecodePatch(
|
||||
@@ -92,4 +92,4 @@ class EnableSeekbarTappingPatch : BytecodePatch(
|
||||
)
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@ import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.youtube.layout.amoled.annotations.AmoledCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import org.w3c.dom.Element
|
||||
@@ -26,7 +26,7 @@ import java.io.File
|
||||
@Version("0.0.1")
|
||||
class AmoledPatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
data.getXmlEditor("res${File.separator}values${File.separator}colors.xml").use { editor ->
|
||||
data.xmlEditor["res${File.separator}values${File.separator}colors.xml"].use { editor ->
|
||||
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
for (i in 0 until resourcesNode.childNodes.length) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
@Patch
|
||||
@Dependencies(dependencies = [ResourceIdMappingProviderResourcePatch::class])
|
||||
@Name("hide-autoplay-button")
|
||||
@Description("Disable the autoplay button.")
|
||||
@Description("Disables the autoplay button.")
|
||||
@AutoplayButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideAutoplayButton : BytecodePatch(
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.autorepeat.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.24.35", "17.25.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class AutoRepeatCompatibility
|
||||
@@ -0,0 +1,32 @@
|
||||
package app.revanced.patches.youtube.layout.autorepeat.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.layout.autorepeat.annotations.AutoRepeatCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("auto-repeat-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Laamp;", "ae"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@AutoRepeatCompatibility
|
||||
@Version("0.0.1")
|
||||
//Finds method:
|
||||
/*
|
||||
public final void ae() {
|
||||
aq(aabj.ENDED);
|
||||
}
|
||||
*/
|
||||
object AutoRepeatFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
customFingerprint = { methodDef -> methodDef.implementation!!.instructions.count() == 3 }
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
package app.revanced.patches.youtube.layout.autorepeat.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.layout.autorepeat.annotations.AutoRepeatCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("auto-repeat-parent-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Laamp;", "E"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@AutoRepeatCompatibility
|
||||
@Version("0.0.1")
|
||||
//This Fingerprints finds the play() method needed to be called when AutoRepeatPatch.shouldAutoRepeat() == true
|
||||
/*
|
||||
public final void E() {
|
||||
Stuff happens
|
||||
String str = "play() called when the player wasn't loaded.";
|
||||
String str2 = "play() blocked because Background Playability failed";
|
||||
Stuff happens again
|
||||
}
|
||||
*/
|
||||
object AutoRepeatParentFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
null,
|
||||
listOf("play() called when the player wasn't loaded.", "play() blocked because Background Playability failed"),
|
||||
null
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
package app.revanced.patches.youtube.layout.autorepeat.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.autorepeat.annotations.AutoRepeatCompatibility
|
||||
import app.revanced.patches.youtube.layout.autorepeat.fingerprints.AutoRepeatFingerprint
|
||||
import app.revanced.patches.youtube.layout.autorepeat.fingerprints.AutoRepeatParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch(include = false)
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("autorepeat-by-default")
|
||||
@Description("Enables auto repeating of videos by default.")
|
||||
@AutoRepeatCompatibility
|
||||
@Version("0.0.1")
|
||||
class AutoRepeatPatch : BytecodePatch(
|
||||
listOf(
|
||||
AutoRepeatParentFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
//Get Result from the ParentFingerprint which is the playMethod we need to get.
|
||||
val parentResult = AutoRepeatParentFingerprint.result
|
||||
?: return PatchResultError("ParentFingerprint did not resolve.")
|
||||
|
||||
//this one needs to be called when app/revanced/integrations/patches/AutoRepeatPatch;->shouldAutoRepeat() returns true
|
||||
val playMethod = parentResult.mutableMethod
|
||||
AutoRepeatFingerprint.resolve(data, parentResult.classDef)
|
||||
//String is: Laamp;->E()V
|
||||
val methodToCall = playMethod.definingClass + "->" + playMethod.name + "()V";
|
||||
|
||||
//This is the method we search for
|
||||
val result = AutoRepeatFingerprint.result
|
||||
?: return PatchResultError("FingerPrint did not resolve.")
|
||||
val method = result.mutableMethod
|
||||
|
||||
//Instructions to add to the smali code
|
||||
val instructions = """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/AutoRepeatPatch;->shouldAutoRepeat()Z
|
||||
move-result v0
|
||||
if-eqz v0, :noautorepeat
|
||||
const/4 v0, 0x0
|
||||
invoke-virtual {}, $methodToCall
|
||||
:noautorepeat
|
||||
return-void
|
||||
"""
|
||||
|
||||
//Get the implementation so we can do a check for null and get instructions size.
|
||||
val implementation = method.implementation
|
||||
?: return PatchResultError("No Method Implementation found!")
|
||||
|
||||
//Since addInstructions needs an index which starts counting at 0 and size starts counting at 1,
|
||||
//we have to remove 1 to get the latest instruction
|
||||
val index = implementation.instructions.size-1
|
||||
|
||||
|
||||
//remove last instruction which is return-void
|
||||
method.removeInstruction(index)
|
||||
// Add our own instructions there
|
||||
method.addInstructions(index, instructions)
|
||||
|
||||
//Everything worked as expected, return Success
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,12 @@ import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.branding.icon.annotations.CustomBrandingCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import java.nio.file.Files
|
||||
@@ -24,7 +24,7 @@ import java.nio.file.Files
|
||||
@Version("0.0.1")
|
||||
class CustomBrandingPatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
val resDirectory = data.get("res")
|
||||
val resDirectory = data["res"]
|
||||
if (!resDirectory.isDirectory) return PatchResultError("The res folder can not be found.")
|
||||
|
||||
val iconNames = arrayOf(
|
||||
|
||||
@@ -16,10 +16,10 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("hide-cast-button")
|
||||
@Description("Patch to hide the cast button.")
|
||||
@Description("Hides the cast button.")
|
||||
@CastButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideCastButtonPatch : BytecodePatch(listOf()) {
|
||||
class HideCastButtonPatch : BytecodePatch() {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
data.classes.forEach { classDef ->
|
||||
classDef.methods.forEach { method ->
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class])
|
||||
@Name("disable-create-button")
|
||||
@Description("Disable the create button.")
|
||||
@Description("Disables the create button.")
|
||||
@CreateButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class CreateButtonRemoverPatch : BytecodePatch(
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch
|
||||
@Name("disable-fullscreen-panels")
|
||||
@Description("Disable comments panel in fullscreen view.")
|
||||
@Description("Disables comments panel in fullscreen view.")
|
||||
@FullscreenPanelsCompatibility
|
||||
@Version("0.0.1")
|
||||
class FullscreenPanelsRemovalPatch : BytecodePatch(
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package app.revanced.patches.youtube.layout.minimizedplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
|
||||
@Name("minimized-playback-manager-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Ladj", "w"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@MinimizedPlaybackCompatibility
|
||||
@Version("0.0.1")
|
||||
object MinimizedPlaybackSettingsFingerprint : MethodFingerprint(
|
||||
"L",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.GOTO,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CHECK_CAST
|
||||
),
|
||||
)
|
||||
@@ -3,24 +3,30 @@ package app.revanced.patches.youtube.layout.minimizedplayback.patch
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.data.impl.toMethodWalker
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
|
||||
|
||||
@Patch
|
||||
@Name("minimized-playback")
|
||||
@Description("Enable minimized and background playback.")
|
||||
@Description("Enables minimized and background playback.")
|
||||
@MinimizedPlaybackCompatibility
|
||||
@Version("0.0.1")
|
||||
class MinimizedPlaybackPatch : BytecodePatch(
|
||||
listOf(
|
||||
MinimizedPlaybackManagerFingerprint
|
||||
MinimizedPlaybackManagerFingerprint, MinimizedPlaybackSettingsFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
@@ -32,6 +38,22 @@ class MinimizedPlaybackPatch : BytecodePatch(
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
|
||||
val method = MinimizedPlaybackSettingsFingerprint.result!!.mutableMethod
|
||||
val booleanCalls = method.implementation!!.instructions.withIndex()
|
||||
.filter { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z" }
|
||||
|
||||
val settingsBooleanIndex = booleanCalls.elementAt(1).index
|
||||
val settingsBooleanMethod =
|
||||
data.toMethodWalker(method).nextMethod(settingsBooleanIndex, true).getMethod() as MutableMethod
|
||||
|
||||
settingsBooleanMethod.addInstructions(
|
||||
0, """
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
package app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package app.revanced.patches.youtube.layout.oldqualitylayout.patch
|
||||
|
||||
import OldQualityFingerprint
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
|
||||
import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.OldQualityFingerprint
|
||||
import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.OldQualityParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
@@ -22,7 +22,7 @@ import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("old-quality-layout")
|
||||
@Description("Enable the original quality flyout menu.")
|
||||
@Description("Enables the original quality flyout menu.")
|
||||
@OldQualityLayoutCompatibility
|
||||
@Version("0.0.1")
|
||||
class OldQualityLayoutPatch : BytecodePatch(
|
||||
@@ -51,4 +51,4 @@ class OldQualityLayoutPatch : BytecodePatch(
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import app.revanced.patches.youtube.layout.reels.fingerprints.HideReelsFingerpri
|
||||
|
||||
//@Patch TODO: this is currently in the general-bytecode-ads patch due to the integrations having a preference for including reels or not. Move it here.
|
||||
@Name("hide-reels")
|
||||
@Description("Hide reels on the page.")
|
||||
@Description("Hides reels on the page.")
|
||||
@HideReelsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideReelsPatch : BytecodePatch(
|
||||
@@ -33,4 +33,4 @@ class HideReelsPatch : BytecodePatch(
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("hide-shorts-button")
|
||||
@Description("Hide the shorts button.")
|
||||
@Description("Hides the shorts button.")
|
||||
@ShortsButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class ShortsButtonRemoverPatch : BytecodePatch(
|
||||
|
||||
@@ -6,7 +6,6 @@ import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
@@ -22,7 +21,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
@Patch
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("hide-watermark")
|
||||
@Description("Hide Watermark on the page.")
|
||||
@Description("Hides the creator's watermark on videos.")
|
||||
@HideWatermarkCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideWatermarkPatch : BytecodePatch(
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.widesearchbar.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.25.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class WideSearchbarCompatibility
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patches.youtube.layout.widesearchbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("wide-searchbar-methodone-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Ljkg;", "i"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@WideSearchbarCompatibility
|
||||
@Version("0.0.1")
|
||||
|
||||
/*
|
||||
This finds the following method:
|
||||
public final View i(akrl akrlVar, adpd adpdVar) {
|
||||
}
|
||||
|
||||
Method we search for is located in smali now.
|
||||
See:
|
||||
.method public final i(Lakrl;Ladpd;)Landroid/view/View;
|
||||
iget-object v0, p0, Ljkg;->a:Landroid/app/Activity;
|
||||
invoke-static {v0}, Landroid/view/LayoutInflater;->from(Landroid/content/Context;)Landroid/view/LayoutInflater;
|
||||
move-result-object v0
|
||||
iget-object v1, p0, Ljkg;->g:Ljis;
|
||||
const/4 v2, 0x0
|
||||
invoke-interface {v1, v2}, Ljis;->h(Z)V
|
||||
iget-object p1, p1, Lakrl;->f:Lahnq;
|
||||
if-nez p1, :cond_12
|
||||
sget-object p1, Lahnq;->a:Lahnq;
|
||||
:cond_12
|
||||
iget-object v1, p0, Ljkg;->x:Ltxm;
|
||||
invoke-static {v1}, Lfbn;->aF(Ltxm;)Z //THIS IS WHAT WE SEARCH FOR (Method fbn.aF)
|
||||
move-result v1
|
||||
*/
|
||||
|
||||
object WideSearchbarOneFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L"), listOf(Opcode.IF_NEZ, Opcode.SGET_OBJECT, Opcode.IGET_OBJECT, Opcode.INVOKE_STATIC),
|
||||
null, null
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.youtube.layout.widesearchbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("wide-searchbar-methodone-parent-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Ljkg;", "l"
|
||||
)
|
||||
@FuzzyPatternScanMethod(3)
|
||||
@WideSearchbarCompatibility
|
||||
@Version("0.0.1")
|
||||
|
||||
/*
|
||||
* This finds the following method:
|
||||
private final void l(PaneDescriptor paneDescriptor) {
|
||||
Class cls = null;
|
||||
ahat f = paneDescriptor != null ? paneDescriptor.f() : null;
|
||||
if (paneDescriptor != null) {
|
||||
cls = paneDescriptor.a;
|
||||
}
|
||||
ftu k = k();
|
||||
if ((k == null || !k.bk()) && ((!frx.k(f) && !((Boolean) aqer.S(this.n).X(new fac(this, f, 19)).K(irx.i).aH(false)).booleanValue()) || (f != null && f.qA(ReelWatchEndpointOuterClass$ReelWatchEndpoint.reelWatchEndpoint)))) {
|
||||
String j = frx.j(f);
|
||||
if ((j != null && ("FEhistory".equals(j) || "FEmy_videos".equals(j) || "FEpurchases".equals(j) || j.startsWith("VL"))) || cls == this.I.E() || cls == this.G.a) {
|
||||
this.F = 3;
|
||||
return;
|
||||
} else {
|
||||
this.F = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.F = 1;
|
||||
}
|
||||
*/
|
||||
|
||||
object WideSearchbarOneParentFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("L"), null,
|
||||
listOf("FEhistory", "FEmy_videos", "FEpurchases")
|
||||
)
|
||||
@@ -0,0 +1,49 @@
|
||||
package app.revanced.patches.youtube.layout.widesearchbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("wide-searchbar-methodtwo-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lkrf;", "h"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@WideSearchbarCompatibility
|
||||
@Version("0.0.1")
|
||||
|
||||
/*
|
||||
public static jis h(Context context, txm txmVar, uag uagVar, txp txpVar) {
|
||||
return fbn.aB(txmVar) ? new jhx(context, txmVar, uagVar, txpVar) : jis.d;
|
||||
}
|
||||
|
||||
Method we search for is located in smali now.
|
||||
See:
|
||||
.method public static h(Landroid/content/Context;Ltxm;Luag;Ltxp;)Ljis;
|
||||
invoke-static {p1}, Lfbn;->aB(Ltxm;)Z //this is the method we want to change. fbn.aB
|
||||
move-result v0
|
||||
if-eqz v0, :cond_c
|
||||
new-instance v0, Ljhx;
|
||||
invoke-direct {v0, p0, p1, p2, p3}, Ljhx;-><init>(Landroid/content/Context;Ltxm;Luag;Ltxp;)V
|
||||
goto :goto_e
|
||||
:cond_c
|
||||
sget-object v0, Ljis;->d:Ljis;
|
||||
:goto_e
|
||||
return-object v0
|
||||
.end method
|
||||
|
||||
*/
|
||||
|
||||
object WideSearchbarTwoFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L", "L"), listOf(
|
||||
Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT, Opcode.IF_EQZ, Opcode.NEW_INSTANCE
|
||||
),
|
||||
null, null
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
package app.revanced.patches.youtube.layout.widesearchbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("wide-searchbar-methodtwo-parent-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lkrf;", "i"
|
||||
)
|
||||
@FuzzyPatternScanMethod(3)
|
||||
@WideSearchbarCompatibility
|
||||
@Version("0.0.1")
|
||||
|
||||
/*
|
||||
This finds following method:
|
||||
public static ies i(br brVar) {
|
||||
bp f = brVar.getSupportFragmentManager().f("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT");
|
||||
if (f != null) {
|
||||
return (kga) f;
|
||||
}
|
||||
return new kga();
|
||||
}
|
||||
*/
|
||||
|
||||
object WideSearchbarTwoParentFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), null,
|
||||
listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT")
|
||||
)
|
||||
@@ -0,0 +1,105 @@
|
||||
package app.revanced.patches.youtube.layout.widesearchbar.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.data.impl.toMethodWalker
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarOneFingerprint
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarOneParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoFingerprint
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch(include = false)
|
||||
@Dependencies(dependencies = [IntegrationsPatch::class])
|
||||
@Name("enable-wide-searchbar")
|
||||
@Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.")
|
||||
@WideSearchbarCompatibility
|
||||
@Version("0.0.1")
|
||||
class WideSearchbarPatch : BytecodePatch(
|
||||
listOf(
|
||||
WideSearchbarOneParentFingerprint, WideSearchbarTwoParentFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
WideSearchbarOneFingerprint.resolve(data, WideSearchbarOneParentFingerprint.result!!.classDef)
|
||||
WideSearchbarTwoFingerprint.resolve(data, WideSearchbarTwoParentFingerprint.result!!.classDef)
|
||||
|
||||
val resultOne = WideSearchbarOneFingerprint.result
|
||||
|
||||
//This should be the method aF in class fbn
|
||||
val targetMethodOne =
|
||||
data.toMethodWalker(resultOne!!.method).nextMethod(resultOne.patternScanResult!!.endIndex, true).getMethod() as MutableMethod
|
||||
|
||||
//Since both methods have the same smali code, inject instructions using a method.
|
||||
addInstructions(targetMethodOne)
|
||||
|
||||
val resultTwo = WideSearchbarTwoFingerprint.result
|
||||
|
||||
//This should be the method aB in class fbn
|
||||
val targetMethodTwo =
|
||||
data.toMethodWalker(resultTwo!!.method).nextMethod(resultTwo.patternScanResult!!.startIndex, true).getMethod() as MutableMethod
|
||||
|
||||
//Since both methods have the same smali code, inject instructions using a method.
|
||||
addInstructions(targetMethodTwo)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private fun addInstructions(method: MutableMethod) {
|
||||
val index = method.implementation!!.instructions.size - 1
|
||||
method.addInstructions(
|
||||
index, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/NewActionbarPatch;->getNewActionBar()Z
|
||||
move-result p0
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
//targetMethodOne: in class fbn
|
||||
/*
|
||||
.method public static aF(Ltxm;)Z
|
||||
invoke-virtual {p0}, Ltxm;->b()Lahah;
|
||||
move-result-object p0
|
||||
iget-object p0, p0, Lahah;->e:Lakfd;
|
||||
if-nez p0, :cond_a
|
||||
sget-object p0, Lakfd;->a:Lakfd;
|
||||
:cond_a
|
||||
iget-boolean p0, p0, Lakfd;->V:Z
|
||||
//added code here:
|
||||
invoke-static {}, app/revanced/integrations/patches/NewActionbarPatch;->getNewActionBar()Z
|
||||
move-result p0
|
||||
//original code here:
|
||||
return p0
|
||||
.end method
|
||||
*/
|
||||
|
||||
//targetMethodTwo: in class fbn
|
||||
/*
|
||||
.method public static aB(Ltxm;)Z
|
||||
invoke-virtual {p0}, Ltxm;->b()Lahah;
|
||||
move-result-object p0
|
||||
iget-object p0, p0, Lahah;->e:Lakfd;
|
||||
if-nez p0, :cond_a
|
||||
sget-object p0, Lakfd;->a:Lakfd;
|
||||
:cond_a
|
||||
iget-boolean p0, p0, Lakfd;->y:Z
|
||||
//added code here:
|
||||
invoke-static {}, app/revanced/integrations/patches/NewActionbarPatch;->getNewActionBar()Z
|
||||
move-result p0
|
||||
//original code here:
|
||||
return p0
|
||||
.end method
|
||||
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.enabledebugging.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf()
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class EnableDebuggingCompatibility
|
||||
@@ -0,0 +1,35 @@
|
||||
package app.revanced.patches.youtube.misc.enabledebugging.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.misc.enabledebugging.annotations.EnableDebuggingCompatibility
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Patch(false)
|
||||
@Name("enable-debugging")
|
||||
@Description("Enables app debugging by patching the manifest file.")
|
||||
@EnableDebuggingCompatibility
|
||||
@Version("0.0.1")
|
||||
class EnableDebuggingPatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
// create an xml editor instance
|
||||
data.xmlEditor["AndroidManifest.xml"].use { dom ->
|
||||
// get the application node
|
||||
val applicationNode = dom
|
||||
.file
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
|
||||
// set application as debuggable
|
||||
applicationNode.setAttribute("android:debuggable", "true")
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.hdrbrightness.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.24.34", "17.24.35", "17.25.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class HDRBrightnessCompatibility
|
||||
@@ -0,0 +1,35 @@
|
||||
package app.revanced.patches.youtube.misc.hdrbrightness.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
@Name("hdrbrightness-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lghz;", "mZ"
|
||||
)
|
||||
@FuzzyPatternScanMethod(3)
|
||||
@HDRBrightnessCompatibility
|
||||
@Version("0.0.1")
|
||||
object HDRBrightnessFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, null,
|
||||
listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_HIGH16,
|
||||
Opcode.IPUT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
),
|
||||
null,
|
||||
customFingerprint = { methodDef ->
|
||||
methodDef.implementation!!.instructions.count() == 16 && methodDef.implementation!!.instructions.any {((it as? NarrowLiteralInstruction)?.narrowLiteral == (-1.0f).toRawBits())}
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patches.youtube.misc.hdrbrightness.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility
|
||||
import app.revanced.patches.youtube.misc.hdrbrightness.fingerprints.HDRBrightnessFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Name("hdr-max-brightness")
|
||||
@Description("Sets brightness to max for HDR videos in fullscreen mode.")
|
||||
@HDRBrightnessCompatibility
|
||||
@Version("0.0.1")
|
||||
class HDRBrightnessPatch : BytecodePatch(
|
||||
listOf(
|
||||
HDRBrightnessFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val result = HDRBrightnessFingerprint.result
|
||||
?: return PatchResultError("HDRBrightnessFingerprint could not resolve the method!")
|
||||
|
||||
|
||||
val method = result.mutableMethod
|
||||
|
||||
//Get the index here, so we know where to inject our code to override -1.0f
|
||||
val index = method.implementation!!.instructions.indexOfFirst { ((it as? NarrowLiteralInstruction)?.narrowLiteral == (-1.0f).toRawBits()) }
|
||||
val register = (method.implementation!!.instructions.get(index) as OneRegisterInstruction).registerA
|
||||
|
||||
method.addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {v$register}, Lapp/revanced/integrations/patches/HDRMaxBrightnessPatch;->getHDRBrightness(F)F
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,20 @@ import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.misc.manifest.annotations.FixLocaleConfigErrorCompatibility
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Name("locale-config-fix")
|
||||
@Description("Fix an error when building the resources by patching the manifest file.")
|
||||
@Description("Fixes an error when building the resources by patching the manifest file.")
|
||||
@FixLocaleConfigErrorCompatibility
|
||||
@Version("0.0.1")
|
||||
class FixLocaleConfigErrorPatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
// create an xml editor instance
|
||||
data.getXmlEditor("AndroidManifest.xml").use {
|
||||
data.xmlEditor["AndroidManifest.xml"].use {
|
||||
// edit the application nodes attribute...
|
||||
val applicationNode = it
|
||||
.file
|
||||
|
||||
@@ -11,7 +11,7 @@ import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Name("resource-id-mapping-provider-resource-patch-dependency")
|
||||
@Description("This patch acts as a provider/ dependency for resource mappings.")
|
||||
@Description("Acts as a provider/dependency for resource mappings.")
|
||||
@Version("0.0.1")
|
||||
class ResourceIdMappingProviderResourcePatch : ResourcePatch() {
|
||||
companion object {
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
||||
]
|
||||
)
|
||||
@Name("microg-support")
|
||||
@Description("Patch to allow YouTube ReVanced to run without root and under a different package name.")
|
||||
@Description("Allows YouTube ReVanced to run without root and under a different package name.")
|
||||
@MicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
class MicroGBytecodePatch : BytecodePatch(
|
||||
@@ -168,4 +168,4 @@ class MicroGBytecodePatch : BytecodePatch(
|
||||
index, "const-string v$register, \"$REVANCED_PACKAGE_NAME\""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user