chore: Merge branch dev
to main
(#2707)
This commit is contained in:
commit
fa27861ce0
3
.editorconfig
Normal file
3
.editorconfig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[*.{kt,kts}]
|
||||||
|
ktlint_code_style = intellij_idea
|
||||||
|
ktlint_standard_no-wildcard-imports = disabled
|
25
.github/workflows/build_pull_request.yml
vendored
Normal file
25
.github/workflows/build_pull_request.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
name: Build pull request
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Cache Gradle
|
||||||
|
uses: burrunan/gradle-cache-action@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: ./gradlew build --no-daemon
|
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
|
@ -6,10 +6,6 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- dev
|
- dev
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- dev
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
@ -41,6 +37,13 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
|
- name: Import GPG key
|
||||||
|
uses: crazy-max/ghaction-import-gpg@v6
|
||||||
|
with:
|
||||||
|
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
fingerprint: ${{ env.GPG_FINGERPRINT }}
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
{
|
{
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
"path": "build/libs/*.jar"
|
"path": "build/libs/revanced-patches*"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "patches.json"
|
"path": "patches.json"
|
||||||
|
|
99
CHANGELOG.md
99
CHANGELOG.md
|
@ -1,3 +1,102 @@
|
||||||
|
# [4.3.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.12...v4.3.0-dev.13) (2024-03-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube:** Reorganize settings menu ([#2737](https://github.com/ReVanced/revanced-patches/issues/2737)) ([36132df](https://github.com/ReVanced/revanced-patches/commit/36132df4be6a04c08b6f3dd79de1bcea93a80fb8))
|
||||||
|
|
||||||
|
# [4.3.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.11...v4.3.0-dev.12) (2024-03-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Spoof app version:** Add target versions ([#2787](https://github.com/ReVanced/revanced-patches/issues/2787)) ([83a7bd8](https://github.com/ReVanced/revanced-patches/commit/83a7bd8d69e62623fc4d2ba73d9fb49e92751d89))
|
||||||
|
|
||||||
|
# [4.3.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.10...v4.3.0-dev.11) (2024-03-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Spoof signature:** Fix tracking such as history or watch time ([bcd8b48](https://github.com/ReVanced/revanced-patches/commit/bcd8b48e70693dac1bfcc0bf4971d6b526065b59))
|
||||||
|
|
||||||
|
# [4.3.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.9...v4.3.0-dev.10) (2024-02-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Spoof app version:** Remove broken versions ([#2776](https://github.com/ReVanced/revanced-patches/issues/2776)) ([9466d97](https://github.com/ReVanced/revanced-patches/commit/9466d973c6d7a2891e3fa9f283107b64399152ea))
|
||||||
|
|
||||||
|
# [4.3.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.8...v4.3.0-dev.9) (2024-02-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Override certificate pinning:** Always overwrite with a generic network security configuration ([2a842a1](https://github.com/ReVanced/revanced-patches/commit/2a842a1e14e1993eb028ae0bd1a93e227bb929a6))
|
||||||
|
|
||||||
|
# [4.3.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.7...v4.3.0-dev.8) (2024-02-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Remove extra space from patch description ([#2780](https://github.com/ReVanced/revanced-patches/issues/2780)) ([96a3f35](https://github.com/ReVanced/revanced-patches/commit/96a3f359266ff8d16ae9ee3c6ce2f16ce67a3b93))
|
||||||
|
|
||||||
|
# [4.3.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.6...v4.3.0-dev.7) (2024-02-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **OpeningHours:** Add `Fix crash` patch ([#2697](https://github.com/ReVanced/revanced-patches/issues/2697)) ([0d011b8](https://github.com/ReVanced/revanced-patches/commit/0d011b876ecf05031a7daa54ab7e6d3506728a47))
|
||||||
|
|
||||||
|
# [4.3.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.5...v4.3.0-dev.6) (2024-02-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **VSCO - Unlock pro:** Constrain to last working version ([6dd4a7c](https://github.com/ReVanced/revanced-patches/commit/6dd4a7c29e48c3bc517bbdd7ed160624c36c2333))
|
||||||
|
|
||||||
|
# [4.3.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.4...v4.3.0-dev.5) (2024-02-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Remove unnecessary description from patch ([1a89dd9](https://github.com/ReVanced/revanced-patches/commit/1a89dd9f8cd0c614055a9da97338839b77a25ed1))
|
||||||
|
* **Twitter - Unlock downloads:** Unlock GIF downloads ([d0f91c8](https://github.com/ReVanced/revanced-patches/commit/d0f91c8550592723e1252e1af2971b508591dd59))
|
||||||
|
|
||||||
|
# [4.3.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.3...v4.3.0-dev.4) (2024-02-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Compile DEX without debugging information ([f5df957](https://github.com/ReVanced/revanced-patches/commit/f5df9578669f71a67411bc93a25a7e8da43610d0))
|
||||||
|
* Use deprecated members to ensure backwards compatibility ([083bd40](https://github.com/ReVanced/revanced-patches/commit/083bd4009231b9612394b4496ca1d329947d6577))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **X:** Add `Open links as query` patch ([#2730](https://github.com/ReVanced/revanced-patches/issues/2730)) ([ba75a51](https://github.com/ReVanced/revanced-patches/commit/ba75a51b71dbb9157db230b3e97a90361019fe30))
|
||||||
|
|
||||||
|
# [4.3.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.2...v4.3.0-dev.3) (2024-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Change header:** Improve patch option description ([3b8bc08](https://github.com/ReVanced/revanced-patches/commit/3b8bc08d4ed3a3a0f96d2f476e5059840b9f9d9b))
|
||||||
|
* **YouTube - Custom branding:** Improve patch option description ([e27f56c](https://github.com/ReVanced/revanced-patches/commit/e27f56c8a34d41167b290f47280276c1c6003876))
|
||||||
|
|
||||||
|
# [4.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.1...v4.3.0-dev.2) (2024-02-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Sync for Reddit:** Add `Fix /s/ links` patch ([f15ef3f](https://github.com/ReVanced/revanced-patches/commit/f15ef3f63460254236185f8e22c9395db4db9465))
|
||||||
|
|
||||||
|
# [4.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.2.0...v4.3.0-dev.1) (2024-02-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Change start page:** Add more start pages ([cc1d9b7](https://github.com/ReVanced/revanced-patches/commit/cc1d9b743633c619fb6acc428e884c1c9b53e10b))
|
||||||
|
|
||||||
# [4.2.0](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.2.0) (2024-02-08)
|
# [4.2.0](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.2.0) (2024-02-08)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,15 +64,15 @@ This document describes how to contribute to ReVanced Patches.
|
||||||
|
|
||||||
## 📖 Resources to help you get started
|
## 📖 Resources to help you get started
|
||||||
|
|
||||||
* The [documentation](https://github.com/ReVanced/revanced-patches/tree/docs/docs) provides the fundamentals of patches
|
* The [documentation](https://github.com/ReVanced/revanced-patcher/tree/docs/docs) contains the fundamentals
|
||||||
and everything necessary to create your own patch from scratch
|
of ReVanced Patcher and how to use ReVanced Patcher to create patches
|
||||||
* [Our backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on
|
* [Our backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on
|
||||||
* [Issues](https://github.com/ReVanced/revanced-patches/issues) are where we keep track of bugs and feature requests
|
* [Issues](https://github.com/ReVanced/revanced-patches/issues) are where we keep track of bugs and feature requests
|
||||||
|
|
||||||
## 🙏 Submitting a feature request
|
## 🙏 Submitting a feature request
|
||||||
|
|
||||||
Features can be requested by opening an issue using the
|
Features can be requested by opening an issue using the
|
||||||
[Feature request issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Feature+request&projects=&template=feature-request.yml&title=feat%3A+).
|
[Feature request issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Feature+request&projects=&template=feature_request.yml&title=feat%3A+).
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
> Requests can be accepted or rejected at the discretion of maintainers of ReVanced Patches.
|
> Requests can be accepted or rejected at the discretion of maintainers of ReVanced Patches.
|
||||||
|
@ -81,7 +81,7 @@ Features can be requested by opening an issue using the
|
||||||
## 🐞 Submitting a bug report
|
## 🐞 Submitting a bug report
|
||||||
|
|
||||||
If you encounter a bug while using ReVanced Patches, open an issue using the
|
If you encounter a bug while using ReVanced Patches, open an issue using the
|
||||||
[Bug report issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Bug+report&projects=&template=bug-report.yml&title=bug%3A+).
|
[Bug report issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Bug+report&projects=&template=bug_report.yml&title=bug%3A+).
|
||||||
|
|
||||||
## 🧑⚖️ Guidelines for requesting or contributing patches
|
## 🧑⚖️ Guidelines for requesting or contributing patches
|
||||||
|
|
||||||
|
|
16
README.md
16
README.md
|
@ -67,7 +67,7 @@ This repository contains a collection of ReVanced Patches.
|
||||||
|
|
||||||
## ❓ About
|
## ❓ About
|
||||||
|
|
||||||
Patches are small modifications to Android apps that allow you to change the behaviour of or add new features,
|
Patches are small modifications to Android apps that allow you to change the behavior of or add new features,
|
||||||
block ads, customize the appearance, and much more.
|
block ads, customize the appearance, and much more.
|
||||||
|
|
||||||
## 💪 Features
|
## 💪 Features
|
||||||
|
@ -81,7 +81,7 @@ Some of the features the patches provide are:
|
||||||
export activities, etc.
|
export activities, etc.
|
||||||
* ✨ **And much more!**
|
* ✨ **And much more!**
|
||||||
|
|
||||||
For a full list of all available patches, visit [revanced.app/patches](https://revanced.app/patches).
|
For a complete list of all available patches, visit [revanced.app/patches](https://revanced.app/patches).
|
||||||
|
|
||||||
## 🚀 How to get started
|
## 🚀 How to get started
|
||||||
|
|
||||||
|
@ -93,17 +93,13 @@ You can use [ReVanced CLI](https://github.com/ReVanced/revanced-cli) or [ReVance
|
||||||
|
|
||||||
Thank you for considering contributing to ReVanced Patches. You can find the contribution guidelines [here](CONTRIBUTING.md).
|
Thank you for considering contributing to ReVanced Patches. You can find the contribution guidelines [here](CONTRIBUTING.md).
|
||||||
|
|
||||||
### 📃 Documentation
|
|
||||||
|
|
||||||
The documentation provides the fundamentals of patches and everything necessary to create your own patch from scratch.
|
|
||||||
You can find it [here](https://github.com/ReVanced/revanced-patches/tree/docs/docs).
|
|
||||||
|
|
||||||
### 🛠️ Building
|
### 🛠️ Building
|
||||||
|
|
||||||
In order to build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
|
To build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
|
||||||
|
|
||||||
## 📜 Licence
|
## 📜 Licence
|
||||||
|
|
||||||
ReVanced Patches is licensed under the GPLv3 licence. Please see the [licence file](LICENSE) for more information.
|
ReVanced Patches is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
|
||||||
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Patches as long as you track changes/dates in source files.
|
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Patches as long as you track changes/dates in source files.
|
||||||
Any modifications to ReVanced Patches must also be made available under the GPL along with build & install instructions.
|
Any modifications to ReVanced Patches must also be made available under the GPL,
|
||||||
|
along with build & install instructions.
|
|
@ -1,3 +1,7 @@
|
||||||
|
public final class app/revanced/generator/MainKt {
|
||||||
|
public static synthetic fun main ([Ljava/lang/String;)V
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch : app/revanced/patcher/patch/ResourcePatch {
|
public final class app/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch;
|
public static final field INSTANCE Lapp/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch;
|
||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
|
@ -406,6 +410,12 @@ public final class app/revanced/patches/nyx/misc/pro/UnlockProPatch : app/revanc
|
||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch;
|
||||||
|
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/photomath/detection/deviceid/SpoofDeviceIdPatch : app/revanced/patcher/patch/BytecodePatch {
|
public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch;
|
public static final field INSTANCE Lapp/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch;
|
||||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
@ -550,6 +560,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/detec
|
||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch;
|
||||||
|
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/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch : app/revanced/patcher/patch/BytecodePatch {
|
public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch;
|
public static final field INSTANCE Lapp/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch;
|
||||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
@ -707,10 +723,8 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
|
||||||
}
|
}
|
||||||
|
|
||||||
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;)V
|
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;)V
|
||||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;)V
|
|
||||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
|
||||||
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||||
public final fun getCategories ()Ljava/util/Set;
|
public final fun getCategories ()Ljava/util/Set;
|
||||||
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||||
|
@ -782,12 +796,22 @@ public class app/revanced/patches/shared/misc/settings/preference/PreferenceCate
|
||||||
}
|
}
|
||||||
|
|
||||||
public class app/revanced/patches/shared/misc/settings/preference/PreferenceScreen : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
public class app/revanced/patches/shared/misc/settings/preference/PreferenceScreen : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
public final fun getPreferences ()Ljava/util/Set;
|
public final fun getPreferences ()Ljava/util/Set;
|
||||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting : java/lang/Enum {
|
||||||
|
public static final field BY_KEY Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
|
||||||
|
public static final field BY_TITLE Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
|
||||||
|
public static final field UNSORTED Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
|
||||||
|
public static fun getEntries ()Lkotlin/enums/EnumEntries;
|
||||||
|
public final fun getKeySuffix ()Ljava/lang/String;
|
||||||
|
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
|
||||||
|
public static fun values ()[Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/shared/misc/settings/preference/SummaryType : java/lang/Enum {
|
public final class app/revanced/patches/shared/misc/settings/preference/SummaryType : java/lang/Enum {
|
||||||
public static final field DEFAULT Lapp/revanced/patches/shared/misc/settings/preference/SummaryType;
|
public static final field DEFAULT Lapp/revanced/patches/shared/misc/settings/preference/SummaryType;
|
||||||
public static final field OFF Lapp/revanced/patches/shared/misc/settings/preference/SummaryType;
|
public static final field OFF Lapp/revanced/patches/shared/misc/settings/preference/SummaryType;
|
||||||
|
@ -1104,6 +1128,12 @@ public final class app/revanced/patches/twitter/misc/hook/patch/recommendation/H
|
||||||
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch;
|
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch;
|
||||||
|
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/vsco/misc/pro/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
|
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/vsco/misc/pro/UnlockProPatch;
|
public static final field INSTANCE Lapp/revanced/patches/vsco/misc/pro/UnlockProPatch;
|
||||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
@ -1446,7 +1476,6 @@ public final class app/revanced/patches/youtube/layout/tabletminiplayer/TabletMi
|
||||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch;
|
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch;
|
||||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
public final fun unwrap (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lkotlin/Triple;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
|
public final class app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
@ -1595,9 +1624,14 @@ public final class app/revanced/patches/youtube/misc/settings/SettingsPatch$Pref
|
||||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/settings/SettingsPatch$PreferenceScreen;
|
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/settings/SettingsPatch$PreferenceScreen;
|
||||||
public fun commit (Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen;)V
|
public fun commit (Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen;)V
|
||||||
public final fun getADS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
public final fun getADS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
public final fun getINTERACTIONS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
public final fun getALTERNATIVE_THUMBNAILS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
public final fun getLAYOUT ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
public final fun getFEED ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
|
public final fun getGENERAL_LAYOUT ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
public final fun getMISC ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
public final fun getMISC ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
|
public final fun getPLAYER ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
|
public final fun getSEEKBAR ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
|
public final fun getSHORTS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
|
public final fun getSWIPE_CONTROLS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
public final fun getVIDEO ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
public final fun getVIDEO ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import org.gradle.kotlin.dsl.support.listFilesOrdered
|
import org.gradle.kotlin.dsl.support.listFilesOrdered
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.9.22"
|
alias(libs.plugins.kotlin)
|
||||||
alias(libs.plugins.binary.compatibility.validator)
|
alias(libs.plugins.binary.compatibility.validator)
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "app.revanced"
|
group = "app.revanced"
|
||||||
|
@ -12,7 +13,14 @@ repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
google()
|
google()
|
||||||
maven { url = uri("https://jitpack.io") }
|
maven {
|
||||||
|
// A repository must be speficied for some reason. "registry" is a dummy.
|
||||||
|
url = uri("https://maven.pkg.github.com/revanced/registry")
|
||||||
|
credentials {
|
||||||
|
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
|
||||||
|
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -22,16 +30,14 @@ dependencies {
|
||||||
implementation(libs.guava)
|
implementation(libs.guava)
|
||||||
// Used in JsonGenerator.
|
// Used in JsonGenerator.
|
||||||
implementation(libs.gson)
|
implementation(libs.gson)
|
||||||
|
|
||||||
// A dependency to the Android library unfortunately fails the build, which is why this is required.
|
|
||||||
compileOnly(project("dummy"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvmToolchain(11)
|
jvmToolchain(11)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Jar::class) {
|
tasks {
|
||||||
|
withType(Jar::class) {
|
||||||
exclude("app/revanced/meta")
|
exclude("app/revanced/meta")
|
||||||
|
|
||||||
manifest {
|
manifest {
|
||||||
|
@ -47,9 +53,9 @@ tasks.withType(Jar::class) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
register("buildDexJar") {
|
||||||
register<DefaultTask>("generateBundle") {
|
description = "Build and add a DEX to the JAR file"
|
||||||
description = "Generate DEX files and add them in the JAR file"
|
group = "build"
|
||||||
|
|
||||||
dependsOn(build)
|
dependsOn(build)
|
||||||
|
|
||||||
|
@ -57,39 +63,50 @@ tasks {
|
||||||
val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools")
|
val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools")
|
||||||
.listFilesOrdered().last().resolve("d8").absolutePath
|
.listFilesOrdered().last().resolve("d8").absolutePath
|
||||||
|
|
||||||
val artifacts = configurations.archives.get().allArtifacts.files.files.first().absolutePath
|
val patchesJar = configurations.archives.get().allArtifacts.files.files.first().absolutePath
|
||||||
val workingDirectory = layout.buildDirectory.dir("libs").get().asFile
|
val workingDirectory = layout.buildDirectory.dir("libs").get().asFile
|
||||||
|
|
||||||
exec {
|
exec {
|
||||||
workingDir = workingDirectory
|
workingDir = workingDirectory
|
||||||
commandLine = listOf(d8, artifacts)
|
commandLine = listOf(d8, "--release", patchesJar)
|
||||||
}
|
}
|
||||||
|
|
||||||
exec {
|
exec {
|
||||||
workingDir = workingDirectory
|
workingDir = workingDirectory
|
||||||
commandLine = listOf("zip", "-u", artifacts, "classes.dex")
|
commandLine = listOf("zip", "-u", patchesJar, "classes.dex")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
register<JavaExec>("generateMeta") {
|
register<JavaExec>("generatePatchesFiles") {
|
||||||
description = "Generate metadata for this bundle"
|
description = "Generate patches files"
|
||||||
|
|
||||||
dependsOn(build)
|
dependsOn(build)
|
||||||
|
|
||||||
classpath = sourceSets["main"].runtimeClasspath
|
classpath = sourceSets["main"].runtimeClasspath
|
||||||
mainClass.set("app.revanced.meta.IPatchesFileGenerator")
|
mainClass.set("app.revanced.generator.MainKt")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required to run tasks because Gradle semantic-release plugin runs the publish task.
|
// Needed by gradle-semantic-release-plugin.
|
||||||
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
||||||
named("publish") {
|
publish {
|
||||||
dependsOn("generateBundle")
|
dependsOn("buildDexJar")
|
||||||
dependsOn("generateMeta")
|
dependsOn("generatePatchesFiles")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "GitHubPackages"
|
||||||
|
url = uri("https://maven.pkg.github.com/revanced/revanced-patches")
|
||||||
|
credentials {
|
||||||
|
username = System.getenv("GITHUB_ACTOR")
|
||||||
|
password = System.getenv("GITHUB_TOKEN")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
publications {
|
publications {
|
||||||
create<MavenPublication>("revanced-patches-publication") {
|
create<MavenPublication>("revanced-patches-publication") {
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
|
@ -121,3 +138,9 @@ publishing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
useGpgCmd()
|
||||||
|
|
||||||
|
sign(publishing.publications["revanced-patches-publication"])
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
plugins {
|
|
||||||
id("java")
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion.set(JavaLanguageVersion.of(11))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package android.os;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public final class Environment {
|
|
||||||
public static File getExternalStorageDirectory() {
|
|
||||||
throw new UnsupportedOperationException("Stub");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 4.2.0
|
version = 4.3.0-dev.13
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
[versions]
|
[versions]
|
||||||
revanced-patcher = "19.2.0"
|
revanced-patcher = "19.3.1"
|
||||||
smali = "3.0.3"
|
smali = "3.0.4"
|
||||||
guava = "33.0.0-jre"
|
guava = "33.0.0-jre"
|
||||||
gson = "2.10.1"
|
gson = "2.10.1"
|
||||||
binary-compatibility-validator = "0.13.2"
|
binary-compatibility-validator = "0.14.0"
|
||||||
|
kotlin = "1.9.22"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
||||||
|
@ -13,3 +14,4 @@ gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
||||||
|
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
|
|
8
gradle/wrapper/gradle-wrapper.properties
vendored
8
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,8 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
|
||||||
networkTimeout=10000
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dist
|
280
package-lock.json
generated
280
package-lock.json
generated
|
@ -9,7 +9,7 @@
|
||||||
"@semantic-release/changelog": "^6.0.3",
|
"@semantic-release/changelog": "^6.0.3",
|
||||||
"@semantic-release/git": "^10.0.1",
|
"@semantic-release/git": "^10.0.1",
|
||||||
"gradle-semantic-release-plugin": "^1.9.1",
|
"gradle-semantic-release-plugin": "^1.9.1",
|
||||||
"semantic-release": "^23.0.0"
|
"semantic-release": "^23.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
|
@ -326,9 +326,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/request": {
|
"node_modules/@octokit/request": {
|
||||||
"version": "8.1.6",
|
"version": "8.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.2.0.tgz",
|
||||||
"integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==",
|
"integrity": "sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/endpoint": "^9.0.0",
|
"@octokit/endpoint": "^9.0.0",
|
||||||
|
@ -564,6 +564,26 @@
|
||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@saithodev/semantic-release-backmerge/node_modules/marked-terminal": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-escapes": "^6.2.0",
|
||||||
|
"cardinal": "^2.1.1",
|
||||||
|
"chalk": "^5.3.0",
|
||||||
|
"cli-table3": "^0.6.3",
|
||||||
|
"node-emoji": "^2.1.3",
|
||||||
|
"supports-hyperlinks": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"marked": ">=1 <12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@saithodev/semantic-release-backmerge/node_modules/mimic-fn": {
|
"node_modules/@saithodev/semantic-release-backmerge/node_modules/mimic-fn": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||||
|
@ -1195,9 +1215,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sindresorhus/merge-streams": {
|
"node_modules/@sindresorhus/merge-streams": {
|
||||||
"version": "1.0.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.2.0.tgz",
|
||||||
"integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==",
|
"integrity": "sha512-UTce8mUwUW0RikMb/eseJ7ys0BRkZVFB86orHzrfW12ZmFtym5zua8joZ4L7okH2dDFHkcFjqnZ5GocWBXOFtA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
|
@ -1282,6 +1302,12 @@
|
||||||
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
|
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/any-promise": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
@ -1376,6 +1402,81 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cli-highlight": {
|
||||||
|
"version": "2.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
|
||||||
|
"integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^4.0.0",
|
||||||
|
"highlight.js": "^10.7.1",
|
||||||
|
"mz": "^2.4.0",
|
||||||
|
"parse5": "^5.1.1",
|
||||||
|
"parse5-htmlparser2-tree-adapter": "^6.0.0",
|
||||||
|
"yargs": "^16.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"highlight": "bin/highlight"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0",
|
||||||
|
"npm": ">=5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-highlight/node_modules/chalk": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-highlight/node_modules/cliui": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"strip-ansi": "^6.0.0",
|
||||||
|
"wrap-ansi": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-highlight/node_modules/yargs": {
|
||||||
|
"version": "16.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||||
|
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"cliui": "^7.0.2",
|
||||||
|
"escalade": "^3.1.1",
|
||||||
|
"get-caller-file": "^2.0.5",
|
||||||
|
"require-directory": "^2.1.1",
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"y18n": "^5.0.5",
|
||||||
|
"yargs-parser": "^20.2.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-highlight/node_modules/yargs-parser": {
|
||||||
|
"version": "20.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||||
|
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cli-table3": {
|
"node_modules/cli-table3": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
|
||||||
|
@ -1818,9 +1919,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/escalade": {
|
"node_modules/escalade": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
@ -1888,9 +1989,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.16.0",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
"integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
|
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
|
@ -2052,12 +2153,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globby": {
|
"node_modules/globby": {
|
||||||
"version": "14.0.0",
|
"version": "14.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz",
|
||||||
"integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==",
|
"integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sindresorhus/merge-streams": "^1.0.0",
|
"@sindresorhus/merge-streams": "^2.1.0",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"ignore": "^5.2.4",
|
"ignore": "^5.2.4",
|
||||||
"path-type": "^5.0.0",
|
"path-type": "^5.0.0",
|
||||||
|
@ -2142,9 +2243,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
|
||||||
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
|
"integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"function-bind": "^1.1.2"
|
"function-bind": "^1.1.2"
|
||||||
|
@ -2153,6 +2254,15 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/highlight.js": {
|
||||||
|
"version": "10.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
|
||||||
|
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hook-std": {
|
"node_modules/hook-std": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz",
|
||||||
|
@ -2178,9 +2288,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/http-proxy-agent": {
|
"node_modules/http-proxy-agent": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.1.tgz",
|
||||||
"integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==",
|
"integrity": "sha512-My1KCEPs6A0hb4qCVzYp8iEvA8j8YqcvXLZZH8C9OFuTYpYjHE7N2dtG3mRl1HMD4+VGXpF3XcDVcxGBT7yDZQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"agent-base": "^7.1.0",
|
"agent-base": "^7.1.0",
|
||||||
|
@ -2191,9 +2301,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/https-proxy-agent": {
|
"node_modules/https-proxy-agent": {
|
||||||
"version": "7.0.2",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.3.tgz",
|
||||||
"integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
|
"integrity": "sha512-kCnwztfX0KZJSLOBrcL0emLeFako55NWMovvyPP2AjsghNk9RB1yjSI+jVumPHYZsNXegNoqupSW9IY3afSH8w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"agent-base": "^7.0.2",
|
"agent-base": "^7.0.2",
|
||||||
|
@ -2213,9 +2323,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||||
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
|
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
|
@ -2629,9 +2739,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "11.1.1",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz",
|
||||||
"integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==",
|
"integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"marked": "bin/marked.js"
|
"marked": "bin/marked.js"
|
||||||
|
@ -2641,14 +2751,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-terminal": {
|
"node_modules/marked-terminal": {
|
||||||
"version": "6.2.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.0.0.tgz",
|
||||||
"integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==",
|
"integrity": "sha512-sNEx8nn9Ktcm6pL0TnRz8tnXq/mSS0Q1FRSwJOAqw4lAB4l49UeDf85Gm1n9RPFm5qurCPjwi1StAQT2XExhZw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-escapes": "^6.2.0",
|
"ansi-escapes": "^6.2.0",
|
||||||
"cardinal": "^2.1.1",
|
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
|
"cli-highlight": "^2.1.11",
|
||||||
"cli-table3": "^0.6.3",
|
"cli-table3": "^0.6.3",
|
||||||
"node-emoji": "^2.1.3",
|
"node-emoji": "^2.1.3",
|
||||||
"supports-hyperlinks": "^3.0.0"
|
"supports-hyperlinks": "^3.0.0"
|
||||||
|
@ -2657,7 +2767,7 @@
|
||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"marked": ">=1 <12"
|
"marked": ">=1 <13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/meow": {
|
"node_modules/meow": {
|
||||||
|
@ -2739,6 +2849,17 @@
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/mz": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"any-promise": "^1.0.0",
|
||||||
|
"object-assign": "^4.0.1",
|
||||||
|
"thenify-all": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/neo-async": {
|
"node_modules/neo-async": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||||
|
@ -5551,6 +5672,15 @@
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
@ -5695,6 +5825,27 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parse5": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"parse5": "^6.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/parsimmon": {
|
"node_modules/parsimmon": {
|
||||||
"version": "1.18.1",
|
"version": "1.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.18.1.tgz",
|
||||||
|
@ -5860,9 +6011,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/read-pkg-up/node_modules/type-fest": {
|
"node_modules/read-pkg-up/node_modules/type-fest": {
|
||||||
"version": "4.10.1",
|
"version": "4.10.2",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
|
||||||
"integrity": "sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==",
|
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
@ -5889,9 +6040,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/read-pkg/node_modules/type-fest": {
|
"node_modules/read-pkg/node_modules/type-fest": {
|
||||||
"version": "4.10.1",
|
"version": "4.10.2",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
|
||||||
"integrity": "sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==",
|
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
@ -5994,9 +6145,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/semantic-release": {
|
"node_modules/semantic-release": {
|
||||||
"version": "23.0.0",
|
"version": "23.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.2.tgz",
|
||||||
"integrity": "sha512-Jz7jEWO2igTtske112gC4PPE2whCMVrsgxUPG3/SZI7VE357suIUZFlJd1Yu0g2I6RPc2HxNEfUg7KhmDTjwqg==",
|
"integrity": "sha512-OnVYJ6Xgzwe1x8MKswba7RU9+5djS1MWRTrTn5qsq3xZYpslroZkV9Pt0dA2YcIuieeuSZWJhn+yUWoBUHO5Fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@semantic-release/commit-analyzer": "^11.0.0",
|
"@semantic-release/commit-analyzer": "^11.0.0",
|
||||||
|
@ -6017,8 +6168,8 @@
|
||||||
"hosted-git-info": "^7.0.0",
|
"hosted-git-info": "^7.0.0",
|
||||||
"import-from-esm": "^1.3.1",
|
"import-from-esm": "^1.3.1",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^11.0.0",
|
"marked": "^12.0.0",
|
||||||
"marked-terminal": "^6.0.0",
|
"marked-terminal": "^7.0.0",
|
||||||
"micromatch": "^4.0.2",
|
"micromatch": "^4.0.2",
|
||||||
"p-each-series": "^3.0.0",
|
"p-each-series": "^3.0.0",
|
||||||
"p-reduce": "^3.0.0",
|
"p-reduce": "^3.0.0",
|
||||||
|
@ -6247,9 +6398,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.5.4",
|
"version": "7.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
|
@ -6481,9 +6632,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/spdx-license-ids": {
|
"node_modules/spdx-license-ids": {
|
||||||
"version": "3.0.16",
|
"version": "3.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
|
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
|
||||||
"integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
|
"integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/split2": {
|
"node_modules/split2": {
|
||||||
|
@ -6655,6 +6806,27 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/thenify": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"any-promise": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/thenify-all": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"thenify": ">= 3.1.0 < 4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/through": {
|
"node_modules/through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
"@semantic-release/changelog": "^6.0.3",
|
"@semantic-release/changelog": "^6.0.3",
|
||||||
"@semantic-release/git": "^10.0.1",
|
"@semantic-release/git": "^10.0.1",
|
||||||
"gradle-semantic-release-plugin": "^1.9.1",
|
"gradle-semantic-release-plugin": "^1.9.1",
|
||||||
"semantic-release": "^23.0.0"
|
"semantic-release": "^23.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,3 @@
|
||||||
include("dummy")
|
|
||||||
|
|
||||||
rootProject.name = "revanced-patches"
|
rootProject.name = "revanced-patches"
|
||||||
|
|
||||||
buildCache {
|
buildCache {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package app.revanced.meta
|
package app.revanced.generator
|
||||||
|
|
||||||
import app.revanced.patcher.PatchSet
|
import app.revanced.patcher.PatchSet
|
||||||
import app.revanced.patcher.patch.Patch
|
import app.revanced.patcher.patch.Patch
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
internal class JsonPatchesFileGenerator : PatchesFileGenerator {
|
||||||
override fun generate(patches: PatchSet) = patches.map {
|
override fun generate(patches: PatchSet) = patches.map {
|
||||||
JsonPatch(
|
JsonPatch(
|
||||||
it.name!!,
|
it.name!!,
|
||||||
|
@ -20,9 +20,9 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
||||||
option.values,
|
option.values,
|
||||||
option.title,
|
option.title,
|
||||||
option.description,
|
option.description,
|
||||||
option.required
|
option.required,
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}.let {
|
}.let {
|
||||||
File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it))
|
File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it))
|
||||||
|
@ -35,7 +35,7 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
||||||
val compatiblePackages: Set<Patch.CompatiblePackage>? = null,
|
val compatiblePackages: Set<Patch.CompatiblePackage>? = null,
|
||||||
val use: Boolean = true,
|
val use: Boolean = true,
|
||||||
val requiresIntegrations: Boolean = false,
|
val requiresIntegrations: Boolean = false,
|
||||||
val options: List<Option>
|
val options: List<Option>,
|
||||||
) {
|
) {
|
||||||
class Option(
|
class Option(
|
||||||
val key: String,
|
val key: String,
|
12
src/main/kotlin/app/revanced/generator/Main.kt
Normal file
12
src/main/kotlin/app/revanced/generator/Main.kt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package app.revanced.generator
|
||||||
|
|
||||||
|
import app.revanced.patcher.PatchBundleLoader
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal fun main() = PatchBundleLoader.Jar(
|
||||||
|
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first(),
|
||||||
|
).also { loader ->
|
||||||
|
if (loader.isEmpty()) throw IllegalStateException("No patches found")
|
||||||
|
}.let { bundle ->
|
||||||
|
arrayOf(JsonPatchesFileGenerator()).forEach { generator -> generator.generate(bundle) }
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package app.revanced.generator
|
||||||
|
|
||||||
|
import app.revanced.patcher.PatchSet
|
||||||
|
|
||||||
|
internal interface PatchesFileGenerator {
|
||||||
|
fun generate(patches: PatchSet)
|
||||||
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
package app.revanced.meta
|
|
||||||
|
|
||||||
import app.revanced.patcher.PatchBundleLoader
|
|
||||||
import app.revanced.patcher.PatchSet
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
internal interface IPatchesFileGenerator {
|
|
||||||
fun generate(patches: PatchSet)
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) = PatchBundleLoader.Jar(
|
|
||||||
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first()
|
|
||||||
).also { loader ->
|
|
||||||
if (loader.isEmpty()) throw IllegalStateException("No patches found")
|
|
||||||
}.let { bundle ->
|
|
||||||
arrayOf(JsonPatchesFileGenerator()).forEach { generator -> generator.generate(bundle) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,14 +7,16 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Export all activities",
|
name = "Export all activities",
|
||||||
description = "Makes all app activities exportable.",
|
description = "Makes all app activities exportable.",
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object ExportAllActivitiesPatch : ResourcePatch() {
|
object ExportAllActivitiesPatch : ResourcePatch() {
|
||||||
private const val EXPORTED_FLAG = "android:exported"
|
private const val EXPORTED_FLAG = "android:exported"
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
val document = editor.file
|
val document = editor.file
|
||||||
|
|
||||||
val activities = document.getElementsByTagName("activity")
|
val activities = document.getElementsByTagName("activity")
|
||||||
|
|
||||||
for (i in 0..activities.length) {
|
for (i in 0..activities.length) {
|
||||||
|
@ -22,12 +24,14 @@ object ExportAllActivitiesPatch : ResourcePatch() {
|
||||||
val exportedAttribute = attributes.getNamedItem(EXPORTED_FLAG)
|
val exportedAttribute = attributes.getNamedItem(EXPORTED_FLAG)
|
||||||
|
|
||||||
if (exportedAttribute != null) {
|
if (exportedAttribute != null) {
|
||||||
if (exportedAttribute.nodeValue != "true")
|
if (exportedAttribute.nodeValue != "true") {
|
||||||
exportedAttribute.nodeValue = "true"
|
exportedAttribute.nodeValue = "true"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Reason why the attribute is added in the case it does not exist:
|
// Reason why the attribute is added in the case it does not exist:
|
||||||
// https://github.com/revanced/revanced-patches/pull/1751/files#r1141481604
|
// https://github.com/revanced/revanced-patches/pull/1751/files#r1141481604
|
||||||
else document.createAttribute(EXPORTED_FLAG)
|
else {
|
||||||
|
document.createAttribute(EXPORTED_FLAG)
|
||||||
.apply { value = "true" }
|
.apply { value = "true" }
|
||||||
.let(attributes::setNamedItem)
|
.let(attributes::setNamedItem)
|
||||||
}
|
}
|
||||||
|
@ -35,3 +39,4 @@ object ExportAllActivitiesPatch : ResourcePatch() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Predictive back gesture",
|
name = "Predictive back gesture",
|
||||||
description = "Enables the predictive back gesture introduced on Android 13.",
|
description = "Enables the predictive back gesture introduced on Android 13.",
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object PredictiveBackGesturePatch : ResourcePatch() {
|
object PredictiveBackGesturePatch : ResourcePatch() {
|
||||||
|
|
|
@ -8,14 +8,16 @@ import org.w3c.dom.Element
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Enable Android debugging",
|
name = "Enable Android debugging",
|
||||||
description = "Enables Android debugging capabilities. This can slow down the app.",
|
description = "Enables Android debugging capabilities. This can slow down the app.",
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object EnableAndroidDebuggingPatch : ResourcePatch() {
|
object EnableAndroidDebuggingPatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
val applicationNode = dom
|
val document = editor.file
|
||||||
.file
|
|
||||||
|
val applicationNode =
|
||||||
|
document
|
||||||
.getElementsByTagName("application")
|
.getElementsByTagName("application")
|
||||||
.item(0) as Element
|
.item(0) as Element
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import app.revanced.patcher.data.ResourceContext
|
||||||
import app.revanced.patcher.patch.ResourcePatch
|
import app.revanced.patcher.patch.ResourcePatch
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch
|
import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch
|
||||||
|
import app.revanced.util.Utils.trimIndentMultiline
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
@ -11,16 +12,17 @@ import java.io.File
|
||||||
name = "Override certificate pinning",
|
name = "Override certificate pinning",
|
||||||
description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
|
description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
|
||||||
dependencies = [EnableAndroidDebuggingPatch::class],
|
dependencies = [EnableAndroidDebuggingPatch::class],
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object OverrideCertificatePinningPatch : ResourcePatch() {
|
object OverrideCertificatePinningPatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
val resXmlDirectory = context["res/xml"]
|
val resXmlDirectory = context.get("res/xml")
|
||||||
|
|
||||||
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
|
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
|
||||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
val document = editor.file
|
val document = editor.file
|
||||||
|
|
||||||
val applicationNode = document.getElementsByTagName("application").item(0) as Element
|
val applicationNode = document.getElementsByTagName("application").item(0) as Element
|
||||||
|
|
||||||
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
|
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
|
||||||
|
@ -31,8 +33,6 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
|
||||||
|
|
||||||
// In case the file does not exist create the "network_security_config.xml" file.
|
// In case the file does not exist create the "network_security_config.xml" file.
|
||||||
File(resXmlDirectory, "network_security_config.xml").apply {
|
File(resXmlDirectory, "network_security_config.xml").apply {
|
||||||
if (!exists()) {
|
|
||||||
createNewFile()
|
|
||||||
writeText(
|
writeText(
|
||||||
"""
|
"""
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
@ -54,22 +54,8 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
|
||||||
</trust-anchors>
|
</trust-anchors>
|
||||||
</debug-overrides>
|
</debug-overrides>
|
||||||
</network-security-config>
|
</network-security-config>
|
||||||
"""
|
""".trimIndentMultiline(),
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// If the file already exists.
|
|
||||||
readText().let { text ->
|
|
||||||
if (!text.contains("<certificates src=\"user\" />")) {
|
|
||||||
writeText(
|
|
||||||
text.replace(
|
|
||||||
"<trust-anchors>",
|
|
||||||
"<trust-anchors>\n<certificates src=\"user\" overridePins=\"true\" />\n<certificates src=\"system\" />"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,18 @@ import java.io.Closeable
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Change package name",
|
name = "Change package name",
|
||||||
description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.",
|
description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.",
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object ChangePackageNamePatch : ResourcePatch(), Closeable {
|
object ChangePackageNamePatch : ResourcePatch(), Closeable {
|
||||||
private val packageNameOption = stringPatchOption(
|
private val packageNameOption =
|
||||||
|
stringPatchOption(
|
||||||
key = "packageName",
|
key = "packageName",
|
||||||
default = "Default",
|
default = "Default",
|
||||||
values = mapOf("Default" to "Default"),
|
values = mapOf("Default" to "Default"),
|
||||||
title = "Package name",
|
title = "Package name",
|
||||||
description = "The name of the package to rename the app to.",
|
description = "The name of the package to rename the app to.",
|
||||||
required = true
|
required = true,
|
||||||
) {
|
) {
|
||||||
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
||||||
}
|
}
|
||||||
|
@ -43,20 +44,27 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
|
||||||
fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
|
fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
|
||||||
val packageName = packageNameOption.value!!
|
val packageName = packageNameOption.value!!
|
||||||
|
|
||||||
return if (packageName == packageNameOption.default)
|
return if (packageName == packageNameOption.default) {
|
||||||
fallbackPackageName.also { packageNameOption.value = it }
|
fallbackPackageName.also { packageNameOption.value = it }
|
||||||
else
|
} else {
|
||||||
packageName
|
packageName
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() =
|
||||||
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
|
val document = editor.file
|
||||||
|
|
||||||
override fun close() = context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
|
||||||
val replacementPackageName = packageNameOption.value
|
val replacementPackageName = packageNameOption.value
|
||||||
|
|
||||||
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
|
val manifest = document.getElementsByTagName("manifest").item(0) as Element
|
||||||
manifest.setAttribute(
|
manifest.setAttribute(
|
||||||
"package",
|
"package",
|
||||||
if (replacementPackageName != packageNameOption.default) replacementPackageName
|
if (replacementPackageName != packageNameOption.default) {
|
||||||
else "${manifest.getAttribute("package")}.revanced"
|
replacementPackageName
|
||||||
|
} else {
|
||||||
|
"${manifest.getAttribute("package")}.revanced"
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.*
|
||||||
* An identifier of an app. For example, `youtube`.
|
* An identifier of an app. For example, `youtube`.
|
||||||
*/
|
*/
|
||||||
private typealias AppId = String
|
private typealias AppId = String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An identifier of a patch. For example, `ad.general.HideAdsPatch`.
|
* An identifier of a patch. For example, `ad.general.HideAdsPatch`.
|
||||||
*/
|
*/
|
||||||
|
@ -28,10 +29,12 @@ private typealias PatchId = String
|
||||||
* A set of resources of a patch.
|
* A set of resources of a patch.
|
||||||
*/
|
*/
|
||||||
private typealias PatchResources = MutableSet<BaseResource>
|
private typealias PatchResources = MutableSet<BaseResource>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of resources belonging to a patch.
|
* A map of resources belonging to a patch.
|
||||||
*/
|
*/
|
||||||
private typealias AppResources = MutableMap<PatchId, PatchResources>
|
private typealias AppResources = MutableMap<PatchId, PatchResources>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of resources belonging to an app.
|
* A map of resources belonging to an app.
|
||||||
*/
|
*/
|
||||||
|
@ -67,7 +70,8 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
this.context = context
|
this.context = context
|
||||||
|
|
||||||
resources = buildMap {
|
resources =
|
||||||
|
buildMap {
|
||||||
/**
|
/**
|
||||||
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
|
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
|
||||||
*
|
*
|
||||||
|
@ -82,14 +86,16 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
) {
|
) {
|
||||||
inputStreamFromBundledResource(
|
inputStreamFromBundledResource(
|
||||||
"addresources",
|
"addresources",
|
||||||
"$value/$resourceKind.xml"
|
"$value/$resourceKind.xml",
|
||||||
)?.let { stream ->
|
)?.let { stream ->
|
||||||
// Add the resources associated with the given value to the map,
|
// Add the resources associated with the given value to the map,
|
||||||
// instead of overwriting it.
|
// instead of overwriting it.
|
||||||
// This covers the example case such as adding strings and arrays of the same value.
|
// This covers the example case such as adding strings and arrays of the same value.
|
||||||
getOrPut(value, ::mutableMapOf).apply {
|
getOrPut(value, ::mutableMapOf).apply {
|
||||||
context.xmlEditor[stream].use {
|
context.xmlEditor[stream].use { editor ->
|
||||||
it.file.getElementsByTagName("app").asSequence().forEach { app ->
|
val document = editor.file
|
||||||
|
|
||||||
|
document.getElementsByTagName("app").asSequence().forEach { app ->
|
||||||
val appId = app.attributes.getNamedItem("id").textContent
|
val appId = app.attributes.getNamedItem("id").textContent
|
||||||
|
|
||||||
getOrPut(appId, ::mutableMapOf).apply {
|
getOrPut(appId, ::mutableMapOf).apply {
|
||||||
|
@ -136,8 +142,10 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
*
|
*
|
||||||
* @return True if the resource was added, false if it already existed.
|
* @return True if the resource was added, false if it already existed.
|
||||||
*/
|
*/
|
||||||
operator fun invoke(value: Value, resource: BaseResource) =
|
operator fun invoke(
|
||||||
getOrPut(value, ::mutableSetOf).add(resource)
|
value: Value,
|
||||||
|
resource: BaseResource,
|
||||||
|
) = getOrPut(value, ::mutableSetOf).add(resource)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a list of [BaseResource]s to the map using [MutableMap.getOrPut].
|
* Adds a list of [BaseResource]s to the map using [MutableMap.getOrPut].
|
||||||
|
@ -147,8 +155,10 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
*
|
*
|
||||||
* @return True if the resources were added, false if they already existed.
|
* @return True if the resources were added, false if they already existed.
|
||||||
*/
|
*/
|
||||||
operator fun invoke(value: Value, resources: Iterable<BaseResource>) =
|
operator fun invoke(
|
||||||
getOrPut(value, ::mutableSetOf).addAll(resources)
|
value: Value,
|
||||||
|
resources: Iterable<BaseResource>,
|
||||||
|
) = getOrPut(value, ::mutableSetOf).addAll(resources)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a [StringResource].
|
* Adds a [StringResource].
|
||||||
|
@ -177,10 +187,9 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
*/
|
*/
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
name: String,
|
name: String,
|
||||||
items: List<String>
|
items: List<String>,
|
||||||
) = invoke("values", ArrayResource(name, items))
|
) = invoke("values", ArrayResource(name, items))
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts all resources of any [Value] staged in [resources] for the given [PatchClass] to [AddResourcesPatch].
|
* Puts all resources of any [Value] staged in [resources] for the given [PatchClass] to [AddResourcesPatch].
|
||||||
*
|
*
|
||||||
|
@ -209,7 +218,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
|
|
||||||
appId to patchId
|
appId to patchId
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val (appId, patchId) = patch.parseIds()
|
val (appId, patchId) = patch.parseIds()
|
||||||
|
|
||||||
|
@ -232,28 +241,32 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
override fun close() {
|
override fun close() {
|
||||||
operator fun MutableMap<String, Pair<DomFileEditor, Node>>.invoke(
|
operator fun MutableMap<String, Pair<DomFileEditor, Node>>.invoke(
|
||||||
value: Value,
|
value: Value,
|
||||||
resource: BaseResource
|
resource: BaseResource,
|
||||||
) {
|
) {
|
||||||
// TODO: Fix open-closed principle violation by modifying BaseResource#serialize so that it accepts
|
// TODO: Fix open-closed principle violation by modifying BaseResource#serialize so that it accepts
|
||||||
// a Value and the map of editors. It will then get or put the editor suitable for its resource type
|
// a Value and the map of documents. It will then get or put the document suitable for its resource type
|
||||||
// to serialize itself to it.
|
// to serialize itself to it.
|
||||||
val resourceFileName = when (resource) {
|
val resourceFileName =
|
||||||
|
when (resource) {
|
||||||
is StringResource -> "strings"
|
is StringResource -> "strings"
|
||||||
is ArrayResource -> "arrays"
|
is ArrayResource -> "arrays"
|
||||||
else -> throw NotImplementedError("Unsupported resource type")
|
else -> throw NotImplementedError("Unsupported resource type")
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrPut(resourceFileName) {
|
getOrPut(resourceFileName) {
|
||||||
val targetFile = context["res/$value/$resourceFileName.xml"].also {
|
val targetFile =
|
||||||
|
context.get("res/$value/$resourceFileName.xml").also {
|
||||||
it.parentFile?.mkdirs()
|
it.parentFile?.mkdirs()
|
||||||
it.createNewFile()
|
it.createNewFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
context.xmlEditor[targetFile.path].let { editor ->
|
context.xmlEditor[targetFile.path].let { editor ->
|
||||||
|
val document = editor.file
|
||||||
|
|
||||||
// Save the target node here as well
|
// Save the target node here as well
|
||||||
// in order to avoid having to call editor.getNode("resources")
|
// in order to avoid having to call document.getNode("resources")
|
||||||
// every time addUsingEditors is called but also save the editor so that it can be closed later.
|
// but also save the document so that it can be closed later.
|
||||||
editor to editor.getNode("resources")
|
editor to document.getNode("resources")
|
||||||
}
|
}
|
||||||
}.let { (_, targetNode) ->
|
}.let { (_, targetNode) ->
|
||||||
targetNode.addResource(resource) { invoke(value, it) }
|
targetNode.addResource(resource) { invoke(value, it) }
|
||||||
|
@ -261,17 +274,17 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||||
}
|
}
|
||||||
|
|
||||||
forEach { (value, resources) ->
|
forEach { (value, resources) ->
|
||||||
// A map of editors associated by their kind (e.g. strings, arrays).
|
// A map of document associated by their kind (e.g. strings, arrays).
|
||||||
// Each editor is accompanied by the target node to which resources are added.
|
// Each document is accompanied by the target node to which resources are added.
|
||||||
// A map is used because Map#getOrPut allows opening a new editor for the duration of a resource value.
|
// A map is used because Map#getOrPut allows opening a new document for the duration of a resource value.
|
||||||
// This is done to prevent having to open the files for every resource that is added.
|
// This is done to prevent having to open the files for every resource that is added.
|
||||||
// Instead, it is cached once and reused for resources of the same value.
|
// Instead, it is cached once and reused for resources of the same value.
|
||||||
// This map is later accessed to close all editors for the current resource value.
|
// This map is later accessed to close all documents for the current resource value.
|
||||||
val resourceFileEditors = mutableMapOf<String, Pair<DomFileEditor, Node>>()
|
val documents = mutableMapOf<String, Pair<DomFileEditor, Node>>()
|
||||||
|
|
||||||
resources.forEach { resource -> resourceFileEditors(value, resource) }
|
resources.forEach { resource -> documents(value, resource) }
|
||||||
|
|
||||||
resourceFileEditors.values.forEach { (editor, _) -> editor.close() }
|
documents.values.forEach { (document, _) -> document.close() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@ import com.android.tools.smali.dexlib2.iface.Method
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
abstract class BaseTransformInstructionsPatch<T> : BytecodePatch() {
|
abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
|
||||||
abstract fun filterMap(
|
abstract fun filterMap(
|
||||||
classDef: ClassDef,
|
classDef: ClassDef,
|
||||||
method: Method,
|
method: Method,
|
||||||
instruction: Instruction,
|
instruction: Instruction,
|
||||||
instructionIndex: Int
|
instructionIndex: Int,
|
||||||
): T?
|
): T?
|
||||||
|
|
||||||
abstract fun transform(mutableMethod: MutableMethod, entry: T)
|
abstract fun transform(mutableMethod: MutableMethod, entry: T)
|
||||||
|
|
|
@ -8,11 +8,12 @@ import org.w3c.dom.Element
|
||||||
@Patch(description = "Sets allowAudioPlaybackCapture in manifest to true.")
|
@Patch(description = "Sets allowAudioPlaybackCapture in manifest to true.")
|
||||||
internal object RemoveCaptureRestrictionResourcePatch : ResourcePatch() {
|
internal object RemoveCaptureRestrictionResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
// create an xml editor instance
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
val document = editor.file
|
||||||
|
|
||||||
// get the application node
|
// get the application node
|
||||||
val applicationNode = dom
|
val applicationNode =
|
||||||
.file
|
document
|
||||||
.getElementsByTagName("application")
|
.getElementsByTagName("application")
|
||||||
.item(0) as Element
|
.item(0) as Element
|
||||||
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
|
||||||
internal object ExclusiveAudioFingerprint : MethodFingerprint(
|
|
||||||
"V",
|
|
||||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
listOf("L", "Z"),
|
|
||||||
listOf(
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_EQ,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.NOP,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.RETURN_VOID
|
|
||||||
)
|
|
||||||
)
|
|
|
@ -1,14 +1,12 @@
|
||||||
package app.revanced.patches.music.misc.gms.fingerprints
|
package app.revanced.patches.music.misc.gms.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
|
||||||
internal object ServiceCheckFingerprint : MethodFingerprint(
|
internal object ServiceCheckFingerprint : MethodFingerprint(
|
||||||
"V",
|
"V",
|
||||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
listOf("L", "I"),
|
listOf("L", "I"),
|
||||||
strings = listOf("Google Play Services not available")
|
strings = listOf("Google Play Services not available"),
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,8 +6,5 @@ import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
|
||||||
|
|
||||||
@Patch(requiresIntegrations = true)
|
@Patch(requiresIntegrations = true)
|
||||||
object IntegrationsPatch : BaseIntegrationsPatch(
|
object IntegrationsPatch : BaseIntegrationsPatch(
|
||||||
"Lapp/revanced/integrations/utils/ReVancedUtils;",
|
setOf(ApplicationInitFingerprint),
|
||||||
setOf(
|
|
||||||
ApplicationInitFingerprint,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,19 +6,20 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Remove broadcasts restriction",
|
name = "Remove broadcasts restriction",
|
||||||
description = "Enables starting/stopping NetGuard via broadcasts.",
|
description = "Enables starting/stopping NetGuard via broadcasts.",
|
||||||
compatiblePackages = [CompatiblePackage("eu.faircode.netguard")],
|
compatiblePackages = [CompatiblePackage("eu.faircode.netguard")],
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object RemoveBroadcastsRestrictionPatch : ResourcePatch() {
|
object RemoveBroadcastsRestrictionPatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
val applicationNode = dom
|
val document = editor.file
|
||||||
.file
|
|
||||||
|
val applicationNode =
|
||||||
|
document
|
||||||
.getElementsByTagName("application")
|
.getElementsByTagName("application")
|
||||||
.item(0) as Element
|
.item(0) as Element
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package app.revanced.patches.openinghours.misc.fix.crash
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.extensions.newLabel
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patches.openinghours.misc.fix.crash.fingerprints.SetPlaceFingerprint
|
||||||
|
import app.revanced.util.exception
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21t
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
name = "Fix crash",
|
||||||
|
compatiblePackages = [CompatiblePackage("de.simon.openinghours", ["1.0"])],
|
||||||
|
)
|
||||||
|
@Suppress("unused")
|
||||||
|
object FixCrashPatch : BytecodePatch(
|
||||||
|
setOf(SetPlaceFingerprint),
|
||||||
|
) {
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
SetPlaceFingerprint.result?.let {
|
||||||
|
val indexedInstructions = it.mutableMethod.getInstructions().withIndex().toList()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function replaces all `checkNotNull` instructions in the integer interval
|
||||||
|
* from [startIndex] to [endIndex], both inclusive. In place of the `checkNotNull`
|
||||||
|
* instruction an if-null check is inserted. If the if-null check yields that
|
||||||
|
* the value is indeed null, we jump to a newly created label at `endIndex + 1`.
|
||||||
|
*/
|
||||||
|
fun avoidNullPointerException(startIndex: Int, endIndex: Int) {
|
||||||
|
val continueLabel = it.mutableMethod.newLabel(endIndex + 1)
|
||||||
|
|
||||||
|
for (index in startIndex..endIndex) {
|
||||||
|
val instruction = indexedInstructions[index].value
|
||||||
|
|
||||||
|
if (!instruction.isCheckNotNullInstruction) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val checkNotNullInstruction = instruction as FiveRegisterInstruction
|
||||||
|
val originalRegister = checkNotNullInstruction.registerC
|
||||||
|
|
||||||
|
it.mutableMethod.replaceInstruction(
|
||||||
|
index,
|
||||||
|
BuilderInstruction21t(
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
originalRegister,
|
||||||
|
continueLabel,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val getOpeningHoursIndex = getIndicesOfInvoke(
|
||||||
|
indexedInstructions,
|
||||||
|
"Lde/simon/openinghours/models/Place;",
|
||||||
|
"getOpeningHours",
|
||||||
|
)
|
||||||
|
|
||||||
|
val setWeekDayTextIndex = getIndexOfInvoke(
|
||||||
|
indexedInstructions,
|
||||||
|
"Lde/simon/openinghours/views/custom/PlaceCard;",
|
||||||
|
"setWeekDayText",
|
||||||
|
)
|
||||||
|
|
||||||
|
val startCalculateStatusIndex = getIndexOfInvoke(
|
||||||
|
indexedInstructions,
|
||||||
|
"Lde/simon/openinghours/views/custom/PlaceCard;",
|
||||||
|
"startCalculateStatus",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Replace the Intrinsics;->checkNotNull instructions with a null check
|
||||||
|
// and jump to our newly created label if it returns true.
|
||||||
|
// This avoids the NullPointerExceptions.
|
||||||
|
avoidNullPointerException(getOpeningHoursIndex[1], startCalculateStatusIndex)
|
||||||
|
avoidNullPointerException(getOpeningHoursIndex[0], setWeekDayTextIndex)
|
||||||
|
} ?: throw SetPlaceFingerprint.exception
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isInvokeInstruction(instruction: Instruction, className: String, methodName: String): Boolean {
|
||||||
|
val methodRef = instruction.getReference<MethodReference>() ?: return false
|
||||||
|
return methodRef.definingClass == className && methodRef.name == methodName
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIndicesOfInvoke(
|
||||||
|
instructions: List<IndexedValue<Instruction>>,
|
||||||
|
className: String,
|
||||||
|
methodName: String,
|
||||||
|
): List<Int> = instructions.mapNotNull { (index, instruction) ->
|
||||||
|
if (isInvokeInstruction(instruction, className, methodName)) {
|
||||||
|
index
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIndexOfInvoke(
|
||||||
|
instructions: List<IndexedValue<Instruction>>,
|
||||||
|
className: String,
|
||||||
|
methodName: String,
|
||||||
|
): Int = instructions.first { (_, instruction) ->
|
||||||
|
isInvokeInstruction(instruction, className, methodName)
|
||||||
|
}.index
|
||||||
|
|
||||||
|
private val Instruction.isCheckNotNullInstruction
|
||||||
|
get() = isInvokeInstruction(this, "Lkotlin/jvm/internal/Intrinsics;", "checkNotNull")
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package app.revanced.patches.openinghours.misc.fix.crash.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
|
internal object SetPlaceFingerprint : MethodFingerprint(
|
||||||
|
"V",
|
||||||
|
parameters = listOf("Lde/simon/openinghours/models/Place;"),
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.definingClass == "Lde/simon/openinghours/views/custom/PlaceCard;" &&
|
||||||
|
methodDef.name == "setPlace"
|
||||||
|
},
|
||||||
|
)
|
|
@ -9,8 +9,10 @@ object HideBannerPatch : ResourcePatch() {
|
||||||
private const val RESOURCE_FILE_PATH = "res/layout/merge_listheader_link_detail.xml"
|
private const val RESOURCE_FILE_PATH = "res/layout/merge_listheader_link_detail.xml"
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
context.xmlEditor[RESOURCE_FILE_PATH].use {
|
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
|
||||||
it.file.getElementsByTagName("merge").item(0).childNodes.apply {
|
val document = editor.file
|
||||||
|
|
||||||
|
document.getElementsByTagName("merge").item(0).childNodes.apply {
|
||||||
val attributes = arrayOf("height", "width")
|
val attributes = arrayOf("height", "width")
|
||||||
|
|
||||||
for (i in 1 until length) {
|
for (i in 1 until length) {
|
||||||
|
@ -30,4 +32,3 @@ object HideBannerPatch : ResourcePatch() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.reddit.ad.comments.fingerprints.HideCommentAdsFingerprint
|
import app.revanced.patches.reddit.ad.comments.fingerprints.HideCommentAdsFingerprint
|
||||||
|
|
||||||
@Patch(description = "Removes ads in the comments.",)
|
@Patch(description = "Removes ads in the comments.")
|
||||||
object HideCommentAdsPatch : BytecodePatch(
|
object HideCommentAdsPatch : BytecodePatch(
|
||||||
setOf(HideCommentAdsFingerprint)
|
setOf(HideCommentAdsFingerprint)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -6,18 +6,13 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
|
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
|
||||||
|
|
||||||
@Patch(description = "Disables detection of modified versions.",)
|
@Patch(description = "Disables detection of modified versions.")
|
||||||
object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
|
object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
// Do not throw an error if the fingerprint is not resolved.
|
// Do not throw an error if the fingerprint is not resolved.
|
||||||
// This is fine because new versions of the target app do not need this patch.
|
// This is fine because new versions of the target app do not need this patch.
|
||||||
PiracyDetectionFingerprint.result?.mutableMethod?.apply {
|
PiracyDetectionFingerprint.result?.mutableMethod?.apply {
|
||||||
addInstruction(
|
addInstruction(0, "return-void")
|
||||||
0,
|
|
||||||
"""
|
|
||||||
return-void
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package app.revanced.patches.reddit.customclients.syncforreddit.fix.slink
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints.LinkHelperOpenLinkFingerprint
|
||||||
|
import app.revanced.util.exception
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
name = "Fix /s/ links",
|
||||||
|
description = "Fixes the issue where /s/ links do not work.",
|
||||||
|
compatiblePackages = [
|
||||||
|
CompatiblePackage("com.laurencedawson.reddit_sync"),
|
||||||
|
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
|
||||||
|
CompatiblePackage("com.laurencedawson.reddit_sync.dev")
|
||||||
|
],
|
||||||
|
requiresIntegrations = true
|
||||||
|
)
|
||||||
|
object FixSLinksPatch : BytecodePatch(
|
||||||
|
setOf(LinkHelperOpenLinkFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext) =
|
||||||
|
LinkHelperOpenLinkFingerprint.result?.mutableMethod?.addInstructions(
|
||||||
|
1,
|
||||||
|
"""
|
||||||
|
invoke-static { p3 }, Lapp/revanced/integrations/syncforreddit/FixSLinksPatch;->resolveSLink(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object p3
|
||||||
|
"""
|
||||||
|
) ?: throw LinkHelperOpenLinkFingerprint.exception
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
|
internal object LinkHelperOpenLinkFingerprint: MethodFingerprint(
|
||||||
|
strings = listOf("Link title: ")
|
||||||
|
)
|
|
@ -22,18 +22,20 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||||
private val fromPackageName: String,
|
private val fromPackageName: String,
|
||||||
private val toPackageName: String,
|
private val toPackageName: String,
|
||||||
private val spoofedPackageSignature: String,
|
private val spoofedPackageSignature: String,
|
||||||
dependencies: Set<PatchClass> = setOf()
|
dependencies: Set<PatchClass> = setOf(),
|
||||||
) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class, AddResourcesPatch::class) + dependencies) {
|
) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class, AddResourcesPatch::class) + dependencies) {
|
||||||
internal val gmsCoreVendorOption = stringPatchOption(
|
internal val gmsCoreVendorOption =
|
||||||
|
stringPatchOption(
|
||||||
key = "gmsCoreVendor",
|
key = "gmsCoreVendor",
|
||||||
default = "com.mgoogle",
|
default = "com.mgoogle",
|
||||||
values = mapOf(
|
values =
|
||||||
|
mapOf(
|
||||||
"Vanced" to "com.mgoogle",
|
"Vanced" to "com.mgoogle",
|
||||||
"ReVanced" to "app.revanced"
|
"ReVanced" to "app.revanced",
|
||||||
),
|
),
|
||||||
title = "GmsCore Vendor",
|
title = "GmsCore Vendor",
|
||||||
description = "The group id of the GmsCore vendor.",
|
description = "The group id of the GmsCore vendor.",
|
||||||
required = true
|
required = true,
|
||||||
) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) }
|
) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) }
|
||||||
|
|
||||||
protected val gmsCoreVendor by gmsCoreVendorOption
|
protected val gmsCoreVendor by gmsCoreVendorOption
|
||||||
|
@ -49,15 +51,20 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||||
* Add metadata to manifest to support spoofing the package name and signature of GmsCore.
|
* Add metadata to manifest to support spoofing the package name and signature of GmsCore.
|
||||||
*/
|
*/
|
||||||
private fun ResourceContext.addSpoofingMetadata() {
|
private fun ResourceContext.addSpoofingMetadata() {
|
||||||
fun Node.adoptChild(tagName: String, block: Element.() -> Unit) {
|
fun Node.adoptChild(
|
||||||
|
tagName: String,
|
||||||
|
block: Element.() -> Unit,
|
||||||
|
) {
|
||||||
val child = ownerDocument.createElement(tagName)
|
val child = ownerDocument.createElement(tagName)
|
||||||
child.block()
|
child.block()
|
||||||
appendChild(child)
|
appendChild(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlEditor["AndroidManifest.xml"].use {
|
xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
val applicationNode = it
|
val document = editor.file
|
||||||
.file
|
|
||||||
|
val applicationNode =
|
||||||
|
document
|
||||||
.getElementsByTagName("application")
|
.getElementsByTagName("application")
|
||||||
.item(0)
|
.item(0)
|
||||||
|
|
||||||
|
@ -87,27 +94,27 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||||
private fun ResourceContext.patchManifest() {
|
private fun ResourceContext.patchManifest() {
|
||||||
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
|
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
|
||||||
|
|
||||||
val manifest = this["AndroidManifest.xml"].readText()
|
val manifest = this.get("AndroidManifest.xml").readText()
|
||||||
this["AndroidManifest.xml"].writeText(
|
this.get("AndroidManifest.xml").writeText(
|
||||||
manifest.replace(
|
manifest.replace(
|
||||||
"package=\"$fromPackageName",
|
"package=\"$fromPackageName",
|
||||||
"package=\"$packageName"
|
"package=\"$packageName",
|
||||||
).replace(
|
).replace(
|
||||||
"android:authorities=\"$fromPackageName",
|
"android:authorities=\"$fromPackageName",
|
||||||
"android:authorities=\"$packageName"
|
"android:authorities=\"$packageName",
|
||||||
).replace(
|
).replace(
|
||||||
"$fromPackageName.permission.C2D_MESSAGE",
|
"$fromPackageName.permission.C2D_MESSAGE",
|
||||||
"$packageName.permission.C2D_MESSAGE"
|
"$packageName.permission.C2D_MESSAGE",
|
||||||
).replace(
|
).replace(
|
||||||
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||||
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
|
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||||
).replace(
|
).replace(
|
||||||
"com.google.android.c2dm",
|
"com.google.android.c2dm",
|
||||||
"$gmsCoreVendor.android.c2dm"
|
"$gmsCoreVendor.android.c2dm",
|
||||||
).replace(
|
).replace(
|
||||||
"</queries>",
|
"</queries>",
|
||||||
"<package android:name=\"$gmsCoreVendor.android.gms\"/></queries>"
|
"<package android:name=\"$gmsCoreVendor.android.gms\"/></queries>",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,23 +11,25 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
|
|
||||||
abstract class BaseIntegrationsPatch(
|
abstract class BaseIntegrationsPatch(
|
||||||
private val hooks: Set<IntegrationsFingerprint>
|
private val hooks: Set<IntegrationsFingerprint>,
|
||||||
) : BytecodePatch(hooks) {
|
) : BytecodePatch(hooks) {
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"Use the constructor without the integrationsDescriptor parameter",
|
"Use the constructor without the integrationsDescriptor parameter",
|
||||||
ReplaceWith("AbstractIntegrationsPatch(hooks)")
|
ReplaceWith("BaseIntegrationsPatch(hooks)"),
|
||||||
)
|
)
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
constructor(
|
constructor(
|
||||||
integrationsDescriptor: String,
|
integrationsDescriptor: String,
|
||||||
hooks: Set<IntegrationsFingerprint>
|
hooks: Set<IntegrationsFingerprint>,
|
||||||
) : this(hooks)
|
) : this(hooks)
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) throw PatchException(
|
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) {
|
||||||
"Integrations have not been merged yet. This patch can not succeed without merging the integrations."
|
throw PatchException(
|
||||||
|
"Integrations have not been merged yet. This patch can not succeed without merging the integrations.",
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
hooks.forEach { hook ->
|
hooks.forEach { hook ->
|
||||||
hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR)
|
hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||||
|
@ -47,14 +49,14 @@ abstract class BaseIntegrationsPatch(
|
||||||
opcodes: Iterable<Opcode?>? = null,
|
opcodes: Iterable<Opcode?>? = null,
|
||||||
strings: Iterable<String>? = null,
|
strings: Iterable<String>? = null,
|
||||||
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
|
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
|
||||||
private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
|
private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {},
|
||||||
) : MethodFingerprint(
|
) : MethodFingerprint(
|
||||||
returnType,
|
returnType,
|
||||||
accessFlags,
|
accessFlags,
|
||||||
parameters,
|
parameters,
|
||||||
opcodes,
|
opcodes,
|
||||||
strings,
|
strings,
|
||||||
customFingerprint
|
customFingerprint,
|
||||||
) {
|
) {
|
||||||
fun invoke(integrationsDescriptor: String) {
|
fun invoke(integrationsDescriptor: String) {
|
||||||
result?.mutableMethod?.let { method ->
|
result?.mutableMethod?.let { method ->
|
||||||
|
@ -63,7 +65,7 @@ abstract class BaseIntegrationsPatch(
|
||||||
method.addInstruction(
|
method.addInstruction(
|
||||||
0,
|
0,
|
||||||
"sput-object v$contextRegister, " +
|
"sput-object v$contextRegister, " +
|
||||||
"$integrationsDescriptor->context:Landroid/content/Context;"
|
"$integrationsDescriptor->context:Landroid/content/Context;",
|
||||||
)
|
)
|
||||||
} ?: throw PatchException("Could not find hook target fingerprint.")
|
} ?: throw PatchException("Could not find hook target fingerprint.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import java.util.*
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
object ResourceMappingPatch : ResourcePatch() {
|
object ResourceMappingPatch : ResourcePatch() {
|
||||||
internal lateinit var resourceMappings: List<ResourceElement>
|
internal lateinit var resourceMappings: List<ResourceElement>
|
||||||
private set
|
private set
|
||||||
|
@ -17,7 +16,7 @@ object ResourceMappingPatch : ResourcePatch() {
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
// save the file in memory to concurrently read from
|
// save the file in memory to concurrently read from
|
||||||
val resourceXmlFile = context["res/values/public.xml"].readBytes()
|
val resourceXmlFile = context.get("res/values/public.xml").readBytes()
|
||||||
|
|
||||||
// create a synchronized list to store the resource mappings
|
// create a synchronized list to store the resource mappings
|
||||||
val mappings = Collections.synchronizedList(mutableListOf<ResourceElement>())
|
val mappings = Collections.synchronizedList(mutableListOf<ResourceElement>())
|
||||||
|
@ -25,7 +24,9 @@ object ResourceMappingPatch : ResourcePatch() {
|
||||||
for (threadIndex in 0 until THREAD_COUNT) {
|
for (threadIndex in 0 until THREAD_COUNT) {
|
||||||
threadPoolExecutor.execute thread@{
|
threadPoolExecutor.execute thread@{
|
||||||
context.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
|
context.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
|
||||||
val resources = editor.file.documentElement.childNodes
|
val document = editor.file
|
||||||
|
|
||||||
|
val resources = document.documentElement.childNodes
|
||||||
val resourcesLength = resources.length
|
val resourcesLength = resources.length
|
||||||
val jobSize = resourcesLength / THREAD_COUNT
|
val jobSize = resourcesLength / THREAD_COUNT
|
||||||
|
|
||||||
|
|
|
@ -21,16 +21,18 @@ import java.io.Closeable
|
||||||
*/
|
*/
|
||||||
abstract class BaseSettingsResourcePatch(
|
abstract class BaseSettingsResourcePatch(
|
||||||
private val rootPreference: Pair<IntentPreference, String>? = null,
|
private val rootPreference: Pair<IntentPreference, String>? = null,
|
||||||
dependencies: Set<PatchClass> = emptySet()
|
dependencies: Set<PatchClass> = emptySet(),
|
||||||
) : ResourcePatch(
|
) : ResourcePatch(
|
||||||
dependencies = setOf(AddResourcesPatch::class) + dependencies
|
dependencies = setOf(AddResourcesPatch::class) + dependencies,
|
||||||
), MutableSet<BasePreference> by mutableSetOf(), Closeable {
|
),
|
||||||
|
MutableSet<BasePreference> by mutableSetOf(),
|
||||||
|
Closeable {
|
||||||
private lateinit var context: ResourceContext
|
private lateinit var context: ResourceContext
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
context.copyResources(
|
context.copyResources(
|
||||||
"settings",
|
"settings",
|
||||||
ResourceGroup("xml", "revanced_prefs.xml")
|
ResourceGroup("xml", "revanced_prefs.xml"),
|
||||||
)
|
)
|
||||||
|
|
||||||
this.context = context
|
this.context = context
|
||||||
|
@ -39,24 +41,34 @@ abstract class BaseSettingsResourcePatch(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
fun Node.addPreference(preference: BasePreference) {
|
fun Node.addPreference(preference: BasePreference, prepend: Boolean = false) {
|
||||||
preference.serialize(ownerDocument) { resource ->
|
preference.serialize(ownerDocument) { resource ->
|
||||||
// TODO: Currently, resources can only be added to "values", which may not be the correct place.
|
// TODO: Currently, resources can only be added to "values", which may not be the correct place.
|
||||||
// It may be necessary to ask for the desired resourceValue in the future.
|
// It may be necessary to ask for the desired resourceValue in the future.
|
||||||
AddResourcesPatch("values", resource)
|
AddResourcesPatch("values", resource)
|
||||||
}.let(this::appendChild)
|
}.let { preferenceNode ->
|
||||||
|
if (prepend && firstChild != null) {
|
||||||
|
insertBefore(preferenceNode, firstChild)
|
||||||
|
} else {
|
||||||
|
appendChild(preferenceNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the root preference to an existing fragment if needed.
|
// Add the root preference to an existing fragment if needed.
|
||||||
rootPreference?.let { (intentPreference, fragment) ->
|
rootPreference?.let { (intentPreference, fragment) ->
|
||||||
context.xmlEditor["res/xml/$fragment.xml"].use {
|
context.xmlEditor["res/xml/$fragment.xml"].use { editor ->
|
||||||
it.getNode("PreferenceScreen").addPreference(intentPreference)
|
val document = editor.file
|
||||||
|
|
||||||
|
document.getNode("PreferenceScreen").addPreference(intentPreference, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all preferences to the ReVanced fragment.
|
// Add all preferences to the ReVanced fragment.
|
||||||
context.xmlEditor["res/xml/revanced_prefs.xml"].use { editor ->
|
context.xmlEditor["res/xml/revanced_prefs.xml"].use { editor ->
|
||||||
val revancedPreferenceScreenNode = editor.getNode("PreferenceScreen")
|
val document = editor.file
|
||||||
|
|
||||||
|
val revancedPreferenceScreenNode = document.getNode("PreferenceScreen")
|
||||||
forEach { revancedPreferenceScreenNode.addPreference(it) }
|
forEach { revancedPreferenceScreenNode.addPreference(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package app.revanced.patches.shared.misc.settings.preference
|
package app.revanced.patches.shared.misc.settings.preference
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
|
|
||||||
abstract class BasePreferenceScreen(
|
abstract class BasePreferenceScreen(
|
||||||
private val root: MutableSet<Screen> = mutableSetOf()
|
private val root: MutableSet<Screen> = mutableSetOf(),
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
@ -24,34 +25,28 @@ abstract class BasePreferenceScreen(
|
||||||
titleKey: String = "${key}_title",
|
titleKey: String = "${key}_title",
|
||||||
private val summaryKey: String? = "${key}_summary",
|
private val summaryKey: String? = "${key}_summary",
|
||||||
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||||
val categories: MutableSet<Category> = mutableSetOf()
|
val categories: MutableSet<Category> = mutableSetOf(),
|
||||||
|
private val sorting: Sorting = Sorting.BY_TITLE,
|
||||||
) : BasePreferenceCollection(key, titleKey, preferences) {
|
) : BasePreferenceCollection(key, titleKey, preferences) {
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize using title and summary keys with suffix "_title" and "_summary".
|
|
||||||
*/
|
|
||||||
constructor(
|
|
||||||
key: String? = null,
|
|
||||||
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
|
||||||
categories: MutableSet<Category> = mutableSetOf()
|
|
||||||
) : this(key, key + "_title", key + "_summary", preferences, categories)
|
|
||||||
|
|
||||||
override fun transform(): PreferenceScreen {
|
override fun transform(): PreferenceScreen {
|
||||||
return PreferenceScreen(
|
return PreferenceScreen(
|
||||||
key,
|
key,
|
||||||
titleKey,
|
titleKey,
|
||||||
summaryKey,
|
summaryKey,
|
||||||
|
sorting,
|
||||||
// Screens and preferences are sorted at runtime by integrations code,
|
// Screens and preferences are sorted at runtime by integrations code,
|
||||||
// so they appear in alphabetical order for the localized language in use.
|
// so title sorting uses the localized language in use.
|
||||||
preferences = preferences + categories.map { it.transform() }
|
preferences = preferences + categories.map { it.transform() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureScreenInserted() {
|
private fun ensureScreenInserted() {
|
||||||
// Add to screens if not yet done
|
// Add to screens if not yet done
|
||||||
if (!root.contains(this))
|
if (!root.contains(this)) {
|
||||||
root.add(this)
|
root.add(this)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun addPreferences(vararg preferences: BasePreference) {
|
fun addPreferences(vararg preferences: BasePreference) {
|
||||||
ensureScreenInserted()
|
ensureScreenInserted()
|
||||||
|
@ -61,13 +56,13 @@ abstract class BasePreferenceScreen(
|
||||||
open inner class Category(
|
open inner class Category(
|
||||||
key: String? = null,
|
key: String? = null,
|
||||||
titleKey: String = "${key}_title",
|
titleKey: String = "${key}_title",
|
||||||
preferences: MutableSet<BasePreference> = mutableSetOf()
|
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||||
) : BasePreferenceCollection(key, titleKey, preferences) {
|
) : BasePreferenceCollection(key, titleKey, preferences) {
|
||||||
override fun transform(): PreferenceCategory {
|
override fun transform(): PreferenceCategory {
|
||||||
return PreferenceCategory(
|
return PreferenceCategory(
|
||||||
key,
|
key,
|
||||||
titleKey,
|
titleKey,
|
||||||
preferences = preferences
|
preferences = preferences,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +70,9 @@ abstract class BasePreferenceScreen(
|
||||||
ensureScreenInserted()
|
ensureScreenInserted()
|
||||||
|
|
||||||
// Add to the categories if not done yet.
|
// Add to the categories if not done yet.
|
||||||
if (!categories.contains(this))
|
if (!categories.contains(this)) {
|
||||||
categories.add(this)
|
categories.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
this.preferences.addAll(preferences)
|
this.preferences.addAll(preferences)
|
||||||
}
|
}
|
||||||
|
@ -86,7 +82,7 @@ abstract class BasePreferenceScreen(
|
||||||
abstract class BasePreferenceCollection(
|
abstract class BasePreferenceCollection(
|
||||||
val key: String? = null,
|
val key: String? = null,
|
||||||
val titleKey: String = "${key}_title",
|
val titleKey: String = "${key}_title",
|
||||||
val preferences: MutableSet<BasePreference> = mutableSetOf()
|
val preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||||
) {
|
) {
|
||||||
abstract fun transform(): BasePreference
|
abstract fun transform(): BasePreference
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
package app.revanced.patches.shared.misc.settings.preference
|
package app.revanced.patches.shared.misc.settings.preference
|
||||||
|
|
||||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference.Intent
|
|
||||||
import app.revanced.util.resource.BaseResource
|
import app.revanced.util.resource.BaseResource
|
||||||
import org.w3c.dom.Document
|
import org.w3c.dom.Document
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A preference that opens an intent.
|
* A preference that opens an intent.
|
||||||
*
|
*
|
||||||
* @param key The preference key. If null, other parameters must be specified.
|
* @param key Optional preference key.
|
||||||
* @param titleKey The preference title key.
|
* @param titleKey The preference title key.
|
||||||
* @param summaryKey The preference summary key.
|
* @param summaryKey The preference summary key.
|
||||||
* @param tag The preference tag.
|
* @param tag The preference tag.
|
||||||
* @param intent The intent to open.
|
* @param intent The intent to open.
|
||||||
*
|
|
||||||
* @see Intent
|
|
||||||
*/
|
*/
|
||||||
class IntentPreference(
|
class IntentPreference(
|
||||||
key: String? = null,
|
key: String? = null,
|
||||||
|
@ -21,7 +18,7 @@ class IntentPreference(
|
||||||
summaryKey: String? = "${key}_summary",
|
summaryKey: String? = "${key}_summary",
|
||||||
tag: String = "Preference",
|
tag: String = "Preference",
|
||||||
val intent: Intent,
|
val intent: Intent,
|
||||||
) : BasePreference(null, titleKey, summaryKey, tag) {
|
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||||
|
|
||||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||||
super.serialize(ownerDocument, resourceCallback).apply {
|
super.serialize(ownerDocument, resourceCallback).apply {
|
||||||
|
|
|
@ -6,10 +6,12 @@ import org.w3c.dom.Document
|
||||||
/**
|
/**
|
||||||
* A non-interactive preference.
|
* A non-interactive preference.
|
||||||
*
|
*
|
||||||
|
* Typically used to present static text, but also used for custom integration code that responds to taps.
|
||||||
|
*
|
||||||
* @param key The preference key.
|
* @param key The preference key.
|
||||||
* @param summaryKey The preference summary key.
|
* @param summaryKey The preference summary key.
|
||||||
* @param tag The preference tag.
|
* @param tag The tag or full class name of the preference.
|
||||||
* @param selectable Whether the preference is selectable.
|
* @param selectable If the preference is selectable and responds to tap events.
|
||||||
*/
|
*/
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
class NonInteractivePreference(
|
class NonInteractivePreference(
|
||||||
|
|
|
@ -9,6 +9,8 @@ import org.w3c.dom.Document
|
||||||
* @param key The key of the preference. If null, other parameters must be specified.
|
* @param key The key of the preference. If null, other parameters must be specified.
|
||||||
* @param titleKey The key of the preference title.
|
* @param titleKey The key of the preference title.
|
||||||
* @param summaryKey The key of the preference summary.
|
* @param summaryKey The key of the preference summary.
|
||||||
|
* @param sorting Sorting to use. If the sorting is not [Sorting.UNSORTED],
|
||||||
|
* then the key parameter will be modified to include the sort type.
|
||||||
* @param tag The tag or full class name of the preference.
|
* @param tag The tag or full class name of the preference.
|
||||||
* @param preferences The preferences in this screen.
|
* @param preferences The preferences in this screen.
|
||||||
*/
|
*/
|
||||||
|
@ -17,14 +19,40 @@ open class PreferenceScreen(
|
||||||
key: String? = null,
|
key: String? = null,
|
||||||
titleKey: String = "${key}_title",
|
titleKey: String = "${key}_title",
|
||||||
summaryKey: String? = "${key}_summary",
|
summaryKey: String? = "${key}_summary",
|
||||||
|
sorting: Sorting = Sorting.BY_TITLE,
|
||||||
tag: String = "PreferenceScreen",
|
tag: String = "PreferenceScreen",
|
||||||
val preferences: Set<BasePreference>
|
val preferences: Set<BasePreference>,
|
||||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
// Alternatively, instead of repurposing the key for sorting,
|
||||||
|
// an extra bundle parameter can be added to the preferences XML declaration.
|
||||||
|
// This would require bundling and referencing an additional XML file
|
||||||
|
// or adding new attributes to the attrs.xml file.
|
||||||
|
// Since the key value is not currently used by integrations,
|
||||||
|
// for now it's much simpler to modify the key to include the sort parameter.
|
||||||
|
) : BasePreference(if (sorting == Sorting.UNSORTED) key else (key + sorting.keySuffix), titleKey, summaryKey, tag) {
|
||||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||||
super.serialize(ownerDocument, resourceCallback).apply {
|
super.serialize(ownerDocument, resourceCallback).apply {
|
||||||
preferences.forEach {
|
preferences.forEach {
|
||||||
appendChild(it.serialize(ownerDocument, resourceCallback))
|
appendChild(it.serialize(ownerDocument, resourceCallback))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How a PreferenceScreen should be sorted.
|
||||||
|
*/
|
||||||
|
enum class Sorting(val keySuffix: String) {
|
||||||
|
/**
|
||||||
|
* Sort by the localized preference title.
|
||||||
|
*/
|
||||||
|
BY_TITLE("_sort_by_title"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by the preference keys.
|
||||||
|
*/
|
||||||
|
BY_KEY("_sort_by_key"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unspecified sorting.
|
||||||
|
*/
|
||||||
|
UNSORTED("_sort_by_unsorted"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.w3c.dom.Element
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Custom theme",
|
name = "Custom theme",
|
||||||
description = "Applies a custom theme.",
|
description = "Applies a custom theme.",
|
||||||
compatiblePackages = [CompatiblePackage("com.spotify.music")]
|
compatiblePackages = [CompatiblePackage("com.spotify.music")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object CustomThemePatch : ResourcePatch() {
|
object CustomThemePatch : ResourcePatch() {
|
||||||
|
@ -19,7 +19,7 @@ object CustomThemePatch : ResourcePatch() {
|
||||||
default = "@android:color/black",
|
default = "@android:color/black",
|
||||||
title = "Primary background color",
|
title = "Primary background color",
|
||||||
description = "The background color. Can be a hex color or a resource reference.",
|
description = "The background color. Can be a hex color or a resource reference.",
|
||||||
required = true
|
required = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
private var backgroundColorSecondary by stringPatchOption(
|
private var backgroundColorSecondary by stringPatchOption(
|
||||||
|
@ -27,7 +27,7 @@ object CustomThemePatch : ResourcePatch() {
|
||||||
default = "#ff282828",
|
default = "#ff282828",
|
||||||
title = "Secondary background color",
|
title = "Secondary background color",
|
||||||
description = "The secondary background color. (e.g. search box, artist & podcast). Can be a hex color or a resource reference.",
|
description = "The secondary background color. (e.g. search box, artist & podcast). Can be a hex color or a resource reference.",
|
||||||
required = true
|
required = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
private var accentColor by stringPatchOption(
|
private var accentColor by stringPatchOption(
|
||||||
|
@ -35,16 +35,17 @@ object CustomThemePatch : ResourcePatch() {
|
||||||
default = "#ff1ed760",
|
default = "#ff1ed760",
|
||||||
title = "Accent color",
|
title = "Accent color",
|
||||||
description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.",
|
description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.",
|
||||||
required = true
|
required = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
private var accentColorPressed by stringPatchOption(
|
private var accentColorPressed by stringPatchOption(
|
||||||
key = "accentColorPressed",
|
key = "accentColorPressed",
|
||||||
default = "#ff169c46",
|
default = "#ff169c46",
|
||||||
title = "Pressed dark theme accent color",
|
title = "Pressed dark theme accent color",
|
||||||
description = "The color when accented buttons are pressed, by default slightly darker than accent. "
|
description =
|
||||||
+ "Can be a hex color or a resource reference.",
|
"The color when accented buttons are pressed, by default slightly darker than accent. " +
|
||||||
required = true
|
"Can be a hex color or a resource reference.",
|
||||||
|
required = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
|
@ -54,15 +55,19 @@ object CustomThemePatch : ResourcePatch() {
|
||||||
val accentColorPressed = accentColorPressed!!
|
val accentColorPressed = accentColorPressed!!
|
||||||
|
|
||||||
context.xmlEditor["res/values/colors.xml"].use { editor ->
|
context.xmlEditor["res/values/colors.xml"].use { editor ->
|
||||||
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
|
val document = editor.file
|
||||||
|
|
||||||
|
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||||
|
|
||||||
for (i in 0 until resourcesNode.childNodes.length) {
|
for (i in 0 until resourcesNode.childNodes.length) {
|
||||||
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
|
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
|
||||||
|
|
||||||
node.textContent = when (node.getAttribute("name")) {
|
node.textContent =
|
||||||
|
when (node.getAttribute("name")) {
|
||||||
"dark_base_background_elevated_base", "design_dark_default_color_background",
|
"dark_base_background_elevated_base", "design_dark_default_color_background",
|
||||||
"design_dark_default_color_surface", "gray_7", "gray_background", "gray_layer",
|
"design_dark_default_color_surface", "gray_7", "gray_background", "gray_layer",
|
||||||
"sthlm_blk" -> backgroundColor
|
"sthlm_blk",
|
||||||
|
-> backgroundColor
|
||||||
|
|
||||||
"gray_15" -> backgroundColorSecondary
|
"gray_15" -> backgroundColorSecondary
|
||||||
|
|
||||||
|
|
|
@ -23,19 +23,19 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage("com.ss.android.ugc.trill"),
|
CompatiblePackage("com.ss.android.ugc.trill"),
|
||||||
CompatiblePackage("com.zhiliaoapp.musically")
|
CompatiblePackage("com.zhiliaoapp.musically"),
|
||||||
],
|
],
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object SpoofSimPatch : BytecodePatch() {
|
object SpoofSimPatch : BytecodePatch(emptySet()) {
|
||||||
private val replacements = hashMapOf(
|
private val replacements = hashMapOf(
|
||||||
"getSimCountryIso" to "getCountryIso",
|
"getSimCountryIso" to "getCountryIso",
|
||||||
"getNetworkCountryIso" to "getCountryIso",
|
"getNetworkCountryIso" to "getCountryIso",
|
||||||
"getSimOperator" to "getOperator",
|
"getSimOperator" to "getOperator",
|
||||||
"getNetworkOperator" to "getOperator",
|
"getNetworkOperator" to "getOperator",
|
||||||
"getSimOperatorName" to "getOperatorName",
|
"getSimOperatorName" to "getOperatorName",
|
||||||
"getNetworkOperatorName" to "getOperatorName"
|
"getNetworkOperatorName" to "getOperatorName",
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
@ -85,7 +85,7 @@ object SpoofSimPatch : BytecodePatch() {
|
||||||
with(SettingsStatusLoadFingerprint.result!!.mutableMethod) {
|
with(SettingsStatusLoadFingerprint.result!!.mutableMethod) {
|
||||||
addInstruction(
|
addInstruction(
|
||||||
0,
|
0,
|
||||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableSimSpoof()V"
|
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableSimSpoof()V",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ object SpoofSimPatch : BytecodePatch() {
|
||||||
"""
|
"""
|
||||||
invoke-static {v$resultReg}, Lapp/revanced/integrations/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
|
move-result-object v$resultReg
|
||||||
"""
|
""",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,10 +10,10 @@ import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
|
||||||
name = "Disable dashboard ads",
|
name = "Disable dashboard ads",
|
||||||
description = "Disables ads in the dashboard.",
|
description = "Disables ads in the dashboard.",
|
||||||
compatiblePackages = [CompatiblePackage("com.tumblr")],
|
compatiblePackages = [CompatiblePackage("com.tumblr")],
|
||||||
dependencies = [TimelineFilterPatch::class]
|
dependencies = [TimelineFilterPatch::class],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object DisableDashboardAds : BytecodePatch() {
|
object DisableDashboardAds : BytecodePatch(emptySet()) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
// The timeline object types are filtered by their name in the TimelineObjectType enum.
|
// The timeline object types are filtered by their name in the TimelineObjectType enum.
|
||||||
// This is often different from the "object_type" returned in the api (noted in comments here)
|
// This is often different from the "object_type" returned in the api (noted in comments here)
|
||||||
|
@ -29,7 +29,7 @@ object DisableDashboardAds : BytecodePatch() {
|
||||||
"DISPLAY_IO_INTERSCROLLER_AD", // "display_io_interscroller"
|
"DISPLAY_IO_INTERSCROLLER_AD", // "display_io_interscroller"
|
||||||
"DISPLAY_IO_HEADLINE_VIDEO_AD", // "display_io_headline_video"
|
"DISPLAY_IO_HEADLINE_VIDEO_AD", // "display_io_headline_video"
|
||||||
"FACEBOOK_BIDDAABLE", // "facebook_biddable_sdk_ad"
|
"FACEBOOK_BIDDAABLE", // "facebook_biddable_sdk_ad"
|
||||||
"GOOGLE_NATIVE" // "google_native_ad"
|
"GOOGLE_NATIVE", // "google_native_ad"
|
||||||
).forEach {
|
).forEach {
|
||||||
TimelineFilterPatch.addObjectTypeFilter(it)
|
TimelineFilterPatch.addObjectTypeFilter(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch
|
||||||
name = "Disable in-app update",
|
name = "Disable in-app update",
|
||||||
description = "Disables the in-app update check and update prompt.",
|
description = "Disables the in-app update check and update prompt.",
|
||||||
dependencies = [OverrideFeatureFlagsPatch::class],
|
dependencies = [OverrideFeatureFlagsPatch::class],
|
||||||
compatiblePackages = [CompatiblePackage("com.tumblr")]
|
compatiblePackages = [CompatiblePackage("com.tumblr")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object DisableInAppUpdatePatch : BytecodePatch() {
|
object DisableInAppUpdatePatch : BytecodePatch(emptySet()) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
// Before checking for updates using Google Play core AppUpdateManager, the value of this feature flag is checked.
|
// Before checking for updates using Google Play core AppUpdateManager, the value of this feature flag is checked.
|
||||||
// If this flag is false or the last update check was today and no update check is performed.
|
// If this flag is false or the last update check was today and no update check is performed.
|
||||||
|
|
|
@ -11,10 +11,10 @@ import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
|
||||||
name = "Disable Tumblr Live",
|
name = "Disable Tumblr Live",
|
||||||
description = "Disable the Tumblr Live tab button and dashboard carousel.",
|
description = "Disable the Tumblr Live tab button and dashboard carousel.",
|
||||||
dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class],
|
dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class],
|
||||||
compatiblePackages = [CompatiblePackage("com.tumblr")]
|
compatiblePackages = [CompatiblePackage("com.tumblr")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object DisableTumblrLivePatch : BytecodePatch() {
|
object DisableTumblrLivePatch : BytecodePatch(emptySet()) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
// Hide the LIVE_MARQUEE timeline element that appears in the feed
|
// Hide the LIVE_MARQUEE timeline element that appears in the feed
|
||||||
// Called "live_marquee" in api response
|
// Called "live_marquee" in api response
|
||||||
|
|
|
@ -26,7 +26,9 @@ object AudioAdsPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.ADS.CLIENT_SIDE.addPreferences(SwitchPreference("revanced_block_audio_ads"))
|
SettingsPatch.PreferenceScreen.ADS.CLIENT_SIDE.addPreferences(
|
||||||
|
SwitchPreference("revanced_block_audio_ads")
|
||||||
|
)
|
||||||
|
|
||||||
// Block playAds call
|
// Block playAds call
|
||||||
with(AudioAdsPresenterPlayFingerprint.result!!) {
|
with(AudioAdsPresenterPlayFingerprint.result!!) {
|
||||||
|
|
|
@ -35,7 +35,9 @@ object VideoAdsPatch : BaseAdPatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.ADS.CLIENT_SIDE.addPreferences(SwitchPreference("revanced_block_video_ads"))
|
SettingsPatch.PreferenceScreen.ADS.CLIENT_SIDE.addPreferences(
|
||||||
|
SwitchPreference("revanced_block_video_ads")
|
||||||
|
)
|
||||||
|
|
||||||
/* Amazon ads SDK */
|
/* Amazon ads SDK */
|
||||||
context.blockMethods(
|
context.blockMethods(
|
||||||
|
|
|
@ -32,7 +32,9 @@ object DebugModePatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.MISC.OTHER.addPreferences(SwitchPreference("revanced_twitch_debug_mode"))
|
SettingsPatch.PreferenceScreen.MISC.OTHER.addPreferences(
|
||||||
|
SwitchPreference("revanced_twitch_debug_mode")
|
||||||
|
)
|
||||||
|
|
||||||
listOf(
|
listOf(
|
||||||
IsDebugConfigEnabledFingerprint,
|
IsDebugConfigEnabledFingerprint,
|
||||||
|
|
|
@ -25,7 +25,6 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
|
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Settings",
|
name = "Settings",
|
||||||
description = "Adds settings menu to Twitch.",
|
description = "Adds settings menu to Twitch.",
|
||||||
|
@ -62,7 +61,9 @@ object SettingsPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
PreferenceScreen.MISC.OTHER.addPreferences(SwitchPreference("revanced_debug"))
|
PreferenceScreen.MISC.OTHER.addPreferences(
|
||||||
|
SwitchPreference("revanced_debug")
|
||||||
|
)
|
||||||
|
|
||||||
// Hook onCreate to handle fragment creation
|
// Hook onCreate to handle fragment creation
|
||||||
SettingsActivityOnCreateFingerprint.result?.apply {
|
SettingsActivityOnCreateFingerprint.result?.apply {
|
||||||
|
|
|
@ -2,27 +2,36 @@ package app.revanced.patches.twitter.interaction.downloads
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
|
import app.revanced.patches.twitter.interaction.downloads.fingerprints.BuildMediaOptionsSheetFingerprint
|
||||||
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ConstructMediaOptionsSheetFingerprint
|
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ConstructMediaOptionsSheetFingerprint
|
||||||
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ShowDownloadVideoUpsellBottomSheetFingerprint
|
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ShowDownloadVideoUpsellBottomSheetFingerprint
|
||||||
import app.revanced.util.exception
|
import app.revanced.util.exception
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Unlock downloads",
|
name = "Unlock downloads",
|
||||||
description = "Unlocks the ability to download any video.",
|
description = "Unlocks the ability to download any video. GIFs can be downloaded via the menu on long press.",
|
||||||
compatiblePackages = [CompatiblePackage("com.twitter.android")]
|
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object UnlockDownloadsPatch : BytecodePatch(
|
object UnlockDownloadsPatch : BytecodePatch(
|
||||||
setOf(ConstructMediaOptionsSheetFingerprint, ShowDownloadVideoUpsellBottomSheetFingerprint)
|
setOf(
|
||||||
|
ConstructMediaOptionsSheetFingerprint,
|
||||||
|
ShowDownloadVideoUpsellBottomSheetFingerprint,
|
||||||
|
BuildMediaOptionsSheetFingerprint,
|
||||||
|
),
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
fun MethodFingerprint.patch(getRegisterAndIndex: MethodFingerprintResult.() -> Pair<Int, Int>) = result?.let {
|
fun MethodFingerprint.patch(getRegisterAndIndex: MethodFingerprintResult.() -> Pair<Int, Int>) = result?.let {
|
||||||
|
@ -46,5 +55,29 @@ object UnlockDownloadsPatch : BytecodePatch(
|
||||||
|
|
||||||
showDownloadButtonIndex to register
|
showDownloadButtonIndex to register
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make GIFs downloadable.
|
||||||
|
BuildMediaOptionsSheetFingerprint.result?.let {
|
||||||
|
val scanResult = it.scanResult.patternScanResult!!
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val checkMediaTypeIndex = scanResult.startIndex
|
||||||
|
val checkMediaTypeInstruction = getInstruction<TwoRegisterInstruction>(checkMediaTypeIndex)
|
||||||
|
|
||||||
|
// Treat GIFs as videos.
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
checkMediaTypeIndex + 1,
|
||||||
|
"""
|
||||||
|
const/4 v${checkMediaTypeInstruction.registerB}, 0x2 # GIF
|
||||||
|
if-eq v${checkMediaTypeInstruction.registerA}, v${checkMediaTypeInstruction.registerB}, :video
|
||||||
|
""",
|
||||||
|
ExternalLabel("video", getInstruction(scanResult.endIndex)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Remove media.isDownloadable check.
|
||||||
|
removeInstruction(
|
||||||
|
getInstructions().first { insn -> insn.opcode == Opcode.IGET_BOOLEAN }.location.index + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} ?: throw BuildMediaOptionsSheetFingerprint.exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package app.revanced.patches.twitter.interaction.downloads.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal object BuildMediaOptionsSheetFingerprint : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IF_EQ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.GOTO_16,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
),
|
||||||
|
strings = listOf("resources.getString(R.string.post_video)"),
|
||||||
|
)
|
|
@ -11,12 +11,12 @@ import java.nio.file.Files
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Dynamic color",
|
name = "Dynamic color",
|
||||||
description = "Replaces the default X (Formerly Twitter) Blue with the user's Material You palette.",
|
description = "Replaces the default X (Formerly Twitter) Blue with the user's Material You palette.",
|
||||||
compatiblePackages = [CompatiblePackage("com.twitter.android")]
|
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object DynamicColorPatch : ResourcePatch() {
|
object DynamicColorPatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
val resDirectory = context["res"]
|
val resDirectory = context.get("res")
|
||||||
if (!resDirectory.isDirectory) throw PatchException("The res folder can not be found.")
|
if (!resDirectory.isDirectory) throw PatchException("The res folder can not be found.")
|
||||||
|
|
||||||
val valuesV31Directory = resDirectory.resolve("values-v31")
|
val valuesV31Directory = resDirectory.resolve("values-v31")
|
||||||
|
@ -46,7 +46,7 @@ object DynamicColorPatch : ResourcePatch() {
|
||||||
"twitter_blue_opacity_30" to "@android:color/system_accent1_100",
|
"twitter_blue_opacity_30" to "@android:color/system_accent1_100",
|
||||||
"twitter_blue_opacity_50" to "@android:color/system_accent1_200",
|
"twitter_blue_opacity_50" to "@android:color/system_accent1_200",
|
||||||
"twitter_blue_opacity_58" to "@android:color/system_accent1_300",
|
"twitter_blue_opacity_58" to "@android:color/system_accent1_300",
|
||||||
"deep_transparent_twitter_blue" to "@android:color/system_accent1_200"
|
"deep_transparent_twitter_blue" to "@android:color/system_accent1_200",
|
||||||
).forEach { (k, v) ->
|
).forEach { (k, v) ->
|
||||||
val colorElement = document.createElement("color")
|
val colorElement = document.createElement("color")
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ object DynamicColorPatch : ResourcePatch() {
|
||||||
"twitter_blue_opacity_30" to "@android:color/system_accent1_50",
|
"twitter_blue_opacity_30" to "@android:color/system_accent1_50",
|
||||||
"twitter_blue_opacity_50" to "@android:color/system_accent1_100",
|
"twitter_blue_opacity_50" to "@android:color/system_accent1_100",
|
||||||
"twitter_blue_opacity_58" to "@android:color/system_accent1_200",
|
"twitter_blue_opacity_58" to "@android:color/system_accent1_200",
|
||||||
"deep_transparent_twitter_blue" to "@android:color/system_accent1_200"
|
"deep_transparent_twitter_blue" to "@android:color/system_accent1_200",
|
||||||
).forEach { (k, v) ->
|
).forEach { (k, v) ->
|
||||||
val colorElement = document.createElement("color")
|
val colorElement = document.createElement("color")
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patches.twitter.misc.hook.json.JsonHookPatch
|
import app.revanced.patches.twitter.misc.hook.json.JsonHookPatch
|
||||||
|
|
||||||
abstract class BaseHookPatch(private val hookClassDescriptor: String) : BytecodePatch() {
|
abstract class BaseHookPatch(private val hookClassDescriptor: String) : BytecodePatch(emptySet()) {
|
||||||
override fun execute(context: BytecodeContext) =
|
override fun execute(context: BytecodeContext) =
|
||||||
JsonHookPatch.hooks.addHook(JsonHookPatch.Hook(context, hookClassDescriptor))
|
JsonHookPatch.hooks.addHook(JsonHookPatch.Hook(context, hookClassDescriptor))
|
||||||
}
|
}
|
|
@ -7,9 +7,8 @@ import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatch
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Hide ads",
|
name = "Hide ads",
|
||||||
description = "Hides ads.",
|
|
||||||
dependencies = [JsonHookPatch::class],
|
dependencies = [JsonHookPatch::class],
|
||||||
compatiblePackages = [CompatiblePackage("com.twitter.android")]
|
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object HideAdsHookPatch : BaseHookPatch("Lapp/revanced/integrations/twitter/patches/hook/patch/ads/AdsHook;")
|
object HideAdsHookPatch : BaseHookPatch("Lapp/revanced/integrations/twitter/patches/hook/patch/ads/AdsHook;")
|
|
@ -0,0 +1,35 @@
|
||||||
|
package app.revanced.patches.twitter.misc.links
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patches.twitter.misc.links.fingerprints.OpenLinkFingerprint
|
||||||
|
import app.revanced.util.exception
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
name = "Open links with app chooser",
|
||||||
|
description = "Instead of opening links directly, open them with an app chooser. " +
|
||||||
|
"As a result you can select a browser to open the link with.",
|
||||||
|
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||||
|
use = false,
|
||||||
|
)
|
||||||
|
@Suppress("unused")
|
||||||
|
object OpenLinksWithAppChooserPatch : BytecodePatch(
|
||||||
|
setOf(OpenLinkFingerprint),
|
||||||
|
) {
|
||||||
|
private const val METHOD_REFERENCE =
|
||||||
|
"Lapp/revanced/integrations/twitter/patches/links/OpenLinksWithAppChooserPatch;->" +
|
||||||
|
"openWithChooser(Landroid/content/Context;Landroid/content/Intent;)V"
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
OpenLinkFingerprint.result?.mutableMethod?.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
invoke-static { p0, p1 }, $METHOD_REFERENCE
|
||||||
|
return-void
|
||||||
|
""",
|
||||||
|
) ?: throw OpenLinkFingerprint.exception
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package app.revanced.patches.twitter.misc.links.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
|
internal object OpenLinkFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf("Landroid/content/Context;", "Landroid/content/Intent;", "Landroid/os/Bundle;"),
|
||||||
|
)
|
|
@ -1,20 +1,20 @@
|
||||||
package app.revanced.patches.vsco.misc.pro
|
package app.revanced.patches.vsco.misc.pro
|
||||||
|
|
||||||
import app.revanced.util.exception
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.vsco.misc.pro.fingerprints.RevCatSubscriptionFingerprint
|
import app.revanced.patches.vsco.misc.pro.fingerprints.RevCatSubscriptionFingerprint
|
||||||
|
import app.revanced.util.exception
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Unlock pro",
|
name = "Unlock pro",
|
||||||
description = "Unlocks pro features.",
|
description = "Unlocks pro features.",
|
||||||
compatiblePackages = [CompatiblePackage("com.vsco.cam")]
|
compatiblePackages = [CompatiblePackage("com.vsco.cam", ["345"])],
|
||||||
)
|
)
|
||||||
object UnlockProPatch : BytecodePatch(
|
object UnlockProPatch : BytecodePatch(
|
||||||
setOf(RevCatSubscriptionFingerprint)
|
setOf(RevCatSubscriptionFingerprint),
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
RevCatSubscriptionFingerprint.result?.mutableMethod?.apply {
|
RevCatSubscriptionFingerprint.result?.mutableMethod?.apply {
|
||||||
|
@ -23,7 +23,7 @@ object UnlockProPatch : BytecodePatch(
|
||||||
0,
|
0,
|
||||||
"""
|
"""
|
||||||
const p1, 0x1
|
const p1, 0x1
|
||||||
"""
|
""",
|
||||||
)
|
)
|
||||||
} ?: throw RevCatSubscriptionFingerprint.exception
|
} ?: throw RevCatSubscriptionFingerprint.exception
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package app.revanced.patches.youtube.ad.general
|
package app.revanced.patches.youtube.ad.general
|
||||||
|
|
||||||
import app.revanced.util.findMutableMethodOf
|
|
||||||
import app.revanced.util.injectHideViewCall
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
@ -9,6 +7,8 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.shared.misc.fix.verticalscroll.VerticalScrollPatch
|
import app.revanced.patches.shared.misc.fix.verticalscroll.VerticalScrollPatch
|
||||||
import app.revanced.patches.youtube.ad.getpremium.HideGetPremiumPatch
|
import app.revanced.patches.youtube.ad.getpremium.HideGetPremiumPatch
|
||||||
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.FixBackToExitGesturePatch
|
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.FixBackToExitGesturePatch
|
||||||
|
import app.revanced.util.findMutableMethodOf
|
||||||
|
import app.revanced.util.injectHideViewCall
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
|
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
@ -20,11 +20,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
HideGetPremiumPatch::class,
|
HideGetPremiumPatch::class,
|
||||||
HideAdsResourcePatch::class,
|
HideAdsResourcePatch::class,
|
||||||
VerticalScrollPatch::class,
|
VerticalScrollPatch::class,
|
||||||
FixBackToExitGesturePatch::class
|
FixBackToExitGesturePatch::class,
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
"com.google.android.youtube", [
|
"com.google.android.youtube",
|
||||||
|
[
|
||||||
"18.32.39",
|
"18.32.39",
|
||||||
"18.37.36",
|
"18.37.36",
|
||||||
"18.38.44",
|
"18.38.44",
|
||||||
|
@ -37,30 +38,33 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
"19.02.39",
|
"19.02.39",
|
||||||
"19.03.35",
|
"19.03.35",
|
||||||
"19.03.36",
|
"19.03.36",
|
||||||
"19.04.37"
|
"19.04.37",
|
||||||
]
|
],
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object HideAdsPatch : BytecodePatch() {
|
object HideAdsPatch : BytecodePatch(emptySet()) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
context.classes.forEach { classDef ->
|
context.classes.forEach { classDef ->
|
||||||
classDef.methods.forEach { method ->
|
classDef.methods.forEach { method ->
|
||||||
with(method.implementation) {
|
with(method.implementation) {
|
||||||
this?.instructions?.forEachIndexed { index, instruction ->
|
this?.instructions?.forEachIndexed { index, instruction ->
|
||||||
if (instruction.opcode != Opcode.CONST)
|
if (instruction.opcode != Opcode.CONST) {
|
||||||
return@forEachIndexed
|
return@forEachIndexed
|
||||||
|
}
|
||||||
// Instruction to store the id adAttribution into a register
|
// Instruction to store the id adAttribution into a register
|
||||||
if ((instruction as Instruction31i).wideLiteral != HideAdsResourcePatch.adAttributionId)
|
if ((instruction as Instruction31i).wideLiteral != HideAdsResourcePatch.adAttributionId) {
|
||||||
return@forEachIndexed
|
return@forEachIndexed
|
||||||
|
}
|
||||||
|
|
||||||
val insertIndex = index + 1
|
val insertIndex = index + 1
|
||||||
|
|
||||||
// Call to get the view with the id adAttribution
|
// Call to get the view with the id adAttribution
|
||||||
with(instructions.elementAt(insertIndex)) {
|
with(instructions.elementAt(insertIndex)) {
|
||||||
if (opcode != Opcode.INVOKE_VIRTUAL)
|
if (opcode != Opcode.INVOKE_VIRTUAL) {
|
||||||
return@forEachIndexed
|
return@forEachIndexed
|
||||||
|
}
|
||||||
|
|
||||||
// Hide the view
|
// Hide the view
|
||||||
val viewRegister = (this as Instruction35c).registerC
|
val viewRegister = (this as Instruction35c).registerC
|
||||||
|
@ -71,7 +75,7 @@ object HideAdsPatch : BytecodePatch() {
|
||||||
insertIndex,
|
insertIndex,
|
||||||
viewRegister,
|
viewRegister,
|
||||||
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;",
|
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;",
|
||||||
"hideAdAttributionView"
|
"hideAdAttributionView",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
|
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
@ -27,7 +26,7 @@ object HideAdsResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
PreferenceScreen.ADS.addPreferences(
|
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||||
SwitchPreference("revanced_hide_general_ads"),
|
SwitchPreference("revanced_hide_general_ads"),
|
||||||
SwitchPreference("revanced_hide_fullscreen_ads"),
|
SwitchPreference("revanced_hide_fullscreen_ads"),
|
||||||
SwitchPreference("revanced_hide_buttoned_ads"),
|
SwitchPreference("revanced_hide_buttoned_ads"),
|
||||||
|
|
|
@ -44,7 +44,9 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(SwitchPreference("revanced_hide_get_premium"))
|
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_get_premium")
|
||||||
|
)
|
||||||
|
|
||||||
GetPremiumViewFingerprint.result?.let {
|
GetPremiumViewFingerprint.result?.let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
|
|
|
@ -49,7 +49,9 @@ object VideoAdsPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(SwitchPreference("revanced_hide_video_ads"))
|
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_video_ads")
|
||||||
|
)
|
||||||
|
|
||||||
val loadVideoAdsFingerprintMethod = LoadVideoAdsFingerprint.result!!.mutableMethod
|
val loadVideoAdsFingerprintMethod = LoadVideoAdsFingerprint.result!!.mutableMethod
|
||||||
|
|
||||||
|
|
|
@ -13,28 +13,29 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
dependencies = [
|
dependencies = [
|
||||||
CopyVideoUrlResourcePatch::class,
|
CopyVideoUrlResourcePatch::class,
|
||||||
PlayerControlsBytecodePatch::class,
|
PlayerControlsBytecodePatch::class,
|
||||||
VideoInformationPatch::class
|
VideoInformationPatch::class,
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
"com.google.android.youtube", [
|
"com.google.android.youtube",
|
||||||
|
[
|
||||||
"18.48.39",
|
"18.48.39",
|
||||||
"18.49.37",
|
"18.49.37",
|
||||||
"19.01.34",
|
"19.01.34",
|
||||||
"19.02.39",
|
"19.02.39",
|
||||||
"19.03.35",
|
"19.03.35",
|
||||||
"19.03.36",
|
"19.03.36",
|
||||||
"19.04.37"
|
"19.04.37",
|
||||||
]
|
],
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object CopyVideoUrlBytecodePatch : BytecodePatch() {
|
object CopyVideoUrlBytecodePatch : BytecodePatch(emptySet()) {
|
||||||
private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/youtube/videoplayer"
|
private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/youtube/videoplayer"
|
||||||
private val BUTTONS_DESCRIPTORS = listOf(
|
private val BUTTONS_DESCRIPTORS = listOf(
|
||||||
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
|
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
|
||||||
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
|
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;",
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import app.revanced.patcher.data.ResourceContext
|
||||||
import app.revanced.patcher.patch.ResourcePatch
|
import app.revanced.patcher.patch.ResourcePatch
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
|
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
|
@ -22,15 +21,10 @@ internal object CopyVideoUrlResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
PreferenceScreen(
|
|
||||||
"revanced_copy_video_url_preference_screen",
|
|
||||||
preferences = setOf(
|
|
||||||
SwitchPreference("revanced_copy_video_url"),
|
SwitchPreference("revanced_copy_video_url"),
|
||||||
SwitchPreference("revanced_copy_video_url_timestamp")
|
SwitchPreference("revanced_copy_video_url_timestamp")
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
context.copyResources(
|
context.copyResources(
|
||||||
"copyvideourl", ResourceGroup(
|
"copyvideourl", ResourceGroup(
|
||||||
|
@ -40,8 +34,6 @@ internal object CopyVideoUrlResourcePatch : ResourcePatch() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
AddResourcesPatch(this::class)
|
|
||||||
|
|
||||||
BottomControlsResourcePatch.addControls("copyvideourl")
|
BottomControlsResourcePatch.addControls("copyvideourl")
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -50,7 +50,9 @@ object RemoveViewerDiscretionDialogPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(SwitchPreference("revanced_remove_viewer_discretion_dialog"))
|
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||||
|
SwitchPreference("revanced_remove_viewer_discretion_dialog")
|
||||||
|
)
|
||||||
|
|
||||||
CreateDialogFingerprint.result?.mutableMethod?.apply {
|
CreateDialogFingerprint.result?.mutableMethod?.apply {
|
||||||
val showDialogIndex = implementation!!.instructions.lastIndex - 2
|
val showDialogIndex = implementation!!.instructions.lastIndex - 2
|
||||||
|
|
|
@ -13,24 +13,25 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
dependencies = [
|
dependencies = [
|
||||||
ExternalDownloadsResourcePatch::class,
|
ExternalDownloadsResourcePatch::class,
|
||||||
PlayerControlsBytecodePatch::class,
|
PlayerControlsBytecodePatch::class,
|
||||||
VideoInformationPatch::class
|
VideoInformationPatch::class,
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
"com.google.android.youtube", [
|
"com.google.android.youtube",
|
||||||
|
[
|
||||||
"18.48.39",
|
"18.48.39",
|
||||||
"18.49.37",
|
"18.49.37",
|
||||||
"19.01.34",
|
"19.01.34",
|
||||||
"19.02.39",
|
"19.02.39",
|
||||||
"19.03.35",
|
"19.03.35",
|
||||||
"19.03.36",
|
"19.03.36",
|
||||||
"19.04.37"
|
"19.04.37",
|
||||||
]
|
],
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object ExternalDownloadsBytecodePatch : BytecodePatch() {
|
object ExternalDownloadsBytecodePatch : BytecodePatch(emptySet()) {
|
||||||
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
|
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
@ -39,13 +40,15 @@ object ExternalDownloadsBytecodePatch : BytecodePatch() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PlayerControlsBytecodePatch.initializeControl(
|
PlayerControlsBytecodePatch.initializeControl(
|
||||||
"$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
|
"$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V",
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
add code to change the visibility of the control
|
add code to change the visibility of the control
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(
|
PlayerControlsBytecodePatch.injectVisibilityCheckCall(
|
||||||
"$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
|
"$BUTTON_DESCRIPTOR->changeVisibility(Z)V",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||||
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||||
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
|
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
|
||||||
|
@ -18,25 +19,26 @@ import app.revanced.util.copyResources
|
||||||
BottomControlsResourcePatch::class,
|
BottomControlsResourcePatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
AddResourcesPatch::class,
|
AddResourcesPatch::class,
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
internal object ExternalDownloadsResourcePatch : ResourcePatch() {
|
internal object ExternalDownloadsResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
"revanced_external_downloader_preference_screen",
|
key = "revanced_external_downloader_screen",
|
||||||
|
sorting = Sorting.UNSORTED,
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_external_downloader"),
|
SwitchPreference("revanced_external_downloader"),
|
||||||
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT)
|
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
context.copyResources(
|
context.copyResources(
|
||||||
"downloads",
|
"downloads",
|
||||||
ResourceGroup("drawable", "revanced_yt_download_button.xml")
|
ResourceGroup("drawable", "revanced_yt_download_button.xml"),
|
||||||
)
|
)
|
||||||
|
|
||||||
BottomControlsResourcePatch.addControls("downloads")
|
BottomControlsResourcePatch.addControls("downloads")
|
||||||
|
|
|
@ -50,7 +50,7 @@ object DisablePreciseSeekingGesturePatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
|
||||||
SwitchPreference("revanced_disable_precise_seeking_gesture")
|
SwitchPreference("revanced_disable_precise_seeking_gesture")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,9 @@ object EnableSeekbarTappingPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(SwitchPreference("revanced_seekbar_tapping"))
|
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
|
||||||
|
SwitchPreference("revanced_seekbar_tapping")
|
||||||
|
)
|
||||||
|
|
||||||
// Find the required methods to tap the seekbar.
|
// Find the required methods to tap the seekbar.
|
||||||
val seekbarTappingMethods = OnTouchEventHandlerFingerprint.result?.let {
|
val seekbarTappingMethods = OnTouchEventHandlerFingerprint.result?.let {
|
||||||
|
|
|
@ -50,7 +50,9 @@ object EnableSlideToSeekPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(SwitchPreference("revanced_slide_to_seek"))
|
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
|
||||||
|
SwitchPreference("revanced_slide_to_seek")
|
||||||
|
)
|
||||||
|
|
||||||
arrayOf(
|
arrayOf(
|
||||||
// Restore the behaviour to slide to seek.
|
// Restore the behaviour to slide to seek.
|
||||||
|
|
|
@ -5,7 +5,6 @@ import app.revanced.patcher.patch.ResourcePatch
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
|
@ -13,16 +12,13 @@ import app.revanced.util.ResourceGroup
|
||||||
import app.revanced.util.copyResources
|
import app.revanced.util.copyResources
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
dependencies = [SettingsPatch::class, AddResourcesPatch::class]
|
dependencies = [SettingsPatch::class, AddResourcesPatch::class],
|
||||||
)
|
)
|
||||||
internal object SwipeControlsResourcePatch : ResourcePatch() {
|
internal object SwipeControlsResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
SettingsPatch.PreferenceScreen.SWIPE_CONTROLS.addPreferences(
|
||||||
PreferenceScreen(
|
|
||||||
key = "revanced_swipe_controls_preference_screen",
|
|
||||||
preferences = setOf(
|
|
||||||
SwitchPreference("revanced_swipe_brightness"),
|
SwitchPreference("revanced_swipe_brightness"),
|
||||||
SwitchPreference("revanced_swipe_volume"),
|
SwitchPreference("revanced_swipe_volume"),
|
||||||
SwitchPreference("revanced_swipe_press_to_engage"),
|
SwitchPreference("revanced_swipe_press_to_engage"),
|
||||||
|
@ -31,9 +27,7 @@ internal object SwipeControlsResourcePatch : ResourcePatch() {
|
||||||
TextPreference("revanced_swipe_overlay_timeout", inputType = InputType.NUMBER),
|
TextPreference("revanced_swipe_overlay_timeout", inputType = InputType.NUMBER),
|
||||||
TextPreference("revanced_swipe_text_overlay_size", inputType = InputType.NUMBER),
|
TextPreference("revanced_swipe_text_overlay_size", inputType = InputType.NUMBER),
|
||||||
TextPreference("revanced_swipe_overlay_background_alpha", inputType = InputType.NUMBER),
|
TextPreference("revanced_swipe_overlay_background_alpha", inputType = InputType.NUMBER),
|
||||||
TextPreference("revanced_swipe_threshold", inputType = InputType.NUMBER)
|
TextPreference("revanced_swipe_threshold", inputType = InputType.NUMBER),
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
context.copyResources(
|
context.copyResources(
|
||||||
|
@ -43,8 +37,8 @@ internal object SwipeControlsResourcePatch : ResourcePatch() {
|
||||||
"revanced_ic_sc_brightness_auto.xml",
|
"revanced_ic_sc_brightness_auto.xml",
|
||||||
"revanced_ic_sc_brightness_manual.xml",
|
"revanced_ic_sc_brightness_manual.xml",
|
||||||
"revanced_ic_sc_volume_mute.xml",
|
"revanced_ic_sc_volume_mute.xml",
|
||||||
"revanced_ic_sc_volume_normal.xml"
|
"revanced_ic_sc_volume_normal.xml",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,9 @@ object AutoCaptionsPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_auto_captions"))
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_auto_captions")
|
||||||
|
)
|
||||||
|
|
||||||
mapOf(
|
mapOf(
|
||||||
StartVideoInformerFingerprint to 0,
|
StartVideoInformerFingerprint to 0,
|
||||||
|
|
|
@ -15,9 +15,9 @@ import java.nio.file.Files
|
||||||
name = "Custom branding",
|
name = "Custom branding",
|
||||||
description = "Applies a custom app name and icon. Defaults to \"YouTube ReVanced\" and the ReVanced logo.",
|
description = "Applies a custom app name and icon. Defaults to \"YouTube ReVanced\" and the ReVanced logo.",
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage("com.google.android.youtube")
|
CompatiblePackage("com.google.android.youtube"),
|
||||||
],
|
],
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object CustomBrandingPatch : ResourcePatch() {
|
object CustomBrandingPatch : ResourcePatch() {
|
||||||
|
@ -28,7 +28,7 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||||
"adaptiveproduct_youtube_background_color_108",
|
"adaptiveproduct_youtube_background_color_108",
|
||||||
"adaptiveproduct_youtube_foreground_color_108",
|
"adaptiveproduct_youtube_foreground_color_108",
|
||||||
"ic_launcher",
|
"ic_launcher",
|
||||||
"ic_launcher_round"
|
"ic_launcher_round",
|
||||||
).map { "$it.png" }.toTypedArray()
|
).map { "$it.png" }.toTypedArray()
|
||||||
|
|
||||||
private val mipmapDirectories = arrayOf(
|
private val mipmapDirectories = arrayOf(
|
||||||
|
@ -36,7 +36,7 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||||
"xxhdpi",
|
"xxhdpi",
|
||||||
"xhdpi",
|
"xhdpi",
|
||||||
"hdpi",
|
"hdpi",
|
||||||
"mdpi"
|
"mdpi",
|
||||||
).map { "mipmap-$it" }
|
).map { "mipmap-$it" }
|
||||||
|
|
||||||
private var appName by stringPatchOption(
|
private var appName by stringPatchOption(
|
||||||
|
@ -49,7 +49,7 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||||
"YouTube" to "YouTube",
|
"YouTube" to "YouTube",
|
||||||
),
|
),
|
||||||
title = "App name",
|
title = "App name",
|
||||||
description = "The name of the app."
|
description = "The name of the app.",
|
||||||
)
|
)
|
||||||
|
|
||||||
private var icon by stringPatchOption(
|
private var icon by stringPatchOption(
|
||||||
|
@ -58,14 +58,16 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||||
values = mapOf("ReVanced Logo" to REVANCED_ICON),
|
values = mapOf("ReVanced Logo" to REVANCED_ICON),
|
||||||
title = "App icon",
|
title = "App icon",
|
||||||
description = """
|
description = """
|
||||||
The path to a folder containing the following folders:
|
The icon to apply to the app.
|
||||||
|
|
||||||
|
If a path to a folder is provided, the folder must contain the following folders:
|
||||||
|
|
||||||
${mipmapDirectories.joinToString("\n") { "- $it" }}
|
${mipmapDirectories.joinToString("\n") { "- $it" }}
|
||||||
|
|
||||||
Each of these folders has to have the following files:
|
Each of these folders must contain the following files:
|
||||||
|
|
||||||
${iconResourceFileNames.joinToString("\n") { "- $it" }}
|
${iconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||||
""".trimIndentMultiline()
|
""".trimIndentMultiline(),
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
|
@ -73,12 +75,13 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||||
// Change the app icon.
|
// Change the app icon.
|
||||||
mipmapDirectories.map { directory ->
|
mipmapDirectories.map { directory ->
|
||||||
ResourceGroup(
|
ResourceGroup(
|
||||||
directory, *iconResourceFileNames
|
directory,
|
||||||
|
*iconResourceFileNames,
|
||||||
)
|
)
|
||||||
}.let { resourceGroups ->
|
}.let { resourceGroups ->
|
||||||
if (icon != REVANCED_ICON) {
|
if (icon != REVANCED_ICON) {
|
||||||
val path = File(icon)
|
val path = File(icon)
|
||||||
val resourceDirectory = context["res"]
|
val resourceDirectory = context.get("res")
|
||||||
|
|
||||||
resourceGroups.forEach { group ->
|
resourceGroups.forEach { group ->
|
||||||
val fromDirectory = path.resolve(group.resourceDirectoryName)
|
val fromDirectory = path.resolve(group.resourceDirectoryName)
|
||||||
|
@ -87,23 +90,25 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||||
group.resources.forEach { iconFileName ->
|
group.resources.forEach { iconFileName ->
|
||||||
Files.write(
|
Files.write(
|
||||||
toDirectory.resolve(iconFileName).toPath(),
|
toDirectory.resolve(iconFileName).toPath(),
|
||||||
fromDirectory.resolve(iconFileName).readBytes()
|
fromDirectory.resolve(iconFileName).readBytes(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else resourceGroups.forEach { context.copyResources("custom-branding", it) }
|
} else {
|
||||||
|
resourceGroups.forEach { context.copyResources("custom-branding", it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appName?.let { name ->
|
appName?.let { name ->
|
||||||
// Change the app name.
|
// Change the app name.
|
||||||
val manifest = context["AndroidManifest.xml"]
|
val manifest = context.get("AndroidManifest.xml")
|
||||||
manifest.writeText(
|
manifest.writeText(
|
||||||
manifest.readText()
|
manifest.readText()
|
||||||
.replace(
|
.replace(
|
||||||
"android:label=\"@string/application_name",
|
"android:label=\"@string/application_name",
|
||||||
"android:label=\"$name"
|
"android:label=\"$name",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,67 +15,74 @@ import java.io.File
|
||||||
name = "Change header",
|
name = "Change header",
|
||||||
description = "Applies a custom header in the top left corner within the app. Defaults to the ReVanced header.",
|
description = "Applies a custom header in the top left corner within the app. Defaults to the ReVanced header.",
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage("com.google.android.youtube")
|
CompatiblePackage("com.google.android.youtube"),
|
||||||
],
|
],
|
||||||
use = false
|
use = false,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object ChangeHeaderPatch : ResourcePatch() {
|
object ChangeHeaderPatch : ResourcePatch() {
|
||||||
private const val HEADER_NAME = "yt_wordmark_header"
|
private const val HEADER_FILE_NAME = "yt_wordmark_header"
|
||||||
private const val PREMIUM_HEADER_NAME = "yt_premium_wordmark_header"
|
private const val PREMIUM_HEADER_FILE_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(
|
private const val HEADER_OPTION = "header*"
|
||||||
"xxxhdpi",
|
private const val PREMIUM_HEADER_OPTION = "premium*header"
|
||||||
"xxhdpi",
|
private const val REVANCED_HEADER_OPTION = "revanced*"
|
||||||
"xhdpi",
|
private const val REVANCED_BORDERLESS_HEADER_OPTION = "revanced*borderless"
|
||||||
"mdpi",
|
|
||||||
"hdpi",
|
private val targetResourceDirectoryNames = mapOf(
|
||||||
).map { dpi ->
|
"xxxhdpi" to "512px x 192px",
|
||||||
"drawable-$dpi"
|
"xxhdpi" to "387px x 144px",
|
||||||
}
|
"xhdpi" to "258px x 96px",
|
||||||
|
"hdpi" to "194px x 72px",
|
||||||
|
"mdpi" to "129px x 48px",
|
||||||
|
).map { (dpi, dim) ->
|
||||||
|
"drawable-$dpi" to dim
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
private val variants = arrayOf("light", "dark")
|
private val variants = arrayOf("light", "dark")
|
||||||
|
|
||||||
private val header by stringPatchOption(
|
private val header by stringPatchOption(
|
||||||
key = "header",
|
key = "header",
|
||||||
default = REVANCED_BORDERLESS_HEADER_NAME,
|
default = REVANCED_BORDERLESS_HEADER_OPTION,
|
||||||
values = mapOf(
|
values = mapOf(
|
||||||
"YouTube" to HEADER_NAME,
|
"YouTube" to HEADER_OPTION,
|
||||||
"YouTube Premium" to PREMIUM_HEADER_NAME,
|
"YouTube Premium" to PREMIUM_HEADER_OPTION,
|
||||||
"ReVanced" to REVANCED_HEADER_NAME,
|
"ReVanced" to REVANCED_HEADER_OPTION,
|
||||||
"ReVanced (borderless logo)" to REVANCED_BORDERLESS_HEADER_NAME,
|
"ReVanced (borderless logo)" to REVANCED_BORDERLESS_HEADER_OPTION,
|
||||||
),
|
),
|
||||||
title = "Header",
|
title = "Header",
|
||||||
description = """
|
description = """
|
||||||
Either a header name or a path to a custom header folder to use in the top bar.
|
The header to apply to the app.
|
||||||
The path to a folder must contain one or more of the following folders matching the DPI of your device:
|
|
||||||
|
|
||||||
${targetResourceDirectoryNames.joinToString("\n") { "- $it" }}
|
If a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device:
|
||||||
|
|
||||||
These folders must contain the following files:
|
${targetResourceDirectoryNames.keys.joinToString("\n") { "- $it" }}
|
||||||
|
|
||||||
${variants.joinToString("\n") { variant -> "- ${HEADER_NAME}_$variant.png" }}
|
Each of the folders must contain all of the following files:
|
||||||
|
|
||||||
|
${variants.joinToString("\n") { variant -> "- ${HEADER_FILE_NAME}_$variant.png" }}
|
||||||
|
|
||||||
|
The image dimensions must be as follows:
|
||||||
|
${targetResourceDirectoryNames.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")}
|
||||||
""".trimIndentMultiline(),
|
""".trimIndentMultiline(),
|
||||||
required = true,
|
required = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
// The directories to copy the header to.
|
// The directories to copy the header to.
|
||||||
val targetResourceDirectories = targetResourceDirectoryNames.mapNotNull {
|
val targetResourceDirectories = targetResourceDirectoryNames.keys.mapNotNull {
|
||||||
context["res"].resolve(it).takeIf(File::exists)
|
context.get("res").resolve(it).takeIf(File::exists)
|
||||||
}
|
}
|
||||||
// The files to replace in the target directories.
|
// The files to replace in the target directories.
|
||||||
val targetResourceFiles = targetResourceDirectoryNames.map { directoryName ->
|
val targetResourceFiles = targetResourceDirectoryNames.keys.map { directoryName ->
|
||||||
ResourceGroup(
|
ResourceGroup(
|
||||||
directoryName,
|
directoryName,
|
||||||
*variants.map { variant -> "${HEADER_NAME}_$variant.png" }.toTypedArray()
|
*variants.map { variant -> "${HEADER_FILE_NAME}_$variant.png" }.toTypedArray(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function that overwrites both header variants from [from] to [to] in the target resource directories.
|
* A function that overwrites both header variants in the target resource directories.
|
||||||
*/
|
*/
|
||||||
val overwriteFromTo: (String, String) -> Unit = { from: String, to: String ->
|
val overwriteFromTo: (String, String) -> Unit = { from: String, to: String ->
|
||||||
targetResourceDirectories.forEach { directory ->
|
targetResourceDirectories.forEach { directory ->
|
||||||
|
@ -89,8 +96,8 @@ object ChangeHeaderPatch : ResourcePatch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions to overwrite the header to the different variants.
|
// Functions to overwrite the header to the different variants.
|
||||||
val toPremium = { overwriteFromTo(PREMIUM_HEADER_NAME, HEADER_NAME) }
|
val toPremium = { overwriteFromTo(PREMIUM_HEADER_FILE_NAME, HEADER_FILE_NAME) }
|
||||||
val toHeader = { overwriteFromTo(HEADER_NAME, PREMIUM_HEADER_NAME) }
|
val toHeader = { overwriteFromTo(HEADER_FILE_NAME, PREMIUM_HEADER_FILE_NAME) }
|
||||||
val toReVanced = {
|
val toReVanced = {
|
||||||
// Copy the ReVanced header to the resource directories.
|
// Copy the ReVanced header to the resource directories.
|
||||||
targetResourceFiles.forEach { context.copyResources("change-header/revanced", it) }
|
targetResourceFiles.forEach { context.copyResources("change-header/revanced", it) }
|
||||||
|
@ -106,32 +113,38 @@ object ChangeHeaderPatch : ResourcePatch() {
|
||||||
toHeader()
|
toHeader()
|
||||||
}
|
}
|
||||||
val toCustom = {
|
val toCustom = {
|
||||||
var copiedReplacementImages = false
|
val sourceFolders = File(header!!).listFiles { file -> file.isDirectory }
|
||||||
// For all the resource groups in the custom header folder, copy them to the resource directories.
|
?: throw PatchException("The provided path is not a directory: $header")
|
||||||
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 {
|
var copiedFiles = false
|
||||||
val targetResourceFile = targetDirectory.resolve(it.name)
|
|
||||||
|
|
||||||
it.copyTo(targetResourceFile, true)
|
// For each source folder, copy the files to the target resource directories.
|
||||||
copiedReplacementImages = true
|
sourceFolders.forEach { dpiSourceFolder ->
|
||||||
|
val targetDpiFolder = context.get("res").resolve(dpiSourceFolder.name)
|
||||||
|
if (!targetDpiFolder.exists()) return@forEach
|
||||||
|
|
||||||
|
val imgSourceFiles = dpiSourceFolder.listFiles { file -> file.isFile }!!
|
||||||
|
imgSourceFiles.forEach { imgSourceFile ->
|
||||||
|
val imgTargetFile = targetDpiFolder.resolve(imgSourceFile.name)
|
||||||
|
imgSourceFile.copyTo(imgTargetFile, true)
|
||||||
|
|
||||||
|
copiedFiles = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!copiedReplacementImages) throw PatchException("Could not find any custom images resources in directory: $header")
|
if (!copiedFiles) {
|
||||||
|
throw PatchException("No header files were copied from the provided path: $header.")
|
||||||
|
}
|
||||||
|
|
||||||
// Overwrite the premium with the custom header as well.
|
// Overwrite the premium with the custom header as well.
|
||||||
toHeader()
|
toHeader()
|
||||||
}
|
}
|
||||||
|
|
||||||
when (header) {
|
when (header) {
|
||||||
HEADER_NAME -> toHeader
|
HEADER_OPTION -> toHeader
|
||||||
PREMIUM_HEADER_NAME -> toPremium
|
PREMIUM_HEADER_OPTION -> toPremium
|
||||||
REVANCED_HEADER_NAME -> toReVanced
|
REVANCED_HEADER_OPTION -> toReVanced
|
||||||
REVANCED_BORDERLESS_HEADER_NAME -> toReVancedBorderless
|
REVANCED_BORDERLESS_HEADER_OPTION -> toReVancedBorderless
|
||||||
else -> toCustom
|
else -> toCustom
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,12 +48,11 @@ object HideButtonsPatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
"revanced_hide_buttons_preference_screen",
|
"revanced_hide_buttons_screen",
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_hide_like_dislike_button"),
|
SwitchPreference("revanced_hide_like_dislike_button"),
|
||||||
SwitchPreference("revanced_hide_live_chat_button"),
|
|
||||||
SwitchPreference("revanced_hide_share_button"),
|
SwitchPreference("revanced_hide_share_button"),
|
||||||
SwitchPreference("revanced_hide_report_button"),
|
SwitchPreference("revanced_hide_report_button"),
|
||||||
SwitchPreference("revanced_hide_remix_button"),
|
SwitchPreference("revanced_hide_remix_button"),
|
||||||
|
|
|
@ -57,7 +57,9 @@ object HideAutoplayButtonPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_autoplay_button"))
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_autoplay_button")
|
||||||
|
)
|
||||||
|
|
||||||
LayoutConstructorFingerprint.result?.mutableMethod?.apply {
|
LayoutConstructorFingerprint.result?.mutableMethod?.apply {
|
||||||
val layoutGenMethodInstructions = implementation!!.instructions
|
val layoutGenMethodInstructions = implementation!!.instructions
|
||||||
|
|
|
@ -48,7 +48,9 @@ object HideCaptionsButtonPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_captions_button"))
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_captions_button")
|
||||||
|
)
|
||||||
|
|
||||||
val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod
|
val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,19 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
dependencies = [
|
dependencies = [
|
||||||
IntegrationsPatch::class,
|
IntegrationsPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
AddResourcesPatch::class
|
AddResourcesPatch::class,
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage("com.google.android.youtube")
|
CompatiblePackage("com.google.android.youtube"),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
object HideCastButtonPatch : BytecodePatch() {
|
object HideCastButtonPatch : BytecodePatch(emptySet()) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_cast_button"))
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_cast_button")
|
||||||
|
)
|
||||||
|
|
||||||
val buttonClass = context.findClass("MediaRouteButton")
|
val buttonClass = context.findClass("MediaRouteButton")
|
||||||
?: throw PatchException("MediaRouteButton class not found.")
|
?: throw PatchException("MediaRouteButton class not found.")
|
||||||
|
@ -38,7 +40,7 @@ object HideCastButtonPatch : BytecodePatch() {
|
||||||
"""
|
"""
|
||||||
invoke-static {p1}, Lapp/revanced/integrations/youtube/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I
|
invoke-static {p1}, Lapp/revanced/integrations/youtube/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I
|
||||||
move-result p1
|
move-result p1
|
||||||
"""
|
""",
|
||||||
)
|
)
|
||||||
} ?: throw PatchException("setVisibility method not found.")
|
} ?: throw PatchException("setVisibility method not found.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||||
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.*
|
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.*
|
||||||
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT
|
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT
|
||||||
|
@ -24,7 +25,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
IntegrationsPatch::class,
|
IntegrationsPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
ResolvePivotBarFingerprintsPatch::class,
|
ResolvePivotBarFingerprintsPatch::class,
|
||||||
AddResourcesPatch::class
|
AddResourcesPatch::class,
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
|
@ -42,14 +43,14 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
"19.02.39",
|
"19.02.39",
|
||||||
"19.03.35",
|
"19.03.35",
|
||||||
"19.03.36",
|
"19.03.36",
|
||||||
"19.04.37"
|
"19.04.37",
|
||||||
]
|
],
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object NavigationButtonsPatch : BytecodePatch(
|
object NavigationButtonsPatch : BytecodePatch(
|
||||||
setOf(AddCreateButtonViewFingerprint)
|
setOf(AddCreateButtonViewFingerprint),
|
||||||
) {
|
) {
|
||||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;"
|
"Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;"
|
||||||
|
@ -57,17 +58,18 @@ object NavigationButtonsPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
key = "revanced_navigation_buttons_preference_screen",
|
key = "revanced_navigation_buttons_screen",
|
||||||
|
sorting = Sorting.UNSORTED,
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_hide_home_button"),
|
SwitchPreference("revanced_hide_home_button"),
|
||||||
SwitchPreference("revanced_hide_shorts_button"),
|
SwitchPreference("revanced_hide_shorts_button"),
|
||||||
SwitchPreference("revanced_hide_subscriptions_button"),
|
|
||||||
SwitchPreference("revanced_hide_create_button"),
|
SwitchPreference("revanced_hide_create_button"),
|
||||||
|
SwitchPreference("revanced_hide_subscriptions_button"),
|
||||||
SwitchPreference("revanced_switch_create_with_notifications_button"),
|
SwitchPreference("revanced_switch_create_with_notifications_button"),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -82,14 +84,14 @@ object NavigationButtonsPatch : BytecodePatch(
|
||||||
if (!it.resolve(
|
if (!it.resolve(
|
||||||
context,
|
context,
|
||||||
initializeButtonsResult.mutableMethod,
|
initializeButtonsResult.mutableMethod,
|
||||||
initializeButtonsResult.mutableClass
|
initializeButtonsResult.mutableClass,
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
) {
|
||||||
throw it.exception
|
throw it.exception
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.map { it.result!!.scanResult.patternScanResult!! }
|
.map { it.result!!.scanResult.patternScanResult!! }
|
||||||
|
|
||||||
|
|
||||||
val enumScanResult = fingerprintResults[0]
|
val enumScanResult = fingerprintResults[0]
|
||||||
val buttonViewResult = fingerprintResults[1]
|
val buttonViewResult = fingerprintResults[1]
|
||||||
|
|
||||||
|
@ -108,7 +110,7 @@ object NavigationButtonsPatch : BytecodePatch(
|
||||||
// Inject bottom to top to not mess up the indices
|
// Inject bottom to top to not mess up the indices
|
||||||
mapOf(
|
mapOf(
|
||||||
buttonHook to buttonHookInsertIndex,
|
buttonHook to buttonHookInsertIndex,
|
||||||
enumHook to enumHookInsertIndex
|
enumHook to enumHookInsertIndex,
|
||||||
).forEach { (hook, insertIndex) ->
|
).forEach { (hook, insertIndex) ->
|
||||||
initializeButtonsResult.mutableMethod.injectHook(hook, insertIndex)
|
initializeButtonsResult.mutableMethod.injectHook(hook, insertIndex)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +133,7 @@ object NavigationButtonsPatch : BytecodePatch(
|
||||||
"""
|
"""
|
||||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->switchCreateWithNotificationButton()Z
|
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->switchCreateWithNotificationButton()Z
|
||||||
move-result v$conditionRegister
|
move-result v$conditionRegister
|
||||||
"""
|
""",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} ?: throw AddCreateButtonViewFingerprint.exception
|
} ?: throw AddCreateButtonViewFingerprint.exception
|
||||||
|
@ -141,9 +143,10 @@ object NavigationButtonsPatch : BytecodePatch(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
InitializeButtonsFingerprint.result!!.let {
|
InitializeButtonsFingerprint.result!!.let {
|
||||||
if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass))
|
if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass)) {
|
||||||
throw PivotBarCreateButtonViewFingerprint.exception
|
throw PivotBarCreateButtonViewFingerprint.exception
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PivotBarCreateButtonViewFingerprint.result!!.apply {
|
PivotBarCreateButtonViewFingerprint.result!!.apply {
|
||||||
val insertIndex = scanResult.patternScanResult!!.endIndex
|
val insertIndex = scanResult.patternScanResult!!.endIndex
|
||||||
|
|
|
@ -52,7 +52,9 @@ object HidePlayerButtonsPatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_player_buttons"))
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_player_buttons")
|
||||||
|
)
|
||||||
|
|
||||||
PlayerControlsVisibilityModelFingerprint.result?.apply {
|
PlayerControlsVisibilityModelFingerprint.result?.apply {
|
||||||
val callIndex = scanResult.patternScanResult!!.endIndex
|
val callIndex = scanResult.patternScanResult!!.endIndex
|
||||||
|
|
|
@ -21,7 +21,9 @@ internal object AlbumCardsResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_album_cards"))
|
SettingsPatch.PreferenceScreen.FEED.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_album_cards")
|
||||||
|
)
|
||||||
|
|
||||||
albumCardId = ResourceMappingPatch.resourceMappings.single {
|
albumCardId = ResourceMappingPatch.resourceMappings.single {
|
||||||
it.type == "layout" && it.name == "album_card"
|
it.type == "layout" && it.name == "album_card"
|
||||||
|
|
|
@ -21,7 +21,9 @@ internal object BreakingNewsResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_breaking_news"))
|
SettingsPatch.PreferenceScreen.FEED.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_breaking_news")
|
||||||
|
)
|
||||||
|
|
||||||
horizontalCardListId = ResourceMappingPatch.resourceMappings.single {
|
horizontalCardListId = ResourceMappingPatch.resourceMappings.single {
|
||||||
it.type == "layout" && it.name == "horizontal_card_list"
|
it.type == "layout" && it.name == "horizontal_card_list"
|
||||||
|
|
|
@ -47,9 +47,9 @@ object CommentsPatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
"revanced_comments_preference_screen",
|
"revanced_comments_screen",
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_hide_comments_section"),
|
SwitchPreference("revanced_hide_comments_section"),
|
||||||
SwitchPreference("revanced_hide_preview_comment")
|
SwitchPreference("revanced_hide_preview_comment")
|
||||||
|
|
|
@ -21,7 +21,9 @@ internal object CrowdfundingBoxResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_crowdfunding_box"))
|
SettingsPatch.PreferenceScreen.FEED.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_crowdfunding_box")
|
||||||
|
)
|
||||||
|
|
||||||
crowdfundingBoxId = ResourceMappingPatch.resourceMappings.single {
|
crowdfundingBoxId = ResourceMappingPatch.resourceMappings.single {
|
||||||
it.type == "layout" && it.name == "donation_companion"
|
it.type == "layout" && it.name == "donation_companion"
|
||||||
|
|
|
@ -23,7 +23,9 @@ internal object HideEndscreenCardsResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_endscreen_cards"))
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_endscreen_cards")
|
||||||
|
)
|
||||||
|
|
||||||
fun findEndscreenResourceId(name: String) = ResourceMappingPatch.resourceMappings.single {
|
fun findEndscreenResourceId(name: String) = ResourceMappingPatch.resourceMappings.single {
|
||||||
it.type == "layout" && it.name == "endscreen_element_layout_$name"
|
it.type == "layout" && it.name == "endscreen_element_layout_$name"
|
||||||
|
|
|
@ -18,9 +18,9 @@ internal object HideFilterBarResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.FEED.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
key = "revanced_hide_filter_bar_preference",
|
key = "revanced_hide_filter_bar_screen",
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_hide_filter_bar_feed_in_feed"),
|
SwitchPreference("revanced_hide_filter_bar_feed_in_feed"),
|
||||||
SwitchPreference("revanced_hide_filter_bar_feed_in_search"),
|
SwitchPreference("revanced_hide_filter_bar_feed_in_search"),
|
||||||
|
|
|
@ -22,7 +22,9 @@ internal object HideFloatingMicrophoneButtonResourcePatch : ResourcePatch() {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference("revanced_hide_floating_microphone_button"))
|
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_floating_microphone_button")
|
||||||
|
)
|
||||||
|
|
||||||
fabButtonId = ResourceMappingPatch.resourceMappings.find { it.type == "id" && it.name == "fab" }?.id
|
fabButtonId = ResourceMappingPatch.resourceMappings.find { it.type == "id" && it.name == "fab" }?.id
|
||||||
?: throw PatchException("Can not find required fab button resource id")
|
?: throw PatchException("Can not find required fab button resource id")
|
||||||
|
|
|
@ -45,7 +45,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch(
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
SwitchPreference("revanced_disable_fullscreen_ambient_mode")
|
SwitchPreference("revanced_disable_fullscreen_ambient_mode")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||||
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||||
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
|
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
|
||||||
|
@ -19,7 +21,6 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverl
|
||||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
|
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
|
||||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
|
|
||||||
import app.revanced.util.exception
|
import app.revanced.util.exception
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
|
@ -31,11 +32,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
dependencies = [
|
dependencies = [
|
||||||
LithoFilterPatch::class,
|
LithoFilterPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
AddResourcesPatch::class
|
AddResourcesPatch::class,
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
"com.google.android.youtube", [
|
"com.google.android.youtube",
|
||||||
|
[
|
||||||
"18.32.39",
|
"18.32.39",
|
||||||
"18.37.36",
|
"18.37.36",
|
||||||
"18.38.44",
|
"18.38.44",
|
||||||
|
@ -48,14 +50,14 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
"19.02.39",
|
"19.02.39",
|
||||||
"19.03.35",
|
"19.03.35",
|
||||||
"19.03.36",
|
"19.03.36",
|
||||||
"19.04.37"
|
"19.04.37",
|
||||||
]
|
],
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object HideLayoutComponentsPatch : BytecodePatch(
|
object HideLayoutComponentsPatch : BytecodePatch(
|
||||||
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint)
|
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint),
|
||||||
) {
|
) {
|
||||||
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/integrations/youtube/patches/components/LayoutComponentsFilter;"
|
"Lapp/revanced/integrations/youtube/patches/components/LayoutComponentsFilter;"
|
||||||
|
@ -64,59 +66,68 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||||
private const val CUSTOM_FILTER_CLASS_NAME =
|
private const val CUSTOM_FILTER_CLASS_NAME =
|
||||||
"Lapp/revanced/integrations/youtube/patches/components/CustomFilter;"
|
"Lapp/revanced/integrations/youtube/patches/components/CustomFilter;"
|
||||||
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
|
||||||
SwitchPreference("revanced_hide_gray_separator"),
|
|
||||||
SwitchPreference("revanced_hide_join_membership_button"),
|
|
||||||
SwitchPreference("revanced_hide_channel_watermark"),
|
|
||||||
SwitchPreference("revanced_hide_for_you_shelf"),
|
|
||||||
SwitchPreference("revanced_hide_notify_me_button"),
|
|
||||||
SwitchPreference("revanced_hide_timed_reactions"),
|
|
||||||
SwitchPreference("revanced_hide_search_result_recommendations"),
|
|
||||||
SwitchPreference("revanced_hide_search_result_shelf_header"),
|
|
||||||
SwitchPreference("revanced_hide_channel_guidelines"),
|
|
||||||
SwitchPreference("revanced_hide_expandable_chip"),
|
|
||||||
SwitchPreference("revanced_hide_video_quality_menu_footer"),
|
|
||||||
SwitchPreference("revanced_hide_chapters"),
|
|
||||||
SwitchPreference("revanced_hide_community_posts"),
|
|
||||||
SwitchPreference("revanced_hide_compact_banner"),
|
|
||||||
SwitchPreference("revanced_hide_movies_section"),
|
|
||||||
SwitchPreference("revanced_hide_feed_survey"),
|
|
||||||
SwitchPreference("revanced_hide_community_guidelines"),
|
|
||||||
SwitchPreference("revanced_hide_subscribers_community_guidelines"),
|
|
||||||
SwitchPreference("revanced_hide_channel_member_shelf"),
|
|
||||||
SwitchPreference("revanced_hide_emergency_box"),
|
|
||||||
SwitchPreference("revanced_hide_info_panels"),
|
|
||||||
SwitchPreference("revanced_hide_medical_panels"),
|
|
||||||
SwitchPreference("revanced_hide_channel_bar"),
|
SwitchPreference("revanced_hide_channel_bar"),
|
||||||
SwitchPreference("revanced_hide_quick_actions"),
|
SwitchPreference("revanced_hide_channel_guidelines"),
|
||||||
SwitchPreference("revanced_hide_related_videos"),
|
SwitchPreference("revanced_hide_channel_member_shelf"),
|
||||||
SwitchPreference("revanced_hide_image_shelf"),
|
SwitchPreference("revanced_hide_channel_watermark"),
|
||||||
SwitchPreference("revanced_hide_latest_posts_ads"),
|
|
||||||
SwitchPreference("revanced_hide_mix_playlists"),
|
|
||||||
SwitchPreference("revanced_hide_artist_cards"),
|
|
||||||
SwitchPreference("revanced_hide_chips_shelf"),
|
SwitchPreference("revanced_hide_chips_shelf"),
|
||||||
app.revanced.patches.shared.misc.settings.preference.PreferenceScreen(
|
SwitchPreference("revanced_hide_community_guidelines"),
|
||||||
"revanced_hide_description_components_preference_screen",
|
PreferenceScreen(
|
||||||
|
key = "revanced_hide_description_components_screen",
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
|
SwitchPreference("revanced_hide_chapters"),
|
||||||
SwitchPreference("revanced_hide_info_cards_section"),
|
SwitchPreference("revanced_hide_info_cards_section"),
|
||||||
SwitchPreference("revanced_hide_game_section"),
|
SwitchPreference("revanced_hide_game_section"),
|
||||||
SwitchPreference("revanced_hide_music_section"),
|
SwitchPreference("revanced_hide_music_section"),
|
||||||
SwitchPreference("revanced_hide_podcast_section"),
|
SwitchPreference("revanced_hide_podcast_section"),
|
||||||
SwitchPreference("revanced_hide_transcript_section"),
|
SwitchPreference("revanced_hide_transcript_section"),
|
||||||
)
|
|
||||||
),
|
),
|
||||||
app.revanced.patches.shared.misc.settings.preference.PreferenceScreen(
|
),
|
||||||
"revanced_custom_filter_preference_screen",
|
SwitchPreference("revanced_hide_emergency_box"),
|
||||||
|
SwitchPreference("revanced_hide_expandable_chip"),
|
||||||
|
SwitchPreference("revanced_hide_info_panels"),
|
||||||
|
SwitchPreference("revanced_hide_medical_panels"),
|
||||||
|
SwitchPreference("revanced_hide_quick_actions"),
|
||||||
|
SwitchPreference("revanced_hide_related_videos"),
|
||||||
|
SwitchPreference("revanced_hide_subscribers_community_guidelines"),
|
||||||
|
SwitchPreference("revanced_hide_timed_reactions"),
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingsPatch.PreferenceScreen.FEED.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_artist_cards"),
|
||||||
|
SwitchPreference("revanced_hide_community_posts"),
|
||||||
|
SwitchPreference("revanced_hide_compact_banner"),
|
||||||
|
SwitchPreference("revanced_hide_feed_survey"),
|
||||||
|
SwitchPreference("revanced_hide_for_you_shelf"),
|
||||||
|
SwitchPreference("revanced_hide_image_shelf"),
|
||||||
|
SwitchPreference("revanced_hide_join_membership_button"),
|
||||||
|
SwitchPreference("revanced_hide_latest_posts_ads"),
|
||||||
|
SwitchPreference("revanced_hide_mix_playlists"),
|
||||||
|
SwitchPreference("revanced_hide_movies_section"),
|
||||||
|
SwitchPreference("revanced_hide_notify_me_button"),
|
||||||
|
SwitchPreference("revanced_hide_search_result_recommendations"),
|
||||||
|
SwitchPreference("revanced_hide_search_result_shelf_header"),
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_gray_separator"),
|
||||||
|
PreferenceScreen(
|
||||||
|
key = "revanced_custom_filter_screen",
|
||||||
|
sorting = Sorting.UNSORTED,
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_custom_filter"),
|
SwitchPreference("revanced_custom_filter"),
|
||||||
// TODO: This should be a dynamic ListPreference, which does not exist yet
|
// TODO: This should be a dynamic ListPreference, which does not exist yet
|
||||||
TextPreference("revanced_custom_filter_strings", inputType = InputType.TEXT_MULTI_LINE)
|
TextPreference("revanced_custom_filter_strings", inputType = InputType.TEXT_MULTI_LINE),
|
||||||
)
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
|
||||||
|
SwitchPreference("revanced_hide_video_quality_menu_footer"),
|
||||||
)
|
)
|
||||||
|
|
||||||
LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
|
LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
|
||||||
|
@ -136,14 +147,15 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||||
val byteBufferRegister = getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD
|
val byteBufferRegister = getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
consumeByteBufferIndex, """
|
consumeByteBufferIndex,
|
||||||
|
"""
|
||||||
invoke-static {v$conversionContextRegister, v$byteBufferRegister}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
|
invoke-static {v$conversionContextRegister, v$byteBufferRegister}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
|
||||||
move-result v0 # Conveniently same register happens to be free.
|
move-result v0 # Conveniently same register happens to be free.
|
||||||
if-nez v0, :return_empty_component
|
if-nez v0, :return_empty_component
|
||||||
""", ExternalLabel("return_empty_component", returnEmptyComponentInstruction)
|
""",
|
||||||
|
ExternalLabel("return_empty_component", returnEmptyComponentInstruction),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
} ?: throw ParseElementFromBufferFingerprint.exception
|
} ?: throw ParseElementFromBufferFingerprint.exception
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -157,10 +169,11 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||||
|
|
||||||
removeInstruction(index)
|
removeInstruction(index)
|
||||||
addInstructions(
|
addInstructions(
|
||||||
index, """
|
index,
|
||||||
|
"""
|
||||||
invoke-static {}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->showWatermark()Z
|
invoke-static {}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->showWatermark()Z
|
||||||
move-result p2
|
move-result p2
|
||||||
"""
|
""",
|
||||||
)
|
)
|
||||||
} ?: throw ShowWatermarkFingerprint.exception
|
} ?: throw ShowWatermarkFingerprint.exception
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue