Compare commits

..

20 Commits

Author SHA1 Message Date
semantic-release-bot
002f11a854 chore(release): 4.0.0-dev.8 [skip ci]
# [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)) ([861e9a3](861e9a399e))
2024-01-10 11:28:55 +00:00
KobeW50
861e9a399e fix(YouTube): Shorten setting titles to fit on screen (#2579) 2024-01-10 15:26:24 +04:00
oSumAtrIX
795aee13e4 build: Bump dependencies 2024-01-10 09:33:02 +01:00
semantic-release-bot
09f29e6119 chore(release): 4.0.0-dev.7 [skip ci]
# [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 ([784aa2f](784aa2f246))
2024-01-10 08:16:50 +00:00
oSumAtrIX
784aa2f246 fix: Use new integrations patch path 2024-01-10 09:14:12 +01:00
oSumAtrIX
4ddd5a0b8f chore: Update CI dependencies 2024-01-09 20:14:14 +01:00
semantic-release-bot
1482e7e1e8 chore(release): 4.0.0-dev.6 [skip ci]
# [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)) ([806e944](806e94481c))
2024-01-09 19:12:34 +00:00
d4rkk3y
806e94481c feat(Tiktok - Playback speed): Remember playback speed (#2506)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-01-09 20:10:29 +01:00
semantic-release-bot
edcb6eac6d chore(release): 4.0.0-dev.5 [skip ci]
# [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)) ([62c9085](62c9085096))
2024-01-09 19:09:58 +00:00
LisoUseInAIKyrios
4dced95d54 refactor(YouTube - Return YouTube Dislike): Make patch more robust by removing opcode patterns from fingerprints (#2602) 2024-01-09 23:08:01 +04:00
KobeW50
62c9085096 fix(YouTube - Change header): Improve patch descriptions (#2581) 2024-01-09 20:07:11 +01:00
semantic-release-bot
50a9f09703 chore(release): 4.0.0-dev.4 [skip ci]
# [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)) ([9633b4e](9633b4eef0))
2024-01-09 17:28:21 +00:00
mrwedders
9633b4eef0 feat(MyFitnessPal): Add Hide ads patch (#2594)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-01-09 18:26:15 +01:00
semantic-release-bot
2a94ad681c chore(release): 4.0.0-dev.3 [skip ci]
# [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 ([9e79e9e](9e79e9e72c))
2024-01-09 15:41:21 +00:00
oSumAtrIX
9e79e9e72c feat(Change package name): Mention caveat of the patch in the description 2024-01-09 16:39:23 +01:00
LisoUseInAIKyrios
429badef1a fix:(YouTube - Spoof app version): Adjust spoof target description (#2578) 2024-01-03 19:14:32 +04:00
semantic-release-bot
138b2f8960 chore(release): 4.0.0-dev.2 [skip ci]
# [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)) ([60d70e5](60d70e5877))
2024-01-02 14:36:22 +00:00
oSumAtrIX
60d70e5877 feat(YouTube - Change header): Change to ReVanced borderless logo header by default (#2512)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2024-01-02 15:34:20 +01:00
semantic-release-bot
2debdc1056 chore(release): 4.0.0-dev.1 [skip ci]
# [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)) ([ad1ea46](ad1ea4661f))

### BREAKING CHANGES

* Various public APIs have changed names and packages or were removed entirely
2024-01-01 15:35:13 +00:00
oSumAtrIX
ad1ea4661f refactor: Fix package and code structure (#2541)
BREAKING CHANGE: Various public APIs have changed names and packages or were removed entirely
2024-01-01 16:33:07 +01:00
174 changed files with 5543 additions and 899 deletions

View File

@@ -1,3 +1,64 @@
# [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)

View File

@@ -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

View File

@@ -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.8

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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(

View File

@@ -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)
}
}
}

View File

@@ -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,

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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
}
}

View File

@@ -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"
}
)

View File

@@ -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"
}
)

View File

@@ -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) {

View File

@@ -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;"
}
}

View File

@@ -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 {

View File

@@ -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) }
}

View File

@@ -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}")

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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) ->

View File

@@ -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
}
}
}

View File

@@ -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"
}
)

View File

@@ -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"
}
)

View File

@@ -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")
)

View File

@@ -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"
)
)

View File

@@ -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)
)

View File

@@ -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"

View File

@@ -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"
}
)

View File

