Compare commits

...

22 Commits

Author SHA1 Message Date
semantic-release-bot
30c6749f61 chore(release): 4.0.0-dev.9 [skip ci]
# [4.0.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.8...v4.0.0-dev.9) (2024-01-11)

### Bug Fixes

* **YouTube - Enable slide to seek:** Change patch default to excluded and add description disclaimer ([#2610](https://github.com/ReVanced/revanced-patches/issues/2610)) ([08c3079](08c30791ae))
2024-01-11 14:56:11 +00:00
LisoUseInAIKyrios
08c30791ae fix(YouTube - Enable slide to seek): Change patch default to excluded and add description disclaimer (#2610) 2024-01-11 15:54:10 +01:00
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 5553 additions and 901 deletions

View File

@@ -1,3 +1,71 @@
# [4.0.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.8...v4.0.0-dev.9) (2024-01-11)
### Bug Fixes
* **YouTube - Enable slide to seek:** Change patch default to excluded and add description disclaimer ([#2610](https://github.com/ReVanced/revanced-patches/issues/2610)) ([2fdc4c2](https://github.com/ReVanced/revanced-patches/commit/2fdc4c23b5f39153ad71071359274c39129d691f))
# [4.0.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.7...v4.0.0-dev.8) (2024-01-10)
### Bug Fixes
* **YouTube:** Shorten setting titles to fit on screen ([#2579](https://github.com/ReVanced/revanced-patches/issues/2579)) ([b2a5dd3](https://github.com/ReVanced/revanced-patches/commit/b2a5dd3efc39ae8a42159858b9c00b5b2f8655a4))
# [4.0.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.6...v4.0.0-dev.7) (2024-01-10)
### Bug Fixes
* Use new integrations patch path ([51e2f3b](https://github.com/ReVanced/revanced-patches/commit/51e2f3b476b49460e2f3fc2b5f302a3a72d7963f))
# [4.0.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.5...v4.0.0-dev.6) (2024-01-09)
### Features
* **Tiktok - Playback speed:** Remember playback speed ([#2506](https://github.com/ReVanced/revanced-patches/issues/2506)) ([d2970e5](https://github.com/ReVanced/revanced-patches/commit/d2970e54fbbd7e4b1ae1d354ae2d5c4bbe9336b0))
# [4.0.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.4...v4.0.0-dev.5) (2024-01-09)
### Bug Fixes
* **YouTube - Change header:** Improve patch descriptions ([#2581](https://github.com/ReVanced/revanced-patches/issues/2581)) ([43a5677](https://github.com/ReVanced/revanced-patches/commit/43a5677397380f14a049ae95532fd5096b94c938))
# [4.0.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.3...v4.0.0-dev.4) (2024-01-09)
### Features
* **MyFitnessPal:** Add `Hide ads` patch ([#2594](https://github.com/ReVanced/revanced-patches/issues/2594)) ([fd4b3c7](https://github.com/ReVanced/revanced-patches/commit/fd4b3c79a83f8de6256611629263d3e29e66f2c2))
# [4.0.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.2...v4.0.0-dev.3) (2024-01-09)
### Features
* **Change package name:** Mention caveat of the patch in the description ([427b81a](https://github.com/ReVanced/revanced-patches/commit/427b81a79a5a1de79f14d2261059fb098b22227f))
# [4.0.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.1...v4.0.0-dev.2) (2024-01-02)
### Features
* **YouTube - Change header:** Change to ReVanced borderless logo header by default ([#2512](https://github.com/ReVanced/revanced-patches/issues/2512)) ([75f785d](https://github.com/ReVanced/revanced-patches/commit/75f785d1ef6026cbbdf7073c10aace1b28d93a30))
# [4.0.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.2...v4.0.0-dev.1) (2024-01-01)
### Code Refactoring
* Fix package and code structure ([#2541](https://github.com/ReVanced/revanced-patches/issues/2541)) ([a08457e](https://github.com/ReVanced/revanced-patches/commit/a08457e406f4b2e37458a4835c11d370a02d2ce6))
### BREAKING CHANGES
* Various public APIs have changed names and packages or were removed entirely
# [3.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.1...v3.3.0-dev.2) (2024-01-01)

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.9

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

@@ -17,7 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Enable slide to seek",
description = "Adds an option to enable slide to seek instead of playing at 2x speed when pressing and holding in the video player.",
description = "Adds an option to enable slide to seek instead of playing at 2x speed when pressing and holding in the video player. Including this patch may cause issues with tapping or double tapping the video player overlay.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -29,7 +29,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.45.43"
]
)
]
],
use = false
)
@Suppress("unused")
object EnableSlideToSeekPatch : BytecodePatch(
@@ -38,7 +39,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