mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 09:53:55 +01:00
Compare commits
26 Commits
v3.3.0-dev
...
v4.0.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9acf15f571 | ||
|
|
126fe48ce6 | ||
|
|
32d2037083 | ||
|
|
aca1dd6074 | ||
|
|
30c6749f61 | ||
|
|
08c30791ae | ||
|
|
002f11a854 | ||
|
|
861e9a399e | ||
|
|
795aee13e4 | ||
|
|
09f29e6119 | ||
|
|
784aa2f246 | ||
|
|
4ddd5a0b8f | ||
|
|
1482e7e1e8 | ||
|
|
806e94481c | ||
|
|
edcb6eac6d | ||
|
|
4dced95d54 | ||
|
|
62c9085096 | ||
|
|
50a9f09703 | ||
|
|
9633b4eef0 | ||
|
|
2a94ad681c | ||
|
|
9e79e9e72c | ||
|
|
429badef1a | ||
|
|
138b2f8960 | ||
|
|
60d70e5877 | ||
|
|
2debdc1056 | ||
|
|
ad1ea4661f |
82
CHANGELOG.md
82
CHANGELOG.md
@@ -1,3 +1,85 @@
|
||||
# [4.0.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.10...v4.0.0-dev.11) (2024-01-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `19.02.34` ([#2627](https://github.com/ReVanced/revanced-patches/issues/2627)) ([94e08b7](https://github.com/ReVanced/revanced-patches/commit/94e08b74ced394abf9ae7d4fe6355bfe4d0be248))
|
||||
|
||||
# [4.0.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.9...v4.0.0-dev.10) (2024-01-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support versions `18.48.39`, `18.49.37` and `19.01.34` ([#2551](https://github.com/ReVanced/revanced-patches/issues/2551)) ([a938e73](https://github.com/ReVanced/revanced-patches/commit/a938e736fa2aed1792cfdce5656efa15d0791d71))
|
||||
|
||||
# [4.0.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.8...v4.0.0-dev.9) (2024-01-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Enable slide to seek:** Change patch default to excluded and add description disclaimer ([#2610](https://github.com/ReVanced/revanced-patches/issues/2610)) ([2fdc4c2](https://github.com/ReVanced/revanced-patches/commit/2fdc4c23b5f39153ad71071359274c39129d691f))
|
||||
|
||||
# [4.0.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.7...v4.0.0-dev.8) (2024-01-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Shorten setting titles to fit on screen ([#2579](https://github.com/ReVanced/revanced-patches/issues/2579)) ([b2a5dd3](https://github.com/ReVanced/revanced-patches/commit/b2a5dd3efc39ae8a42159858b9c00b5b2f8655a4))
|
||||
|
||||
# [4.0.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.6...v4.0.0-dev.7) (2024-01-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use new integrations patch path ([51e2f3b](https://github.com/ReVanced/revanced-patches/commit/51e2f3b476b49460e2f3fc2b5f302a3a72d7963f))
|
||||
|
||||
# [4.0.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.5...v4.0.0-dev.6) (2024-01-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Tiktok - Playback speed:** Remember playback speed ([#2506](https://github.com/ReVanced/revanced-patches/issues/2506)) ([d2970e5](https://github.com/ReVanced/revanced-patches/commit/d2970e54fbbd7e4b1ae1d354ae2d5c4bbe9336b0))
|
||||
|
||||
# [4.0.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.4...v4.0.0-dev.5) (2024-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Change header:** Improve patch descriptions ([#2581](https://github.com/ReVanced/revanced-patches/issues/2581)) ([43a5677](https://github.com/ReVanced/revanced-patches/commit/43a5677397380f14a049ae95532fd5096b94c938))
|
||||
|
||||
# [4.0.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.3...v4.0.0-dev.4) (2024-01-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **MyFitnessPal:** Add `Hide ads` patch ([#2594](https://github.com/ReVanced/revanced-patches/issues/2594)) ([fd4b3c7](https://github.com/ReVanced/revanced-patches/commit/fd4b3c79a83f8de6256611629263d3e29e66f2c2))
|
||||
|
||||
# [4.0.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.2...v4.0.0-dev.3) (2024-01-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Change package name:** Mention caveat of the patch in the description ([427b81a](https://github.com/ReVanced/revanced-patches/commit/427b81a79a5a1de79f14d2261059fb098b22227f))
|
||||
|
||||
# [4.0.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.1...v4.0.0-dev.2) (2024-01-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Change header:** Change to ReVanced borderless logo header by default ([#2512](https://github.com/ReVanced/revanced-patches/issues/2512)) ([75f785d](https://github.com/ReVanced/revanced-patches/commit/75f785d1ef6026cbbdf7073c10aace1b28d93a30))
|
||||
|
||||
# [4.0.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.2...v4.0.0-dev.1) (2024-01-01)
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* Fix package and code structure ([#2541](https://github.com/ReVanced/revanced-patches/issues/2541)) ([a08457e](https://github.com/ReVanced/revanced-patches/commit/a08457e406f4b2e37458a4835c11d370a02d2ce6))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* Various public APIs have changed names and packages or were removed entirely
|
||||
|
||||
# [3.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.1...v3.3.0-dev.2) (2024-01-01)
|
||||
|
||||
|
||||
|
||||
@@ -333,6 +333,20 @@ public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatch : app
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/myfitnesspal/ads/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/myfitnesspal/ads/HideAdsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/myfitnesspal/ads/fingerprints/IsPremiumUseCaseImplFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
|
||||
public static final field INSTANCE Lapp/revanced/patches/myfitnesspal/ads/fingerprints/IsPremiumUseCaseImplFingerprint;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/myfitnesspal/ads/fingerprints/MainActivityNavigateToNativePremiumUpsellFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
|
||||
public static final field INSTANCE Lapp/revanced/patches/myfitnesspal/ads/fingerprints/MainActivityNavigateToNativePremiumUpsellFingerprint;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -525,6 +539,7 @@ public final class app/revanced/patches/shared/fingerprints/HomeActivityFingerpr
|
||||
|
||||
public abstract class app/revanced/patches/shared/integrations/AbstractIntegrationsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public fun <init> (Ljava/lang/String;Ljava/util/Set;)V
|
||||
public fun <init> (Ljava/util/Set;)V
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
@@ -616,13 +631,6 @@ public abstract class app/revanced/patches/shared/settings/preference/BaseResour
|
||||
public static synthetic fun serialize$default (Lapp/revanced/patches/shared/settings/preference/BaseResource;Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/shared/settings/preference/DefaultBasePreference : app/revanced/patches/shared/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;Ljava/lang/Object;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getDefault ()Ljava/lang/Object;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/settings/preference/SummaryType : java/lang/Enum {
|
||||
public static final field DEFAULT Lapp/revanced/patches/shared/settings/preference/SummaryType;
|
||||
public static final field OFF Lapp/revanced/patches/shared/settings/preference/SummaryType;
|
||||
@@ -650,11 +658,9 @@ public final class app/revanced/patches/shared/settings/preference/impl/InputTyp
|
||||
public static fun values ()[Lapp/revanced/patches/shared/settings/preference/impl/InputType;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/settings/preference/impl/ListPreference : app/revanced/patches/shared/settings/preference/DefaultBasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getEntries ()Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;
|
||||
public final fun getEntryValues ()Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;
|
||||
public final class app/revanced/patches/shared/settings/preference/impl/ListPreference : app/revanced/patches/shared/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
@@ -700,18 +706,18 @@ public final class app/revanced/patches/shared/settings/preference/impl/StringRe
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/settings/preference/impl/SwitchPreference : app/revanced/patches/shared/settings/preference/DefaultBasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Z)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final class app/revanced/patches/shared/settings/preference/impl/SwitchPreference : app/revanced/patches/shared/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getSummaryOff ()Lapp/revanced/patches/shared/settings/preference/impl/StringResource;
|
||||
public final fun getSummaryOn ()Lapp/revanced/patches/shared/settings/preference/impl/StringResource;
|
||||
public final fun getUserDialogMessage ()Lapp/revanced/patches/shared/settings/preference/impl/StringResource;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/settings/preference/impl/TextPreference : app/revanced/patches/shared/settings/preference/DefaultBasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final class app/revanced/patches/shared/settings/preference/impl/TextPreference : app/revanced/patches/shared/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getInputType ()Lapp/revanced/patches/shared/settings/preference/impl/InputType;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
@@ -1136,6 +1142,12 @@ public final class app/revanced/patches/youtube/layout/branding/CustomBrandingPa
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 3.3.0-dev.2
|
||||
version = 4.0.0-dev.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
revanced-patcher = "19.1.0"
|
||||
revanced-patcher = "19.2.0"
|
||||
smali = "3.0.3"
|
||||
guava = "33.0.0-jre"
|
||||
gson = "2.10.1"
|
||||
|
||||
5045
package-lock.json
generated
5045
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.8.0",
|
||||
"gradle-semantic-release-plugin": "^1.9.0",
|
||||
"semantic-release": "^22.0.12"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
)
|
||||
@Suppress("unused")
|
||||
object SpoofWifiPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/integrations/all/connectivity/wifi/spoof/SpoofWifiPatch"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
|
||||
|
||||
override fun filterMap(
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.io.Closeable
|
||||
|
||||
@Patch(
|
||||
name = "Change package name",
|
||||
description = "Appends \".revanced\" to the package name by default.",
|
||||
description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.",
|
||||
use = false
|
||||
)
|
||||
@Suppress("unused")
|
||||
@@ -59,4 +59,4 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
|
||||
|
||||
manifest.setAttribute("package", replacementPackageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
abstract class AbstractTransformInstructionsPatch<T> : BytecodePatch() {
|
||||
|
||||
abstract fun filterMap(
|
||||
classDef: ClassDef,
|
||||
method: Method,
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
@Suppress("unused")
|
||||
object RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
|
||||
"Lapp/revanced/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
|
||||
"Lapp/revanced/integrations/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
|
||||
// Information about method calls we want to replace
|
||||
enum class MethodCall(
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
@Suppress("unused")
|
||||
object RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
|
||||
"Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
|
||||
"Lapp/revanced/integrations/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.patches.myfitnesspal.ads
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.myfitnesspal.ads.fingerprints.IsPremiumUseCaseImplFingerprint
|
||||
import app.revanced.patches.myfitnesspal.ads.fingerprints.MainActivityNavigateToNativePremiumUpsellFingerprint
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Hide ads",
|
||||
description = "Hides most of the ads across the app.",
|
||||
compatiblePackages = [CompatiblePackage("com.myfitnesspal.android")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideAdsPatch : BytecodePatch(
|
||||
setOf(IsPremiumUseCaseImplFingerprint, MainActivityNavigateToNativePremiumUpsellFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Overwrite the premium status specifically for ads.
|
||||
IsPremiumUseCaseImplFingerprint.result?.mutableMethod?.replaceInstructions(
|
||||
0,
|
||||
"""
|
||||
sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;
|
||||
return-object v0
|
||||
"""
|
||||
) ?: throw IsPremiumUseCaseImplFingerprint.exception
|
||||
|
||||
// Prevent the premium upsell dialog from showing when the main activity is launched.
|
||||
// In other places that are premium-only the dialog will still show.
|
||||
MainActivityNavigateToNativePremiumUpsellFingerprint.result?.mutableMethod?.replaceInstructions(
|
||||
0,
|
||||
"return-void"
|
||||
) ?: throw MainActivityNavigateToNativePremiumUpsellFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.myfitnesspal.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object IsPremiumUseCaseImplFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC.value,
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
classDef.type.endsWith("IsPremiumUseCaseImpl;") && methodDef.name == "doWork"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.myfitnesspal.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object MainActivityNavigateToNativePremiumUpsellFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
classDef.type.endsWith("MainActivity;") && methodDef.name == "navigateToNativePremiumUpsell"
|
||||
}
|
||||
)
|
||||
@@ -26,7 +26,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
@Suppress("unused")
|
||||
object HideAdsPatch : BytecodePatch(setOf(AdPostFingerprint, NewAdPostFingerprint)) {
|
||||
private const val FILTER_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/reddit/patches/FilterPromotedLinksPatch;" +
|
||||
"Lapp/revanced/integrations/reddit/patches/FilterPromotedLinksPatch;" +
|
||||
"->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
@@ -11,9 +11,27 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
|
||||
abstract class AbstractIntegrationsPatch(
|
||||
private val integrationsDescriptor: String,
|
||||
private val hooks: Set<IntegrationsFingerprint>
|
||||
) : BytecodePatch(hooks) {
|
||||
|
||||
@Deprecated(
|
||||
"Use the constructor without the integrationsDescriptor parameter",
|
||||
ReplaceWith("AbstractIntegrationsPatch(hooks)")
|
||||
)
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
constructor(
|
||||
integrationsDescriptor: String,
|
||||
hooks: Set<IntegrationsFingerprint>
|
||||
) : this(hooks)
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) throw PatchException(
|
||||
"Integrations have not been merged yet. This patch can not succeed without merging the integrations."
|
||||
)
|
||||
|
||||
for (hook in hooks) hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
}
|
||||
|
||||
/**
|
||||
* [MethodFingerprint] for integrations.
|
||||
*
|
||||
@@ -53,11 +71,7 @@ abstract class AbstractIntegrationsPatch(
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
if (context.findClass(integrationsDescriptor) == null) throw PatchException(
|
||||
"Integrations have not been merged yet. This patch can not succeed without merging the integrations."
|
||||
)
|
||||
|
||||
for (hook in hooks) hook.invoke(integrationsDescriptor)
|
||||
private companion object {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/shared/Utils;"
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import app.revanced.patches.shared.settings.preference.impl.ArrayResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.mergeStrings
|
||||
import org.w3c.dom.Node
|
||||
import java.io.Closeable
|
||||
|
||||
@@ -37,6 +38,8 @@ abstract class AbstractSettingsResourcePatch(
|
||||
stringsEditor = context.xmlEditor["res/values/strings.xml"]
|
||||
arraysEditor = context.xmlEditor["res/values/arrays.xml"]
|
||||
revancedPreferencesEditor = context.xmlEditor["res/xml/$preferenceFileName.xml"]
|
||||
|
||||
context.mergeStrings("settings/host/values/strings.xml")
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package app.revanced.patches.shared.settings.preference
|
||||
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import org.w3c.dom.Document
|
||||
|
||||
/**
|
||||
* Base preference class that also has a default value.
|
||||
*
|
||||
* @param key The key of the preference.
|
||||
* @param title The title of the preference.
|
||||
* @param tag The tag of the preference.
|
||||
* @param summary The summary of the preference.
|
||||
* @param default The default value of the preference.
|
||||
*/
|
||||
abstract class DefaultBasePreference<T>(
|
||||
key: String?,
|
||||
title: StringResource,
|
||||
summary: StringResource? = null,
|
||||
tag: String,
|
||||
val default: T? = null,
|
||||
) : BasePreference(key, title, summary, tag) {
|
||||
|
||||
/**
|
||||
* Serialize preference element to XML.
|
||||
* Overriding methods should invoke super and operate on its return value.
|
||||
* @param ownerDocument Target document to create elements from.
|
||||
* @param resourceCallback Called when a resource has been processed.
|
||||
* @return The serialized element.
|
||||
*/
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply { addDefault(default) }
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.shared.settings.preference.impl
|
||||
|
||||
import app.revanced.patches.shared.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.settings.preference.BaseResource
|
||||
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
|
||||
import app.revanced.patches.shared.settings.preference.addSummary
|
||||
import org.w3c.dom.Document
|
||||
|
||||
@@ -13,16 +13,14 @@ import org.w3c.dom.Document
|
||||
* @param entries The human-readable entries of the list preference.
|
||||
* @param entryValues The entry values of the list preference.
|
||||
* @param summary The summary of the list preference.
|
||||
* @param default The default entry value of the list preference.
|
||||
*/
|
||||
class ListPreference(
|
||||
key: String,
|
||||
title: StringResource,
|
||||
val entries: ArrayResource,
|
||||
val entryValues: ArrayResource,
|
||||
summary: StringResource? = null,
|
||||
default: String? = null,
|
||||
) : DefaultBasePreference<String>(key, title, summary, "ListPreference", default) {
|
||||
private val entries: ArrayResource,
|
||||
private val entryValues: ArrayResource,
|
||||
summary: StringResource? = null
|
||||
) : BasePreference(key, title, summary, "ListPreference") {
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
setAttribute("android:entries", "@array/${entries.also { resourceCallback.invoke(it) }.name}")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package app.revanced.patches.shared.settings.preference.impl
|
||||
|
||||
import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch.Companion.include
|
||||
import app.revanced.patches.shared.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.settings.preference.BaseResource
|
||||
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
|
||||
import app.revanced.patches.shared.settings.preference.SummaryType
|
||||
import app.revanced.patches.shared.settings.preference.addSummary
|
||||
import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch.Companion.include
|
||||
import org.w3c.dom.Document
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@@ -16,15 +16,13 @@ import org.w3c.dom.Element
|
||||
* @param summaryOn The summary to show when the preference is enabled.
|
||||
* @param summaryOff The summary to show when the preference is disabled.
|
||||
* @param userDialogMessage The message to show in a dialog when the user toggles the preference.
|
||||
* @param default The default value of the switch.
|
||||
*/
|
||||
class SwitchPreference(
|
||||
key: String, title: StringResource,
|
||||
val summaryOn: StringResource,
|
||||
val summaryOff: StringResource,
|
||||
val userDialogMessage: StringResource? = null,
|
||||
default: Boolean = false,
|
||||
) : DefaultBasePreference<Boolean>( key, title, null, "SwitchPreference", default) {
|
||||
) : BasePreference(key, title, null, "SwitchPreference") {
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit): Element {
|
||||
userDialogMessage?.include()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.shared.settings.preference.impl
|
||||
|
||||
import app.revanced.patches.shared.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.settings.preference.BaseResource
|
||||
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
|
||||
import org.w3c.dom.Document
|
||||
|
||||
/**
|
||||
@@ -11,16 +11,14 @@ import org.w3c.dom.Document
|
||||
* @param title The title of the text preference.
|
||||
* @param inputType The input type of the text preference.
|
||||
* @param summary The summary of the text preference.
|
||||
* @param default The default value of the text preference.
|
||||
*/
|
||||
class TextPreference(
|
||||
key: String?,
|
||||
title: StringResource,
|
||||
summary: StringResource?,
|
||||
val inputType: InputType = InputType.TEXT,
|
||||
default: String? = null,
|
||||
tag: String = "app.revanced.integrations.settingsmenu.ResettableEditTextPreference"
|
||||
) : DefaultBasePreference<String>(key, title, summary, tag, default) {
|
||||
tag: String = "app.revanced.integrations.shared.settings.preference.ResettableEditTextPreference"
|
||||
) : BasePreference(key, title, summary, tag) {
|
||||
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
|
||||
@@ -36,13 +36,13 @@ object FeedFilterPatch : BytecodePatch(
|
||||
addInstruction(
|
||||
returnFeedItemInstruction.location.index,
|
||||
"invoke-static { v$feedItemsRegister }, " +
|
||||
"Lapp/revanced/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V"
|
||||
"Lapp/revanced/integrations/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V"
|
||||
)
|
||||
} ?: throw FeedApiServiceLIZFingerprint.exception
|
||||
|
||||
SettingsStatusLoadFingerprint.result?.mutableMethod?.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableFeedFilter()V"
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableFeedFilter()V"
|
||||
) ?: throw SettingsStatusLoadFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ object RememberClearDisplayPatch : BytecodePatch(
|
||||
it.addInstructions(
|
||||
isEnabledIndex,
|
||||
"invoke-static { v$isEnabledRegister }, " +
|
||||
"Lapp/revanced/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V"
|
||||
"Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V"
|
||||
)
|
||||
|
||||
// endregion
|
||||
@@ -55,7 +55,7 @@ object RememberClearDisplayPatch : BytecodePatch(
|
||||
# Create a new clearDisplayEvent and post it to the EventBus (https://github.com/greenrobot/EventBus)
|
||||
|
||||
# The state of clear display.
|
||||
invoke-static { }, Lapp/revanced/tiktok/cleardisplay/RememberClearDisplayPatch;->getClearDisplayState()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->getClearDisplayState()Z
|
||||
move-result v3
|
||||
if-eqz v3, :clear_display_disabled
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ object DownloadsPatch : BytecodePatch(
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z
|
||||
move-result v0
|
||||
if-eqz v0, :noremovewatermark
|
||||
const/4 v0, 0x1
|
||||
@@ -99,7 +99,7 @@ object DownloadsPatch : BytecodePatch(
|
||||
downloadUriMethod.addInstructions(
|
||||
secondIndex,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
"""
|
||||
)
|
||||
@@ -107,7 +107,7 @@ object DownloadsPatch : BytecodePatch(
|
||||
downloadUriMethod.addInstructions(
|
||||
firstIndex,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
"""
|
||||
)
|
||||
@@ -115,7 +115,7 @@ object DownloadsPatch : BytecodePatch(
|
||||
SettingsStatusLoadFingerprint to {
|
||||
addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableDownload()V"
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableDownload()V"
|
||||
)
|
||||
}
|
||||
).forEach { (fingerprint, patch) ->
|
||||
|
||||
@@ -1,49 +1,82 @@
|
||||
package app.revanced.patches.tiktok.interaction.speed
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.GetSpeedFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.OnRenderFirstFrameFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SetSpeedFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11x
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch(
|
||||
name = "Playback speed",
|
||||
description = "Enables the playback speed option for all videos.",
|
||||
description = "Enables the playback speed option for all videos and " +
|
||||
"retains the speed configurations in between videos.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) {
|
||||
object PlaybackSpeedPatch : BytecodePatch(
|
||||
setOf(
|
||||
GetSpeedFingerprint,
|
||||
OnRenderFirstFrameFingerprint,
|
||||
SetSpeedFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SpeedControlParentFingerprint.result?.mutableMethod?.apply {
|
||||
val targetMethodCallIndex = indexOfFirstInstruction {
|
||||
if (opcode == Opcode.INVOKE_STATIC) {
|
||||
val paramsTypes = ((this as Instruction35c).reference as MethodReference).parameterTypes
|
||||
paramsTypes.size == 1 && paramsTypes[0].contains("/Aweme;")
|
||||
} else false
|
||||
}
|
||||
SetSpeedFingerprint.result?.let { onVideoSwiped ->
|
||||
// Remember the playback speed of the current video.
|
||||
GetSpeedFingerprint.result?.mutableMethod?.apply {
|
||||
val injectIndex = indexOfFirstInstruction { getReference<MethodReference>()?.returnType == "F" } + 2
|
||||
val register = getInstruction<Instruction11x>(injectIndex - 1).registerA
|
||||
|
||||
val isSpeedEnableMethod = context
|
||||
.toMethodWalker(this)
|
||||
.nextMethod(targetMethodCallIndex, true)
|
||||
.getMethod() as MutableMethod
|
||||
addInstruction(
|
||||
injectIndex,
|
||||
"invoke-static { v$register }," +
|
||||
" Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->rememberPlaybackSpeed(F)V"
|
||||
)
|
||||
} ?: throw GetSpeedFingerprint.exception
|
||||
|
||||
isSpeedEnableMethod.addInstructions(
|
||||
// By default, the playback speed will reset to 1.0 at the start of each video.
|
||||
// Instead, override it with the desired playback speed.
|
||||
OnRenderFirstFrameFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
# Video playback location (e.g. home page, following page or search result page) retrieved using getEnterFrom method.
|
||||
const/4 v0, 0x1
|
||||
invoke-virtual {p0, v0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getEnterFrom(Z)Ljava/lang/String;
|
||||
move-result-object v0
|
||||
|
||||
# Model of current video retrieved using getCurrentAweme method.
|
||||
invoke-virtual {p0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getCurrentAweme()Lcom/ss/android/ugc/aweme/feed/model/Aweme;
|
||||
move-result-object v1
|
||||
|
||||
# Desired playback speed retrieved using getPlaybackSpeed method.
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->getPlaybackSpeed()F
|
||||
move-result-object v2
|
||||
invoke-static { v0, v1, v2 }, ${onVideoSwiped.method}
|
||||
"""
|
||||
) ?: throw OnRenderFirstFrameFingerprint.exception
|
||||
|
||||
// Force enable the playback speed option for all videos.
|
||||
onVideoSwiped.mutableClass.methods.find { method -> method.returnType == "Z" }?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
)
|
||||
} ?: throw SpeedControlParentFingerprint.exception
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
) ?: throw PatchException("Failed to force enable the playback speed option.")
|
||||
} ?: throw SetSpeedFingerprint.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.tiktok.interaction.speed.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object GetSpeedFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onFeedSpeedSelectedEvent"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.tiktok.interaction.speed.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object OnRenderFirstFrameFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.tiktok.interaction.speed.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object SetSpeedFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf(
|
||||
"Ljava/lang/String;",
|
||||
"Lcom/ss/android/ugc/aweme/feed/model/Aweme;",
|
||||
"F"
|
||||
),
|
||||
strings = listOf("enterFrom")
|
||||
)
|
||||
@@ -1,13 +0,0 @@
|
||||
package app.revanced.patches.tiktok.interaction.speed.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object SpeedControlParentFingerprint : MethodFingerprint(
|
||||
strings = listOf(
|
||||
"onStopTrackingTouch, hasTouchMove=",
|
||||
", isCurVideoPaused: ",
|
||||
"already_shown_edge_speed_guide"
|
||||
)
|
||||
)
|
||||
@@ -6,6 +6,5 @@ import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprin
|
||||
|
||||
@Patch(requiresIntegrations = true)
|
||||
object IntegrationsPatch : AbstractIntegrationsPatch(
|
||||
"Lapp/revanced/tiktok/utils/ReVancedUtils;",
|
||||
setOf(InitFingerprint)
|
||||
)
|
||||
@@ -37,10 +37,10 @@ object SettingsPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
|
||||
"Lapp/revanced/integrations/tiktok/settings/AdPersonalizationActivityHook;"
|
||||
|
||||
private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->initialize(" +
|
||||
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
|
||||
")Z"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object SettingsStatusLoadFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("Lapp/revanced/tiktok/settingsmenu/SettingsStatus;") &&
|
||||
methodDef.definingClass.endsWith("Lapp/revanced/integrations/tiktok/settings/SettingsStatus;") &&
|
||||
methodDef.name == "load"
|
||||
}
|
||||
)
|
||||
@@ -85,7 +85,7 @@ object SpoofSimPatch : BytecodePatch() {
|
||||
with(SettingsStatusLoadFingerprint.result!!.mutableMethod) {
|
||||
addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableSimSpoof()V"
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableSimSpoof()V"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ object SpoofSimPatch : BytecodePatch() {
|
||||
addInstructions(
|
||||
index + 2,
|
||||
"""
|
||||
invoke-static {v$resultReg}, Lapp/revanced/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String;
|
||||
invoke-static {v$resultReg}, Lapp/revanced/integrations/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$resultReg
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
object ShowOnLockscreenPatch : BytecodePatch(
|
||||
setOf(BrightnessFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch;"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/tudortmund/lockscreen/ShowOnLockscreenPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
BrightnessFingerprint.result?.mutableMethod?.apply {
|
||||
|
||||
@@ -60,7 +60,7 @@ object TimelineFilterPatch : BytecodePatch(
|
||||
fingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"invoke-static {p$timelineObjectsRegister}, " +
|
||||
"Lapp/revanced/tumblr/patches/TimelineFilterPatch;->" +
|
||||
"Lapp/revanced/integrations/tumblr/patches/TimelineFilterPatch;->" +
|
||||
"filterTimeline(Ljava/util/List;)V"
|
||||
) ?: throw fingerprint.exception
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ object AudioAdsPatch : BytecodePatch(
|
||||
mutableMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/twitch/patches/AudioAdsPatch;->shouldBlockAudioAds()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/twitch/patches/AudioAdsPatch;->shouldBlockAudioAds()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show_audio_ads
|
||||
return-void
|
||||
@@ -52,8 +52,7 @@ object AudioAdsPatch : BytecodePatch(
|
||||
StringResource(
|
||||
"revanced_block_audio_ads_off",
|
||||
"Audio ads are unblocked"
|
||||
),
|
||||
default = true,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ object EmbeddedAdsPatch : BytecodePatch(
|
||||
result.mutableMethod.addInstructions(
|
||||
3,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/twitch/patches/EmbeddedAdsPatch;->createRequestInterceptor()Lapp/revanced/twitch/api/RequestInterceptor;
|
||||
invoke-static {}, Lapp/revanced/integrations/twitch/patches/EmbeddedAdsPatch;->createRequestInterceptor()Lapp/revanced/integrations/twitch/api/RequestInterceptor;
|
||||
move-result-object v2
|
||||
invoke-virtual {v0, v2}, Lokhttp3/OkHttpClient${"$"}Builder;->addInterceptor(Lokhttp3/Interceptor;)Lokhttp3/OkHttpClient${"$"}Builder;
|
||||
"""
|
||||
@@ -59,8 +59,7 @@ object EmbeddedAdsPatch : BytecodePatch(
|
||||
StringResource("key_revanced_proxy_luminous", "luminous"),
|
||||
StringResource("key_revanced_proxy_purpleadblock", "purpleadblock")
|
||||
)
|
||||
),
|
||||
default = "luminous"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
|
||||
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "16.9.1"])]
|
||||
)
|
||||
object VideoAdsPatch : AbstractAdPatch(
|
||||
"Lapp/revanced/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z",
|
||||
"Lapp/revanced/integrations/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z",
|
||||
"show_video_ads",
|
||||
setOf(
|
||||
ContentConfigShowAdsFingerprint,
|
||||
@@ -135,8 +135,7 @@ object VideoAdsPatch : AbstractAdPatch(
|
||||
StringResource(
|
||||
"revanced_block_video_ads_off",
|
||||
"Video ads are unblocked"
|
||||
),
|
||||
default = true
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ object ShowDeletedMessagesPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
private fun createSpoilerConditionInstructions(register: String = "v0") = """
|
||||
invoke-static {}, Lapp/revanced/twitch/patches/ShowDeletedMessagesPatch;->shouldUseSpoiler()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/twitch/patches/ShowDeletedMessagesPatch;->shouldUseSpoiler()Z
|
||||
move-result $register
|
||||
if-eqz $register, :no_spoiler
|
||||
"""
|
||||
@@ -61,7 +61,7 @@ object ShowDeletedMessagesPatch : BytecodePatch(
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {p2}, Lapp/revanced/twitch/patches/ShowDeletedMessagesPatch;->reformatDeletedMessage(Landroid/text/Spanned;)Landroid/text/Spanned;
|
||||
invoke-static {p2}, Lapp/revanced/integrations/twitch/patches/ShowDeletedMessagesPatch;->reformatDeletedMessage(Landroid/text/Spanned;)Landroid/text/Spanned;
|
||||
move-result-object v0
|
||||
if-eqz v0, :no_reformat
|
||||
return-object v0
|
||||
@@ -92,8 +92,7 @@ object ShowDeletedMessagesPatch : BytecodePatch(
|
||||
StringResource("key_revanced_deleted_messages_spoiler", "spoiler"),
|
||||
StringResource("key_revanced_deleted_messages_cross_out", "cross-out")
|
||||
)
|
||||
),
|
||||
default = "cross-out"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ object AutoClaimChannelPointPatch : BytecodePatch(
|
||||
StringResource(
|
||||
"revanced_auto_claim_channel_points_off",
|
||||
"Channel Points are not claimed automatically"
|
||||
),
|
||||
default = true
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -48,7 +47,7 @@ object AutoClaimChannelPointPatch : BytecodePatch(
|
||||
addInstructionsWithLabels(
|
||||
lastIndex, // place in front of return-void
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/twitch/patches/AutoClaimChannelPointsPatch;->shouldAutoClaim()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/twitch/patches/AutoClaimChannelPointsPatch;->shouldAutoClaim()Z
|
||||
move-result v0
|
||||
if-eqz v0, :auto_claim
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ object DebugModePatch : BytecodePatch(
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/twitch/patches/DebugModePatch;->isDebugModeEnabled()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/twitch/patches/DebugModePatch;->isDebugModeEnabled()Z
|
||||
move-result v0
|
||||
return v0
|
||||
"""
|
||||
@@ -49,20 +49,19 @@ object DebugModePatch : BytecodePatch(
|
||||
|
||||
SettingsPatch.PreferenceScreen.MISC.OTHER.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_debug_mode",
|
||||
"revanced_twitch_debug_mode",
|
||||
StringResource(
|
||||
"revanced_debug_mode_enable",
|
||||
"Enable debug mode"
|
||||
"revanced_twitch_debug_mode_title",
|
||||
"Enable Twitch debug mode"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_debug_mode_on",
|
||||
"Debug mode is enabled (not recommended)"
|
||||
"revanced_twitch_debug_mode_summary_on",
|
||||
"Twitch debug mode is enabled (not recommended)"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_debug_mode_off",
|
||||
"Debug mode is disabled"
|
||||
),
|
||||
default = false,
|
||||
"revanced_twitch_debug_mode_summary_off",
|
||||
"Twitch debug mode is disabled"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,5 @@ import app.revanced.patches.twitch.misc.integrations.fingerprints.InitFingerprin
|
||||
|
||||
@Patch(requiresIntegrations = true)
|
||||
object IntegrationsPatch : AbstractIntegrationsPatch(
|
||||
"Lapp/revanced/twitch/utils/ReVancedUtils;",
|
||||
setOf(InitFingerprint)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.twitch.misc.settings
|
||||
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
@@ -14,12 +13,14 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMut
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.settings.preference.impl.PreferenceCategory
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
|
||||
import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsOnClickFingerprint
|
||||
import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsUpdatedFingerprint
|
||||
import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsActivityOnCreateFingerprint
|
||||
import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsMenuItemEnumFingerprint
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
import java.io.Closeable
|
||||
@@ -46,12 +47,12 @@ object SettingsPatch : BytecodePatch(
|
||||
private const val REVANCED_SETTINGS_MENU_ITEM_TITLE_RES = "revanced_settings"
|
||||
private const val REVANCED_SETTINGS_MENU_ITEM_ICON_RES = "ic_settings"
|
||||
|
||||
private const val MENU_ITEM_ENUM_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuItem;"
|
||||
private const val MENU_DISMISS_EVENT_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuViewDelegate\$Event\$OnDismissClicked;"
|
||||
private const val MENU_ITEM_ENUM_CLASS_DESCRIPTOR = "Ltv/twitch/android/feature/settings/menu/SettingsMenuItem;"
|
||||
private const val MENU_DISMISS_EVENT_CLASS_DESCRIPTOR = "Ltv/twitch/android/feature/settings/menu/SettingsMenuViewDelegate\$Event\$OnDismissClicked;"
|
||||
|
||||
private const val INTEGRATIONS_PACKAGE = "app/revanced/twitch"
|
||||
private const val SETTINGS_HOOKS_CLASS = "L$INTEGRATIONS_PACKAGE/settingsmenu/SettingsHooks;"
|
||||
private const val REVANCED_UTILS_CLASS = "L$INTEGRATIONS_PACKAGE/utils/ReVancedUtils;"
|
||||
private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations/twitch"
|
||||
private const val ACTIVITY_HOOKS_CLASS_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settings/AppCompatActivityHook;"
|
||||
private const val UTILS_CLASS_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/Utils;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Hook onCreate to handle fragment creation
|
||||
@@ -60,7 +61,7 @@ object SettingsPatch : BytecodePatch(
|
||||
mutableMethod.addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {p0}, $SETTINGS_HOOKS_CLASS->handleSettingsCreation(Landroidx/appcompat/app/AppCompatActivity;)Z
|
||||
invoke-static {p0}, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingsCreation(Landroidx/appcompat/app/AppCompatActivity;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :no_rv_settings_init
|
||||
return-void
|
||||
@@ -84,8 +85,8 @@ object SettingsPatch : BytecodePatch(
|
||||
mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
sget-object v0, $MENU_ITEM_ENUM_CLASS->$REVANCED_SETTINGS_MENU_ITEM_NAME:$MENU_ITEM_ENUM_CLASS
|
||||
invoke-static {p1, v0}, $SETTINGS_HOOKS_CLASS->handleSettingMenuCreation(Ljava/util/List;Ljava/lang/Object;)Ljava/util/List;
|
||||
sget-object v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR->$REVANCED_SETTINGS_MENU_ITEM_NAME:$MENU_ITEM_ENUM_CLASS_DESCRIPTOR
|
||||
invoke-static {p1, v0}, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingMenuCreation(Ljava/util/List;Ljava/lang/Object;)Ljava/util/List;
|
||||
move-result-object p1
|
||||
"""
|
||||
)
|
||||
@@ -97,10 +98,10 @@ object SettingsPatch : BytecodePatch(
|
||||
mutableMethod.addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {p1}, $SETTINGS_HOOKS_CLASS->handleSettingMenuOnClick(Ljava/lang/Enum;)Z
|
||||
invoke-static {p1}, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingMenuOnClick(Ljava/lang/Enum;)Z
|
||||
move-result p2
|
||||
if-eqz p2, :no_rv_settings_onclick
|
||||
sget-object p1, $MENU_DISMISS_EVENT_CLASS->INSTANCE:$MENU_DISMISS_EVENT_CLASS
|
||||
sget-object p1, $MENU_DISMISS_EVENT_CLASS_DESCRIPTOR->INSTANCE:$MENU_DISMISS_EVENT_CLASS_DESCRIPTOR
|
||||
invoke-virtual {p0, p1}, Ltv/twitch/android/core/mvp/viewdelegate/RxViewDelegate;->pushEvent(Ltv/twitch/android/core/mvp/viewdelegate/ViewDelegateEvent;)V
|
||||
return-void
|
||||
""",
|
||||
@@ -109,8 +110,15 @@ object SettingsPatch : BytecodePatch(
|
||||
} ?: throw MenuGroupsOnClickFingerprint.exception
|
||||
|
||||
addString("revanced_settings", "ReVanced Settings", false)
|
||||
addString("revanced_reboot_message", "Twitch needs to restart to apply your changes. Restart now?", false)
|
||||
addString("revanced_reboot", "Restart", false)
|
||||
|
||||
PreferenceScreen.MISC.OTHER.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_debug",
|
||||
StringResource("revanced_debug_title", "Debug logging"),
|
||||
StringResource("revanced_debug_summary_on", "Debug logs are enabled"),
|
||||
StringResource("revanced_debug_summary_off", "Debug logs are disabled")
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun addString(identifier: String, value: String, formatted: Boolean = true) =
|
||||
@@ -130,7 +138,7 @@ object SettingsPatch : BytecodePatch(
|
||||
ImmutableField(
|
||||
mutableMethod.definingClass,
|
||||
name,
|
||||
MENU_ITEM_ENUM_CLASS,
|
||||
MENU_ITEM_ENUM_CLASS_DESCRIPTOR,
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.ENUM or AccessFlags.STATIC,
|
||||
null,
|
||||
null,
|
||||
@@ -142,17 +150,17 @@ object SettingsPatch : BytecodePatch(
|
||||
mutableMethod.addInstructions(
|
||||
mutableMethod.implementation!!.instructions.size - 4,
|
||||
"""
|
||||
new-instance v0, $MENU_ITEM_ENUM_CLASS
|
||||
new-instance v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR
|
||||
const-string v1, "$titleResourceName"
|
||||
invoke-static {v1}, $REVANCED_UTILS_CLASS->getStringId(Ljava/lang/String;)I
|
||||
invoke-static {v1}, $UTILS_CLASS_DESCRIPTOR->getStringId(Ljava/lang/String;)I
|
||||
move-result v1
|
||||
const-string v3, "$iconResourceName"
|
||||
invoke-static {v3}, $REVANCED_UTILS_CLASS->getDrawableId(Ljava/lang/String;)I
|
||||
invoke-static {v3}, $UTILS_CLASS_DESCRIPTOR->getDrawableId(Ljava/lang/String;)I
|
||||
move-result v3
|
||||
const-string v4, "$name"
|
||||
const/4 v5, $value
|
||||
invoke-direct {v0, v4, v5, v1, v3}, $MENU_ITEM_ENUM_CLASS-><init>(Ljava/lang/String;III)V
|
||||
sput-object v0, $MENU_ITEM_ENUM_CLASS->$name:$MENU_ITEM_ENUM_CLASS
|
||||
invoke-direct {v0, v4, v5, v1, v3}, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR-><init>(Ljava/lang/String;III)V
|
||||
sput-object v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR->$name:$MENU_ITEM_ENUM_CLASS_DESCRIPTOR
|
||||
"""
|
||||
)
|
||||
}
|
||||
@@ -179,7 +187,7 @@ object SettingsPatch : BytecodePatch(
|
||||
key,
|
||||
StringResource("${key}_title", title),
|
||||
preferences.sortedBy { it.title.value },
|
||||
"app.revanced.twitch.settingsmenu.preference.CustomPreferenceCategory"
|
||||
"app.revanced.integrations.twitch.settings.preference.CustomPreferenceCategory"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.io.InvalidClassException
|
||||
object JsonHookPatch : BytecodePatch(
|
||||
setOf(LoganSquareFingerprint)
|
||||
), Closeable {
|
||||
private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
|
||||
private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/integrations/twitter/patches/hook/json"
|
||||
private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
|
||||
private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
|
||||
private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
|
||||
|
||||
@@ -12,4 +12,4 @@ import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
|
||||
compatiblePackages = [CompatiblePackage("com.twitter.android")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
|
||||
object HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/integrations/twitter/patches/hook/patch/ads/AdsHook;")
|
||||
@@ -12,5 +12,5 @@ import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideRecommendedUsersPatch : BaseHookPatchPatch(
|
||||
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
|
||||
"Lapp/revanced/integrations/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
|
||||
)
|
||||
@@ -24,15 +24,17 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"com.google.android.youtube", [
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -65,7 +67,7 @@ object HideAdsPatch : BytecodePatch() {
|
||||
.injectHideViewCall(
|
||||
insertIndex,
|
||||
viewRegister,
|
||||
"Lapp/revanced/integrations/patches/components/AdsFilter;",
|
||||
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;",
|
||||
"hideAdAttributionView"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
|
||||
)
|
||||
object HideAdsResourcePatch : ResourcePatch() {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/AdsFilter;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;"
|
||||
|
||||
internal var adAttributionId: Long = -1
|
||||
|
||||
|
||||
@@ -25,15 +25,18 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/HideGetPremiumPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/HideGetPremiumPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||
|
||||
@@ -29,8 +29,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -53,7 +56,7 @@ object VideoAdsPatch : BytecodePatch(
|
||||
|
||||
loadVideoAdsFingerprintMethod.addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/VideoAdsPatch;->shouldShowAds()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/youtube/patches/VideoAdsPatch;->shouldShowAds()Z
|
||||
move-result v0
|
||||
if-nez v0, :show_video_ads
|
||||
return-void
|
||||
|
||||
@@ -17,22 +17,18 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"com.google.android.youtube", [
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object CopyVideoUrlBytecodePatch : BytecodePatch() {
|
||||
private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
|
||||
private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/youtube/videoplayer"
|
||||
private val BUTTONS_DESCRIPTORS = listOf(
|
||||
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
|
||||
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
|
||||
|
||||
@@ -21,7 +21,18 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube"
|
||||
"com.google.android.youtube", [
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -30,7 +41,7 @@ object RemoveViewerDiscretionDialogPatch : BytecodePatch(
|
||||
setOf(CreateDialogFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/RemoveViewerDiscretionDialogPatch;->" +
|
||||
"Lapp/revanced/integrations/youtube/patches/RemoveViewerDiscretionDialogPatch;->" +
|
||||
"confirmDialog(Landroid/app/AlertDialog;)V"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
@@ -17,22 +17,18 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"com.google.android.youtube", [
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ExternalDownloadsBytecodePatch : BytecodePatch() {
|
||||
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/ExternalDownloadButton;"
|
||||
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
/*
|
||||
|
||||
@@ -27,8 +27,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -38,7 +41,7 @@ object DisablePreciseSeekingGesturePatch : BytecodePatch(
|
||||
setOf(IsSwipingUpFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/DisablePreciseSeekingGesturePatch;->" +
|
||||
"Lapp/revanced/integrations/youtube/patches/DisablePreciseSeekingGesturePatch;->" +
|
||||
"disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
@@ -29,8 +29,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
[
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -85,7 +88,7 @@ object EnableSeekbarTappingPatch : BytecodePatch(
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/youtube/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
${oMethod.toInvokeInstructionString()}
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Enable slide to seek",
|
||||
description = "Adds an option to enable slide to seek instead of playing at 2x speed when pressing and holding in the video player.",
|
||||
description = "Adds an option to enable slide to seek instead of playing at 2x speed when pressing and holding in the video player. Including this patch may cause issues with tapping or double tapping the video player overlay.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
@@ -25,11 +25,15 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
[
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
],
|
||||
use = false
|
||||
)
|
||||
@Suppress("unused")
|
||||
object EnableSlideToSeekPatch : BytecodePatch(
|
||||
@@ -38,7 +42,7 @@ object EnableSlideToSeekPatch : BytecodePatch(
|
||||
DoubleSpeedSeekNoticeFingerprint
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SlideToSeekPatch;"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/SlideToSeekPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.patches.youtube.interaction.swipecontrols
|
||||
|
||||
import app.revanced.util.transformMethods
|
||||
import app.revanced.util.traverseClassHierarchy
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
@@ -10,7 +8,9 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu
|
||||
import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.SwipeControlsHostActivityFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.shared.fingerprints.WatchWhileActivityFingerprint
|
||||
import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint
|
||||
import app.revanced.util.transformMethods
|
||||
import app.revanced.util.traverseClassHierarchy
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
|
||||
@@ -31,8 +31,11 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -40,19 +43,19 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
@Suppress("unused")
|
||||
object SwipeControlsBytecodePatch : BytecodePatch(
|
||||
setOf(
|
||||
WatchWhileActivityFingerprint,
|
||||
MainActivityFingerprint,
|
||||
SwipeControlsHostActivityFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val wrapperClass = SwipeControlsHostActivityFingerprint.result!!.mutableClass
|
||||
val targetClass = WatchWhileActivityFingerprint.result!!.mutableClass
|
||||
val targetClass = MainActivityFingerprint.result!!.mutableClass
|
||||
|
||||
// inject the wrapper class from integrations into the class hierarchy of WatchWhileActivity
|
||||
// Inject the wrapper class from integrations into the class hierarchy of MainActivity.
|
||||
wrapperClass.setSuperClass(targetClass.superclass)
|
||||
targetClass.setSuperClass(wrapperClass.type)
|
||||
|
||||
// ensure all classes and methods in the hierarchy are non-final, so we can override them in integrations
|
||||
// Ensure all classes and methods in the hierarchy are non-final, so we can override them in integrations.
|
||||
context.traverseClassHierarchy(targetClass) {
|
||||
accessFlags = accessFlags and AccessFlags.FINAL.value.inv()
|
||||
transformMethods {
|
||||
|
||||
@@ -8,6 +8,6 @@ internal object SwipeControlsHostActivityFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf(),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass == "Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;"
|
||||
methodDef.definingClass == "Lapp/revanced/integrations/youtube/swipecontrols/SwipeControlsHostActivity;"
|
||||
}
|
||||
)
|
||||
|
||||
@@ -29,8 +29,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
],
|
||||
@@ -57,7 +60,7 @@ object AutoCaptionsPatch : BytecodePatch(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x$enabled
|
||||
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
sput-boolean v0, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
"""
|
||||
) ?: throw fingerprint.exception
|
||||
}
|
||||
@@ -65,10 +68,10 @@ object AutoCaptionsPatch : BytecodePatch(
|
||||
SubtitleTrackFingerprint.result?.mutableMethod?.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :auto_captions_enabled
|
||||
sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
sget-boolean v0, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
if-nez v0, :auto_captions_enabled
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
|
||||
@@ -93,7 +93,7 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||
)
|
||||
}
|
||||
}
|
||||
} else resourceGroups.forEach { context.copyResources("branding", it) }
|
||||
} else resourceGroups.forEach { context.copyResources("custom-branding", it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package app.revanced.patches.youtube.layout.branding.header
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import java.io.File
|
||||
|
||||
@Patch(
|
||||
name = "Change header",
|
||||
description = "Applies a custom header in the top left corner within the app. Defaults to the ReVanced header.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube")
|
||||
],
|
||||
use = false
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ChangeHeaderPatch : ResourcePatch() {
|
||||
private const val HEADER_NAME = "yt_wordmark_header"
|
||||
private const val PREMIUM_HEADER_NAME = "yt_premium_wordmark_header"
|
||||
private const val REVANCED_HEADER_NAME = "ReVanced"
|
||||
private const val REVANCED_BORDERLESS_HEADER_NAME = "ReVanced (borderless logo)"
|
||||
|
||||
private val targetResourceDirectoryNames = arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"mdpi",
|
||||
"hdpi",
|
||||
).map { dpi ->
|
||||
"drawable-$dpi"
|
||||
}
|
||||
|
||||
private val variants = arrayOf("light", "dark")
|
||||
|
||||
private val header by stringPatchOption(
|
||||
key = "header",
|
||||
default = REVANCED_BORDERLESS_HEADER_NAME,
|
||||
values = mapOf(
|
||||
"YouTube" to HEADER_NAME,
|
||||
"YouTube Premium" to PREMIUM_HEADER_NAME,
|
||||
"ReVanced" to REVANCED_HEADER_NAME,
|
||||
"ReVanced (borderless logo)" to REVANCED_BORDERLESS_HEADER_NAME,
|
||||
),
|
||||
title = "Header",
|
||||
description = """
|
||||
Either a header name or a path to a custom header folder to use in the top bar.
|
||||
The path to a folder must contain one or more of the following folders matching the DPI of your device:
|
||||
|
||||
${targetResourceDirectoryNames.joinToString("\n") { "- $it" }}
|
||||
|
||||
These folders must contain the following files:
|
||||
|
||||
${variants.joinToString("\n") { variant -> "- ${HEADER_NAME}_$variant.png" }}
|
||||
""".trimIndent(),
|
||||
required = true,
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
// The directories to copy the header to.
|
||||
val targetResourceDirectories = targetResourceDirectoryNames.mapNotNull {
|
||||
context["res"].resolve(it).takeIf(File::exists)
|
||||
}
|
||||
// The files to replace in the target directories.
|
||||
val targetResourceFiles = targetResourceDirectoryNames.map { directoryName ->
|
||||
ResourceGroup(
|
||||
directoryName,
|
||||
*variants.map { variant -> "${HEADER_NAME}_$variant.png" }.toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that overwrites both header variants from [from] to [to] in the target resource directories.
|
||||
*/
|
||||
val overwriteFromTo: (String, String) -> Unit = { from: String, to: String ->
|
||||
targetResourceDirectories.forEach { directory ->
|
||||
variants.forEach { variant ->
|
||||
val fromPath = directory.resolve("${from}_$variant.png")
|
||||
val toPath = directory.resolve("${to}_$variant.png")
|
||||
|
||||
fromPath.copyTo(toPath, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Functions to overwrite the header to the different variants.
|
||||
val toPremium = { overwriteFromTo(PREMIUM_HEADER_NAME, HEADER_NAME) }
|
||||
val toHeader = { overwriteFromTo(HEADER_NAME, PREMIUM_HEADER_NAME) }
|
||||
val toReVanced = {
|
||||
// Copy the ReVanced header to the resource directories.
|
||||
targetResourceFiles.forEach { context.copyResources("change-header/revanced", it) }
|
||||
|
||||
// Overwrite the premium with the custom header as well.
|
||||
toHeader()
|
||||
}
|
||||
val toReVancedBorderless = {
|
||||
// Copy the ReVanced borderless header to the resource directories.
|
||||
targetResourceFiles.forEach { context.copyResources("change-header/revanced-borderless", it) }
|
||||
|
||||
// Overwrite the premium with the custom header as well.
|
||||
toHeader()
|
||||
}
|
||||
val toCustom = {
|
||||
var copiedReplacementImages = false
|
||||
// For all the resource groups in the custom header folder, copy them to the resource directories.
|
||||
File(header!!).listFiles { file -> file.isDirectory }?.forEach { folder ->
|
||||
val targetDirectory = context["res"].resolve(folder.name)
|
||||
// Skip if the target directory (DPI) doesn't exist.
|
||||
if (!targetDirectory.exists()) return@forEach
|
||||
|
||||
folder.listFiles { file -> file.isFile }?.forEach {
|
||||
val targetResourceFile = targetDirectory.resolve(it.name)
|
||||
|
||||
it.copyTo(targetResourceFile, true)
|
||||
copiedReplacementImages = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!copiedReplacementImages) throw PatchException("Could not find any custom images resources in directory: $header")
|
||||
|
||||
// Overwrite the premium with the custom header as well.
|
||||
toHeader()
|
||||
}
|
||||
|
||||
when (header) {
|
||||
HEADER_NAME -> toHeader
|
||||
PREMIUM_HEADER_NAME -> toPremium
|
||||
REVANCED_HEADER_NAME -> toReVanced
|
||||
REVANCED_BORDERLESS_HEADER_NAME -> toReVancedBorderless
|
||||
else -> toCustom
|
||||
}()
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,9 @@
|
||||
package app.revanced.patches.youtube.layout.branding.header
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
||||
import kotlin.io.path.copyTo
|
||||
|
||||
@Patch(
|
||||
name = "Premium heading",
|
||||
description = "Adds or removes the YouTube Premium logo at the top of feeds.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
@Deprecated("Use PremiumHeadingPatch instead.")
|
||||
object PremiumHeadingPatch : ResourcePatch() {
|
||||
private const val DEFAULT_HEADING_RES = "yt_wordmark_header"
|
||||
private const val PREMIUM_HEADING_RES = "yt_premium_wordmark_header"
|
||||
|
||||
private val usePremiumHeading by booleanPatchOption(
|
||||
key = "usePremiumHeading",
|
||||
default = true,
|
||||
title = "Use premium heading",
|
||||
description = "Whether to use the YouTube Premium logo.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
val resDirectory = context["res"]
|
||||
|
||||
val (original, replacement) = if (usePremiumHeading!!)
|
||||
PREMIUM_HEADING_RES to DEFAULT_HEADING_RES
|
||||
else
|
||||
DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
|
||||
|
||||
val variants = arrayOf("light", "dark")
|
||||
|
||||
arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).mapNotNull { dpi ->
|
||||
resDirectory.resolve("drawable-$dpi").takeIf { it.exists() }?.toPath()
|
||||
}.also {
|
||||
if (it.isEmpty())
|
||||
throw PatchException("The drawable folder can not be found. Therefore, the patch can not be applied.")
|
||||
}.forEach { path ->
|
||||
|
||||
variants.forEach { mode ->
|
||||
val fromPath = path.resolve("${original}_$mode.png")
|
||||
val toPath = path.resolve("${replacement}_$mode.png")
|
||||
|
||||
fromPath.copyTo(toPath, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun execute(context: ResourceContext) = ChangeHeaderPatch.execute(context)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -36,7 +39,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
@Suppress("unused")
|
||||
object HideButtonsPatch : ResourcePatch() {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/ButtonsFilter;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/ButtonsFilter;"
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
|
||||
@@ -37,8 +37,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -78,7 +81,7 @@ object HideAutoplayButtonPatch : BytecodePatch(
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/youtube/patches/HideAutoplayButtonPatch;->isButtonShown()Z
|
||||
move-result v$clobberRegister
|
||||
if-eqz v$clobberRegister, :hidden
|
||||
""",
|
||||
|
||||
@@ -28,8 +28,11 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -58,7 +61,7 @@ object HideCaptionsButtonPatch : BytecodePatch(
|
||||
subtitleButtonControllerMethod.addInstruction(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {v0}, Lapp/revanced/integrations/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V
|
||||
invoke-static {v0}, Lapp/revanced/integrations/youtube/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ object HideCastButtonPatch : BytecodePatch() {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static {p1}, Lapp/revanced/integrations/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I
|
||||
invoke-static {p1}, Lapp/revanced/integrations/youtube/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I
|
||||
move-result p1
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -34,8 +34,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -45,7 +48,7 @@ object NavigationButtonsPatch : BytecodePatch(
|
||||
setOf(AddCreateButtonViewFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/NavigationButtonsPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
|
||||
@@ -32,8 +32,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -72,10 +75,10 @@ object HidePlayerButtonsPatch : BytecodePatch(
|
||||
mutableMethod.addInstructions(
|
||||
callIndex,
|
||||
"""
|
||||
invoke-static { v$hasNextParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
|
||||
invoke-static { v$hasNextParameterRegister }, Lapp/revanced/integrations/youtube/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
|
||||
move-result v$hasNextParameterRegister
|
||||
|
||||
invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
|
||||
invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/youtube/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
|
||||
move-result v$hasPreviousParameterRegister
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -27,8 +27,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -48,7 +51,7 @@ object AlbumCardsPatch : BytecodePatch(
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static {v$albumCardViewRegister}, " +
|
||||
"Lapp/revanced/integrations/patches/HideAlbumCardsPatch;" +
|
||||
"Lapp/revanced/integrations/youtube/patches/HideAlbumCardsPatch;" +
|
||||
"->" +
|
||||
"hideAlbumCard(Landroid/view/View;)V"
|
||||
)
|
||||
|
||||
@@ -27,8 +27,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -50,7 +53,7 @@ object BreakingNewsPatch : BytecodePatch(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {v$breakingNewsViewRegister},
|
||||
Lapp/revanced/integrations/patches/HideBreakingNewsPatch;
|
||||
Lapp/revanced/integrations/youtube/patches/HideBreakingNewsPatch;
|
||||
->
|
||||
hideBreakingNews(Landroid/view/View;)V
|
||||
"""
|
||||
|
||||
@@ -26,8 +26,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -35,7 +38,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
@Suppress("unused")
|
||||
object CommentsPatch : ResourcePatch() {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/CommentsFilter;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/CommentsFilter;"
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
@@ -27,8 +27,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -38,7 +41,7 @@ object CrowdfundingBoxPatch : BytecodePatch(
|
||||
setOf(CrowdfundingBoxFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"
|
||||
"Lapp/revanced/integrations/youtube/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
CrowdfundingBoxFingerprint.result?.let {
|
||||
|
||||
@@ -30,8 +30,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -53,7 +56,7 @@ object HideEndscreenCardsPatch : BytecodePatch(
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
|
||||
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/youtube/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -42,7 +45,7 @@ object HideFilterBarPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/HideFilterBarPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/HideFilterBarPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
FilterBarHeightFingerprint.patch<TwoRegisterInstruction> { register ->
|
||||
|
||||
@@ -23,8 +23,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -34,7 +37,7 @@ object HideFloatingMicrophoneButtonPatch : BytecodePatch(
|
||||
setOf(ShowFloatingMicrophoneButtonFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/HideFloatingMicrophoneButtonPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/HideFloatingMicrophoneButtonPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
ShowFloatingMicrophoneButtonFingerprint.result?.let { result ->
|
||||
|
||||
@@ -23,8 +23,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -34,7 +37,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch(
|
||||
setOf(InitializeAmbientModeFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/DisableFullscreenAmbientModePatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/DisableFullscreenAmbientModePatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
|
||||
@@ -37,8 +37,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -48,9 +51,9 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint)
|
||||
) {
|
||||
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/LayoutComponentsFilter;"
|
||||
private const val DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME =
|
||||
"Lapp/revanced/integrations/patches/components/DescriptionComponentsFilter;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/DescriptionComponentsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
PreferenceScreen.LAYOUT.addPreferences(
|
||||
@@ -97,7 +100,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
"revanced_hide_search_result_recommendations",
|
||||
StringResource(
|
||||
"revanced_hide_search_result_recommendations_title",
|
||||
"Hide search result recommendations (e.g People also watched)"
|
||||
"Hide \\\'People also watched\\\' recommendations"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_search_result_recommendations_summary_on",
|
||||
|
||||
@@ -34,8 +34,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -48,7 +51,7 @@ object HideInfoCardsPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/HideInfoCardsFilterPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/HideInfoCardsFilterPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
InfocardsIncognitoFingerprint.also {
|
||||
@@ -62,7 +65,7 @@ object HideInfoCardsPatch : BytecodePatch(
|
||||
addInstruction(
|
||||
invokeInstructionIndex,
|
||||
"invoke-static {v${getInstruction<FiveRegisterInstruction>(invokeInstructionIndex).registerC}}," +
|
||||
" Lapp/revanced/integrations/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V"
|
||||
" Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,7 +78,7 @@ object HideInfoCardsPatch : BytecodePatch(
|
||||
hideInfoCardsCallMethod.addInstructionsWithLabels(
|
||||
invokeInterfaceIndex,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideInfoCardsPatch;->hideInfoCardsMethodCall()Z
|
||||
invoke-static {}, Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsMethodCall()Z
|
||||
move-result v$toggleRegister
|
||||
if-nez v$toggleRegister, :hide_info_cards
|
||||
""",
|
||||
|
||||
@@ -23,8 +23,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -34,7 +37,7 @@ object HideLoadMoreButtonPatch : BytecodePatch(
|
||||
setOf(HideLoadMoreButtonFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/HideLoadMoreButtonPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
HideLoadMoreButtonFingerprint.result?.let {
|
||||
|
||||
@@ -23,8 +23,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -44,7 +47,7 @@ object HideEmailAddressPatch : BytecodePatch(
|
||||
addInstructions(
|
||||
setVisibilityConstIndex,
|
||||
"""
|
||||
invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/patches/HideEmailAddressPatch;->hideEmailAddress(I)I
|
||||
invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/youtube/patches/HideEmailAddressPatch;->hideEmailAddress(I)I
|
||||
move-result v$setVisibilityConstRegister
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -20,15 +20,20 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
SettingsPatch::class
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube", [
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
])
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube", [
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
@@ -36,7 +41,7 @@ object HidePlayerFlyoutMenuPatch : ResourcePatch() {
|
||||
private const val KEY = "revanced_hide_player_flyout"
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/PlayerFlyoutMenuItemsFilter;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter;"
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
|
||||
@@ -25,8 +25,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"com.google.android.youtube", [
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -38,7 +41,7 @@ object DisableRollingNumberAnimationPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/DisableRollingNumberAnimationsPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/DisableRollingNumberAnimationsPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
|
||||
@@ -31,8 +31,11 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -63,7 +66,7 @@ object HideSeekbarPatch : BytecodePatch(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/HideSeekbarPatch;->hideSeekbar()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/youtube/patches/HideSeekbarPatch;->hideSeekbar()Z
|
||||
move-result v0
|
||||
if-eqz v0, :hide_seekbar
|
||||
return-void
|
||||
|
||||
@@ -35,8 +35,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -51,7 +54,7 @@ object HideShortsComponentsPatch : BytecodePatch(
|
||||
SetPivotBarVisibilityParentFingerprint
|
||||
)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
|
||||
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/ShortsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// region Hide the Shorts shelf.
|
||||
|
||||
@@ -22,8 +22,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -33,7 +36,7 @@ object DisableSuggestedVideoEndScreenPatch : BytecodePatch(
|
||||
setOf(CreateEndScreenViewFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
CreateEndScreenViewFingerprint.result?.let {
|
||||
|
||||
@@ -19,13 +19,15 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube", [
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -48,7 +50,7 @@ object HideTimestampPatch : BytecodePatch(
|
||||
mutableMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/HideTimestampPatch;->hideTimestamp()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/youtube/patches/HideTimestampPatch;->hideTimestamp()Z
|
||||
move-result v0
|
||||
if-eqz v0, :hide_time
|
||||
return-void
|
||||
|
||||
@@ -24,8 +24,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -50,7 +53,7 @@ object PlayerPopupPanelsPatch : BytecodePatch(
|
||||
engagementPanelControllerMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/DisablePlayerPopupPanelsPatch;->disablePlayerPopupPanels()Z
|
||||
invoke-static { }, Lapp/revanced/integrations/youtube/patches/DisablePlayerPopupPanelsPatch;->disablePlayerPopupPanels()Z
|
||||
move-result v0
|
||||
if-eqz v0, :player_popup_panels
|
||||
if-eqz p4, :player_popup_panels
|
||||
|
||||
@@ -18,8 +18,11 @@ import org.w3c.dom.Element
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
],
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
)
|
||||
@Suppress("unused")
|
||||
object CustomPlayerOverlayOpacityPatch : BytecodePatch(setOf(CreatePlayerOverviewFingerprint)) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/CustomPlayerOverlayOpacityPatch;"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/CustomPlayerOverlayOpacityPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
CreatePlayerOverviewFingerprint.result?.let { result ->
|
||||
|
||||
@@ -1,29 +1,45 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike
|
||||
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.ConversionContextFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.DislikeFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.DislikesOldLayoutTextViewFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.LikeFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RemoveLikeFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberMeasureAnimatedTextFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberMeasureStaticLabelFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberMeasureStaticLabelParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberSetterFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberTextViewFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.ShortsTextViewFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentConstructorFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentDataFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentLookupFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.shared.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
|
||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
|
||||
@Patch(
|
||||
name = "Return YouTube Dislike",
|
||||
@@ -38,10 +54,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube", [
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.41",
|
||||
"18.45.43"
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.34"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -49,23 +64,28 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
@Suppress("unused")
|
||||
object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
setOf(
|
||||
ConversionContextFingerprint,
|
||||
TextComponentConstructorFingerprint,
|
||||
TextComponentDataFingerprint,
|
||||
ShortsTextViewFingerprint,
|
||||
DislikesOldLayoutTextViewFingerprint,
|
||||
LikeFingerprint,
|
||||
DislikeFingerprint,
|
||||
RemoveLikeFingerprint,
|
||||
RollingNumberSetterFingerprint,
|
||||
RollingNumberMeasureTextParentFingerprint,
|
||||
RollingNumberMeasureStaticLabelParentFingerprint,
|
||||
RollingNumberMeasureAnimatedTextFingerprint,
|
||||
RollingNumberTextViewFingerprint,
|
||||
RollingNumberTextViewAnimationUpdateFingerprint
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch;"
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch;"
|
||||
"Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
|
||||
|
||||
private fun MethodFingerprint.resultOrThrow() = result ?: throw exception
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
|
||||
@@ -97,174 +117,54 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hook creation of Spans and the cached lookup of them.
|
||||
// region Hook code for creation and cached lookup of text Spans.
|
||||
|
||||
// Alternatively the hook can be made at the creation of Spans in TextComponentSpec,
|
||||
// And it works in all situations except it fails to update the Span when the user dislikes,
|
||||
// since the underlying (likes only) text did not change.
|
||||
// This hook handles all situations, as it's where the created Spans are stored and later reused.
|
||||
TextComponentContextFingerprint.also {
|
||||
if (!it.resolve(context, TextComponentConstructorFingerprint.result!!.classDef))
|
||||
throw it.exception
|
||||
}.result?.also { result ->
|
||||
if (!TextComponentAtomicReferenceFingerprint.resolve(context, result.method, result.classDef))
|
||||
throw TextComponentAtomicReferenceFingerprint.exception
|
||||
}?.let { textComponentContextFingerprintResult ->
|
||||
val conversionContextIndex = textComponentContextFingerprintResult
|
||||
.scanResult.patternScanResult!!.endIndex
|
||||
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
|
||||
.scanResult.patternScanResult!!.startIndex
|
||||
TextComponentConstructorFingerprint.result?.let { textConstructorResult ->
|
||||
// Find the field name of the conversion context.
|
||||
val conversionContextClassType = ConversionContextFingerprint.resultOrThrow().classDef.type
|
||||
val conversionContextField = textConstructorResult.classDef.fields.find {
|
||||
it.type == conversionContextClassType
|
||||
} ?: throw PatchException("Could not find conversion context field")
|
||||
|
||||
val insertIndex = atomicReferenceStartIndex + 9
|
||||
TextComponentLookupFingerprint.resolve(context, textConstructorResult.classDef)
|
||||
TextComponentLookupFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
// Find the instruction for creating the text data object.
|
||||
val textDataClassType = TextComponentDataFingerprint.resultOrThrow().classDef.type
|
||||
val insertIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.NEW_INSTANCE &&
|
||||
getReference<TypeReference>()?.type == textDataClassType
|
||||
}
|
||||
if (insertIndex < 0) throw PatchException("Could not find data creation instruction")
|
||||
val tempRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
textComponentContextFingerprintResult.mutableMethod.apply {
|
||||
// Get the conversion context obfuscated field name
|
||||
val conversionContextFieldReference =
|
||||
getInstruction<ReferenceInstruction>(conversionContextIndex).reference
|
||||
|
||||
// Free register to hold the conversion context
|
||||
val freeRegister =
|
||||
getInstruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB
|
||||
|
||||
val atomicReferenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 6).registerC
|
||||
|
||||
// Instruction that is replaced, and also has the CharacterSequence register.
|
||||
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
|
||||
val charSequenceSourceRegister = moveCharSequenceInstruction.registerB
|
||||
val charSequenceTargetRegister = moveCharSequenceInstruction.registerA
|
||||
|
||||
// Move the current instance to the free register, and get the conversion context from it.
|
||||
// Must replace the instruction to preserve the control flow label.
|
||||
replaceInstruction(insertIndex, "move-object/from16 v$freeRegister, p0")
|
||||
addInstructions(
|
||||
insertIndex + 1,
|
||||
"""
|
||||
# Move context to free register
|
||||
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
|
||||
invoke-static {v$freeRegister, v$atomicReferenceRegister, v$charSequenceSourceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$freeRegister
|
||||
# Replace the original instruction
|
||||
move-object v${charSequenceTargetRegister}, v${freeRegister}
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw TextComponentContextFingerprint.exception
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hook rolling numbers.
|
||||
|
||||
RollingNumberSetterFingerprint.result?.let {
|
||||
val dislikesIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = 1
|
||||
|
||||
val charSequenceInstanceRegister =
|
||||
getInstruction<OneRegisterInstruction>(0).registerA
|
||||
val charSequenceFieldReference =
|
||||
getInstruction<ReferenceInstruction>(dislikesIndex).reference.toString()
|
||||
|
||||
val registerCount = implementation!!.registerCount
|
||||
|
||||
// This register is being overwritten, so it is free to use.
|
||||
val freeRegister = registerCount - 1
|
||||
val conversionContextRegister = registerCount - parameters.size + 1
|
||||
// Find the instruction that sets the span to an instance field.
|
||||
// The instruction is only a few lines after the creation of the instance.
|
||||
// The method has multiple iput-object instructions using a CharSequence,
|
||||
// so verify the found instruction is in the expected location.
|
||||
val putFieldInstruction = implementation!!.instructions
|
||||
.subList(insertIndex, insertIndex + 20)
|
||||
.find {
|
||||
it.opcode == Opcode.IPUT_OBJECT &&
|
||||
it.getReference<FieldReference>()?.type == "Ljava/lang/CharSequence;"
|
||||
} ?: throw PatchException("Could not find put object instruction")
|
||||
val charSequenceRegister = (putFieldInstruction as TwoRegisterInstruction).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
||||
invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$freeRegister
|
||||
iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
||||
"""
|
||||
# Copy conversion context
|
||||
move-object/from16 v$tempRegister, p0
|
||||
iget-object v$tempRegister, v$tempRegister, $conversionContextField
|
||||
invoke-static {v$tempRegister, v$charSequenceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$charSequenceRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw RollingNumberSetterFingerprint.exception
|
||||
|
||||
// Rolling Number text views use the measured width of the raw string for layout.
|
||||
// Modify the measure text calculation to include the left drawable separator if needed.
|
||||
RollingNumberMeasureAnimatedTextFingerprint.also {
|
||||
if (!it.resolve(context, RollingNumberMeasureTextParentFingerprint.result!!.classDef))
|
||||
throw it.exception
|
||||
}.result?.also {
|
||||
it.mutableMethod.apply {
|
||||
val returnInstructionIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val measuredTextWidthRegister =
|
||||
getInstruction<OneRegisterInstruction>(returnInstructionIndex).registerA
|
||||
|
||||
replaceInstruction( // Replace instruction to preserve control flow label.
|
||||
returnInstructionIndex,
|
||||
"invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F"
|
||||
)
|
||||
addInstructions(
|
||||
returnInstructionIndex + 1,
|
||||
"""
|
||||
move-result v$measuredTextWidthRegister
|
||||
return v$measuredTextWidthRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw RollingNumberMeasureAnimatedTextFingerprint.exception
|
||||
|
||||
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
||||
// and sometimes used for initial video load.
|
||||
RollingNumberMeasureStaticLabelFingerprint.also {
|
||||
if (!it.resolve(context, RollingNumberMeasureTextParentFingerprint.result!!.classDef))
|
||||
throw it.exception
|
||||
}.result?.also {
|
||||
it.mutableMethod.apply {
|
||||
val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||
val freeRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
||||
|
||||
addInstructions(
|
||||
measureTextIndex + 1,
|
||||
"""
|
||||
move-result v$freeRegister
|
||||
invoke-static {p1, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw RollingNumberMeasureStaticLabelFingerprint.exception
|
||||
|
||||
// The rolling number Span is missing styling since it's initially set as a String.
|
||||
// Modify the UI text view and use the styled like/dislike Span.
|
||||
RollingNumberTextViewFingerprint.result?.let {
|
||||
// Initial TextView is set in this method.
|
||||
val initiallyCreatedTextViewMethod = it.mutableMethod
|
||||
|
||||
// Videos less than 24 hours after uploaded, like counts will be updated in real time.
|
||||
// Whenever like counts are updated, TextView is set in this method.
|
||||
val realTimeUpdateTextViewMethod =
|
||||
RollingNumberTextViewAnimationUpdateFingerprint.result?.mutableMethod
|
||||
?: throw RollingNumberTextViewAnimationUpdateFingerprint.exception
|
||||
|
||||
arrayOf(
|
||||
initiallyCreatedTextViewMethod,
|
||||
realTimeUpdateTextViewMethod
|
||||
).forEach { insertMethod ->
|
||||
insertMethod.apply {
|
||||
val setTextIndex = indexOfFirstInstruction {
|
||||
getReference<MethodReference>()?.name == "setText"
|
||||
}
|
||||
|
||||
val textViewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setTextIndex).registerC
|
||||
val textSpanRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setTextIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
setTextIndex,
|
||||
"""
|
||||
invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$textSpanRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: throw RollingNumberTextViewFingerprint.exception
|
||||
} ?: throw TextComponentConstructorFingerprint.exception
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -335,6 +235,120 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
} ?: throw DislikesOldLayoutTextViewFingerprint.exception
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region Hook rolling numbers.
|
||||
|
||||
// Do this last to allow patching old unsupported versions (if the user really wants),
|
||||
// On older unsupported version this will fail to resolve and throw an exception,
|
||||
// but everything will still work correctly anyways.
|
||||
|
||||
RollingNumberSetterFingerprint.result?.let {
|
||||
val dislikesIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = 1
|
||||
|
||||
val charSequenceInstanceRegister =
|
||||
getInstruction<OneRegisterInstruction>(0).registerA
|
||||
val charSequenceFieldReference =
|
||||
getInstruction<ReferenceInstruction>(dislikesIndex).reference
|
||||
|
||||
val registerCount = implementation!!.registerCount
|
||||
|
||||
// This register is being overwritten, so it is free to use.
|
||||
val freeRegister = registerCount - 1
|
||||
val conversionContextRegister = registerCount - parameters.size + 1
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
||||
invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$freeRegister
|
||||
iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw RollingNumberSetterFingerprint.exception
|
||||
|
||||
// Rolling Number text views use the measured width of the raw string for layout.
|
||||
// Modify the measure text calculation to include the left drawable separator if needed.
|
||||
RollingNumberMeasureAnimatedTextFingerprint.result?.also {
|
||||
val scanResult = it.scanResult.patternScanResult!!
|
||||
// Additional check to verify the opcodes are at the start of the method
|
||||
if (scanResult.startIndex != 0) throw PatchException("Unexpected opcode location")
|
||||
val endIndex = scanResult.endIndex
|
||||
it.mutableMethod.apply {
|
||||
val measuredTextWidthRegister = getInstruction<OneRegisterInstruction>(endIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
endIndex + 1,
|
||||
"""
|
||||
invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||
move-result v$measuredTextWidthRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw RollingNumberMeasureAnimatedTextFingerprint.exception
|
||||
|
||||
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
||||
// and sometimes used for initial video load.
|
||||
RollingNumberMeasureStaticLabelFingerprint.resolve(context, RollingNumberMeasureStaticLabelParentFingerprint.resultOrThrow().classDef)
|
||||
RollingNumberMeasureStaticLabelFingerprint.result?.also {
|
||||
val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||
it.mutableMethod.apply {
|
||||
val freeRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
||||
|
||||
addInstructions(
|
||||
measureTextIndex + 1,
|
||||
"""
|
||||
move-result v$freeRegister
|
||||
invoke-static {p1, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw RollingNumberMeasureStaticLabelFingerprint.exception
|
||||
|
||||
// The rolling number Span is missing styling since it's initially set as a String.
|
||||
// Modify the UI text view and use the styled like/dislike Span.
|
||||
RollingNumberTextViewFingerprint.result?.let {
|
||||
// Initial TextView is set in this method.
|
||||
val initiallyCreatedTextViewMethod = it.mutableMethod
|
||||
|
||||
// Videos less than 24 hours after uploaded, like counts will be updated in real time.
|
||||
// Whenever like counts are updated, TextView is set in this method.
|
||||
val realTimeUpdateTextViewMethod =
|
||||
RollingNumberTextViewAnimationUpdateFingerprint.result?.mutableMethod
|
||||
?: throw RollingNumberTextViewAnimationUpdateFingerprint.exception
|
||||
|
||||
arrayOf(
|
||||
initiallyCreatedTextViewMethod,
|
||||
realTimeUpdateTextViewMethod
|
||||
).forEach { insertMethod ->
|
||||
insertMethod.apply {
|
||||
val setTextIndex = indexOfFirstInstruction {
|
||||
getReference<MethodReference>()?.name == "setText"
|
||||
}
|
||||
|
||||
val textViewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setTextIndex).registerC
|
||||
val textSpanRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setTextIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
setTextIndex,
|
||||
"""
|
||||
invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$textSpanRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: throw RollingNumberTextViewFingerprint.exception
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
|
||||
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object ConversionContextFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String;",
|
||||
parameters = listOf(),
|
||||
strings = listOf(
|
||||
", widthConstraint=",
|
||||
", heightConstraint=",
|
||||
", templateLoggerFactory=",
|
||||
", rootDisposableContainer=",
|
||||
// 18.37.36 and after this String is: ConversionContext{containerInternal=
|
||||
// and before it is: ConversionContext{container=
|
||||
// Use a partial string to match both.
|
||||
"ConversionContext{container"
|
||||
)
|
||||
)
|
||||
@@ -5,19 +5,24 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves to class found in [RollingNumberMeasureTextParentFingerprint].
|
||||
*/
|
||||
internal object RollingNumberMeasureAnimatedTextFingerprint : MethodFingerprint(
|
||||
returnType = "F",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Ljava/lang/String;"),
|
||||
returnType = "Lj\$/util/Optional;",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf(
|
||||
"L",
|
||||
"Ljava/lang/String;",
|
||||
"L"
|
||||
),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IGET, // First instruction of method
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CONST_HIGH16,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.ADD_FLOAT_2ADDR,
|
||||
Opcode.ADD_INT_LIT8,
|
||||
Opcode.GOTO,
|
||||
Opcode.RETURN
|
||||
Opcode.CONST_4,
|
||||
Opcode.AGET,
|
||||
Opcode.CONST_4,
|
||||
Opcode.CONST_4, // Measured text width
|
||||
)
|
||||
)
|
||||
@@ -6,7 +6,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves to class found in [RollingNumberMeasureTextParentFingerprint].
|
||||
* Resolves to class found in [RollingNumberMeasureStaticLabelParentFingerprint].
|
||||
*/
|
||||
internal object RollingNumberMeasureStaticLabelFingerprint : MethodFingerprint(
|
||||
returnType = "F",
|
||||
|
||||
@@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object RollingNumberMeasureTextParentFingerprint : MethodFingerprint(
|
||||
internal object RollingNumberMeasureStaticLabelParentFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String;",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf(),
|
||||
@@ -1,33 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves against the same method that [TextComponentContextFingerprint] resolves to.
|
||||
*/
|
||||
internal object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_OBJECT, // Register B is free register
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
null,
|
||||
Opcode.INVOKE_VIRTUAL, // Register C is atomic reference
|
||||
Opcode.MOVE_RESULT_OBJECT, // Register A is char sequence
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.MOVE_OBJECT, // Replace this instruction with patch code
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.GOTO
|
||||
)
|
||||
)
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves against the same class that [TextComponentConstructorFingerprint] resolves to.
|
||||
*/
|
||||
internal object TextComponentContextFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.INVOKE_STATIC_RANGE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT, // conversion context field name
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object TextComponentDataFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("L", "L"),
|
||||
strings = listOf("text"),
|
||||
customFingerprint = { _, classDef ->
|
||||
val fields = classDef.fields
|
||||
fields.find { it.type == "Ljava/util/BitSet;" } != null &&
|
||||
fields.find { it.type == "[Ljava/lang/String;" } != null
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
/**
|
||||
* Resolves against the same class that [TextComponentConstructorFingerprint] resolves to.
|
||||
*/
|
||||
internal object TextComponentLookupFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
strings = listOf("…")
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user