@@ -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
"""
)

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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,
)
)
)
}

View File

@@ -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"
)
)
)

View File

@@ -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
)
)
)
}

View File

@@ -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"
)
)
)

View File

@@ -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

View File

@@ -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"
)
)
)
}

View File

@@ -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)
)
)

View File

@@ -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"
)
}
}

View File

@@ -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;"

View File

@@ -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;")

View File

@@ -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;"
)

View File

@@ -65,7 +65,7 @@ object HideAdsPatch : BytecodePatch() {
.injectHideViewCall(
insertIndex,
viewRegister,
"Lapp/revanced/integrations/patches/components/AdsFilter;",
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;",
"hideAdAttributionView"
)
}

View File

@@ -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

View File

@@ -33,7 +33,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
)
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(

View File

@@ -53,7 +53,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

View File

@@ -32,7 +32,7 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
)
@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;"

View File

@@ -30,7 +30,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) {

View File

@@ -32,7 +32,7 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
)
@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) {
/*

View File

@@ -38,7 +38,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) {

View File

@@ -85,7 +85,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()}

View File

@@ -38,7 +38,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(

View File

@@ -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;"
}
)

View File

@@ -57,7 +57,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 +65,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

View File

@@ -93,7 +93,7 @@ object CustomBrandingPatch : ResourcePatch() {
)
}
}
} else resourceGroups.forEach { context.copyResources("branding", it) }
} else resourceGroups.forEach { context.copyResources("custom-branding", it) }
}
}

View File

@@ -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
}()
}
}

View File

@@ -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)
}

View File

@@ -36,7 +36,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(

View File

@@ -78,7 +78,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
""",

View File

@@ -58,7 +58,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
"""
)
}

View File

@@ -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
"""
)

View File

@@ -45,7 +45,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(

View File

@@ -72,10 +72,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
"""
)

View File

@@ -48,7 +48,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"
)

View File

@@ -50,7 +50,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
"""

View File

@@ -35,7 +35,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)

View File

@@ -38,7 +38,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 {

View File

@@ -53,7 +53,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"
)
}
}

View File

@@ -42,7 +42,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 ->

View File

@@ -34,7 +34,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 ->

View File

@@ -34,7 +34,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(

View File

@@ -48,9 +48,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 +97,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",

View File

@@ -48,7 +48,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 +62,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 +75,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
""",

View File

@@ -34,7 +34,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 {

View File

@@ -44,7 +44,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
"""
)

View File

@@ -36,7 +36,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(

View File

@@ -38,7 +38,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(

View File

@@ -63,7 +63,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

View File

@@ -51,7 +51,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.

View File

@@ -33,7 +33,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 {

View File

@@ -48,7 +48,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

View File

@@ -50,7 +50,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

View File

@@ -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 ->

View File

@@ -1,8 +1,5 @@
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
@@ -11,19 +8,39 @@ 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.RollingNumberMeasureTextParentFingerprint
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,6 +55,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", [
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.41",
@@ -49,7 +67,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Suppress("unused")
object ReturnYouTubeDislikePatch : BytecodePatch(
setOf(
ConversionContextFingerprint,
TextComponentConstructorFingerprint,
TextComponentDataFingerprint,
ShortsTextViewFingerprint,
DislikesOldLayoutTextViewFingerprint,
LikeFingerprint,
@@ -62,10 +82,12 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
)
) {
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,64 +119,132 @@ 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
// 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
// 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}
insertIndex,
"""
# 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 TextComponentContextFingerprint.exception
} ?: throw TextComponentConstructorFingerprint.exception
// endregion
// region Hook for non-litho Short videos.
ShortsTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val patternResult = it.scanResult.patternScanResult!!
// If the field is true, the TextView is for a dislike button.
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference
val textViewFieldReference = // Like/Dislike button TextView field
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
// Check if the hooked TextView object is that of the dislike button.
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
// Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
val insertIndex = patternResult.startIndex + 6
addInstructionsWithLabels(
insertIndex,
"""
# Check, if the TextView is for a dislike button
iget-boolean v0, p0, $isDisLikesBooleanReference
if-eqz v0, :is_like
# Hook the TextView, if it is for the dislike button
iget-object v0, p0, $textViewFieldReference
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
move-result v0
if-eqz v0, :ryd_disabled
return-void
:is_like
:ryd_disabled
nop
"""
)
}
} ?: throw ShortsTextViewFingerprint.exception
// endregion
// region Hook for litho Shorts
// Filter that parses the video id from the UI
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// Player response video id is needed to search for the video ids in Shorts litho components.
VideoIdPatch.hookPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
// endregion
// region Hook old UI layout dislikes, for the older app spoofs used with spoof-app-version.
DislikesOldLayoutTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
val resourceIdentifierRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
val textViewRegister = getInstruction<OneRegisterInstruction>(startIndex + 4).registerA
addInstruction(
startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
} ?: 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
@@ -164,7 +254,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
val charSequenceInstanceRegister =
getInstruction<OneRegisterInstruction>(0).registerA
val charSequenceFieldReference =
getInstruction<ReferenceInstruction>(dislikesIndex).reference.toString()
getInstruction<ReferenceInstruction>(dislikesIndex).reference
val registerCount = implementation!!.registerCount
@@ -268,73 +358,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
// endregion
// region Hook for non-litho Short videos.
ShortsTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val patternResult = it.scanResult.patternScanResult!!
// If the field is true, the TextView is for a dislike button.
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference
val textViewFieldReference = // Like/Dislike button TextView field
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
// Check if the hooked TextView object is that of the dislike button.
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
// Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
val insertIndex = patternResult.startIndex + 6
addInstructionsWithLabels(
insertIndex,
"""
# Check, if the TextView is for a dislike button
iget-boolean v0, p0, $isDisLikesBooleanReference
if-eqz v0, :is_like
# Hook the TextView, if it is for the dislike button
iget-object v0, p0, $textViewFieldReference
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
move-result v0
if-eqz v0, :ryd_disabled
return-void
:is_like
:ryd_disabled
nop
"""
)
}
} ?: throw ShortsTextViewFingerprint.exception
// endregion
// region Hook for litho Shorts
// Filter that parses the video id from the UI
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// Player response video id is needed to search for the video ids in Shorts litho components.
VideoIdPatch.hookPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
// endregion
// region Hook old UI layout dislikes, for the older app spoofs used with spoof-app-version.
DislikesOldLayoutTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
val resourceIdentifierRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
val textViewRegister = getInstruction<OneRegisterInstruction>(startIndex + 4).registerA
addInstruction(
startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
} ?: throw DislikesOldLayoutTextViewFingerprint.exception
// endregion
}
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)

View File

@@ -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"
)
)

View File

@@ -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
)
)

View File

@@ -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

View File

@@ -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
)
)

View File

@@ -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
}
)

View File

@@ -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("")
)

View File

@@ -80,7 +80,7 @@ object WideSearchbarPatch : BytecodePatch(
addInstructions(
implementation!!.instructions.size - 1,
"""
invoke-static {}, Lapp/revanced/integrations/patches/WideSearchbarPatch;->enableWideSearchbar()Z
invoke-static {}, Lapp/revanced/integrations/youtube/patches/WideSearchbarPatch;->enableWideSearchbar()Z
move-result p0
"""
)

View File

@@ -11,7 +11,6 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.seekbar.fingerprints.FullscreenSeekbarThumbnailsFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Restore old seekbar thumbnails",
@@ -35,7 +34,7 @@ object RestoreOldSeekbarThumbnailsPatch : BytecodePatch(
setOf(FullscreenSeekbarThumbnailsFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/RestoreOldSeekbarThumbnailsPatch;"
"Lapp/revanced/integrations/youtube/patches/RestoreOldSeekbarThumbnailsPatch;"
override fun execute(context: BytecodeContext) {
SeekbarPreferencesPatch.addPreferences(

View File

@@ -26,7 +26,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
internal object SeekbarColorBytecodePatch : BytecodePatch(
setOf(PlayerSeekbarColorFingerprint, ShortsSeekbarColorFingerprint, SetSeekbarClickedColorFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/SeekbarColorPatch;"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/theme/SeekbarColorPatch;"
override fun execute(context: BytecodeContext) {
fun MutableMethod.addColorChangeInstructions(resourceId: Long) {

View File

@@ -38,7 +38,7 @@ internal object SeekbarColorResourcePatch : ResourcePatch(){
val scaleNode = progressNode.getElementsByTagName("scale").item(0) as Element
val shapeNode = scaleNode.getElementsByTagName("shape").item(0) as Element
val replacementNode = editor.file.createElement(
"app.revanced.integrations.patches.theme.ProgressBarDrawable")
"app.revanced.integrations.youtube.patches.theme.ProgressBarDrawable")
scaleNode.replaceChild(replacementNode, shapeNode)
}
}

View File

@@ -69,13 +69,13 @@ object SponsorBlockBytecodePatch : BytecodePatch(
)
) {
private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/sponsorblock/SegmentPlaybackController;"
"Lapp/revanced/integrations/youtube/sponsorblock/SegmentPlaybackController;"
private const val INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController;"
"Lapp/revanced/integrations/youtube/sponsorblock/ui/CreateSegmentButtonController;"
private const val INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/sponsorblock/ui/VotingButtonController;"
"Lapp/revanced/integrations/youtube/sponsorblock/ui/VotingButtonController;"
private const val INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/sponsorblock/ui/SponsorBlockViewController;"
"Lapp/revanced/integrations/youtube/sponsorblock/ui/SponsorBlockViewController;"
override fun execute(context: BytecodeContext) {
LayoutConstructorFingerprint.result?.let {

Some files were not shown because too many files have changed in this diff Show More