mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 09:53:55 +01:00
Compare commits
166 Commits
v4.0.2-dev
...
v4.7.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b7e12f995 | ||
|
|
2e59965bb5 | ||
|
|
426f405407 | ||
|
|
f85f518fc9 | ||
|
|
f3972d313f | ||
|
|
04a72d52de | ||
|
|
be76e49a8b | ||
|
|
fa1c616014 | ||
|
|
e97aaf4aae | ||
|
|
92c90ec208 | ||
|
|
b4e8beb8ec | ||
|
|
f2fe0d5c6f | ||
|
|
3d3197701c | ||
|
|
1ac612798b | ||
|
|
e1ed1aee69 | ||
|
|
795ccac990 | ||
|
|
da55410a2b | ||
|
|
e7983411a7 | ||
|
|
182748cb16 | ||
|
|
122f04219f | ||
|
|
80763bcef6 | ||
|
|
b80bb8969c | ||
|
|
2a86a670f0 | ||
|
|
dba37b834d | ||
|
|
3ad4eb8dbc | ||
|
|
0e88306f3f | ||
|
|
87cb63f2e7 | ||
|
|
0fead38701 | ||
|
|
19a31019c2 | ||
|
|
61758414c2 | ||
|
|
b4ee8b6da4 | ||
|
|
e86e3d88cf | ||
|
|
8cf444962c | ||
|
|
48bf632dbe | ||
|
|
03e91d4251 | ||
|
|
8caf70719e | ||
|
|
2f28e95252 | ||
|
|
d819e7bbe9 | ||
|
|
fef5f35788 | ||
|
|
80034bc70a | ||
|
|
c40911a815 | ||
|
|
1a53a93cd2 | ||
|
|
2e68c65c9f | ||
|
|
6f8d92827b | ||
|
|
ab2260acfd | ||
|
|
9b3c060acb | ||
|
|
bbc4a6bfa0 | ||
|
|
4df9b9d5b1 | ||
|
|
eebf72f476 | ||
|
|
a27296223f | ||
|
|
77a9a56e2d | ||
|
|
3df3441385 | ||
|
|
86def3efea | ||
|
|
bc9a612824 | ||
|
|
f378ddc6d5 | ||
|
|
7f852e8f32 | ||
|
|
5b7b134d73 | ||
|
|
df9361ea2b | ||
|
|
8c226c4bdc | ||
|
|
c87f8a376d | ||
|
|
cb4b6514db | ||
|
|
5a172c9deb | ||
|
|
a9f418a19f | ||
|
|
5b0360c067 | ||
|
|
069f26de20 | ||
|
|
46ff5b8b92 | ||
|
|
69721509bf | ||
|
|
0bd0c827a4 | ||
|
|
cbae1383ca | ||
|
|
2679fad25f | ||
|
|
08c4468ff1 | ||
|
|
7c981f6759 | ||
|
|
2fcd786cc7 | ||
|
|
60ace80cbd | ||
|
|
e6a468cf7a | ||
|
|
38392de4a1 | ||
|
|
bc8bc8c798 | ||
|
|
76805e4f31 | ||
|
|
d18719c59c | ||
|
|
743a02f983 | ||
|
|
8306f70fd1 | ||
|
|
5d71f23471 | ||
|
|
122ef68a4b | ||
|
|
b2a7a65bc0 | ||
|
|
32139f151b | ||
|
|
e55364ca87 | ||
|
|
5cca42121a | ||
|
|
7b0365360e | ||
|
|
7f8b7c08b2 | ||
|
|
058acff28c | ||
|
|
060b2c2323 | ||
|
|
bcce7bee9a | ||
|
|
d3f83230f8 | ||
|
|
0ad377bb4c | ||
|
|
9917ddd9c1 | ||
|
|
951ebc54ca | ||
|
|
3b4b21ff2e | ||
|
|
2f2ad3e584 | ||
|
|
f9ae1a46d2 | ||
|
|
e386313deb | ||
|
|
f2edae2ac1 | ||
|
|
c153979981 | ||
|
|
2fe9060944 | ||
|
|
212a94cbb3 | ||
|
|
16eee2f03f | ||
|
|
4937fa5fbd | ||
|
|
a6f5dd933f | ||
|
|
97c4682ccc | ||
|
|
6742cd9232 | ||
|
|
5b2cc10adb | ||
|
|
dbad6252fb | ||
|
|
0f7ed841d1 | ||
|
|
d33d7d8f35 | ||
|
|
3200da8657 | ||
|
|
348e42a374 | ||
|
|
cbbac445b6 | ||
|
|
1593d1352a | ||
|
|
c6fedaa7bc | ||
|
|
d070aebec4 | ||
|
|
d583256f06 | ||
|
|
fc67d284f7 | ||
|
|
d3f3f81b75 | ||
|
|
8e8600c7c3 | ||
|
|
ea33863083 | ||
|
|
a6d8e4210f | ||
|
|
1e3356808d | ||
|
|
43359b95eb | ||
|
|
afe7f0605e | ||
|
|
8916789f7a | ||
|
|
0d14aa1191 | ||
|
|
376dda6e81 | ||
|
|
ff8b58b645 | ||
|
|
f4b888be56 | ||
|
|
e775bc2cae | ||
|
|
5c566753a8 | ||
|
|
968ebf9f50 | ||
|
|
75c510d876 | ||
|
|
72528cb2f1 | ||
|
|
81d79111cf | ||
|
|
33036092b4 | ||
|
|
f5f88092b6 | ||
|
|
0434d8812b | ||
|
|
ec38b8e51c | ||
|
|
96f9b73c74 | ||
|
|
1502fe1f7f | ||
|
|
824d094394 | ||
|
|
010471a745 | ||
|
|
3343b5cb12 | ||
|
|
1bf9582437 | ||
|
|
ea09d4b520 | ||
|
|
53b29ea270 | ||
|
|
fd11e2b969 | ||
|
|
65a32ee52e | ||
|
|
7b2e32d88c | ||
|
|
f18edb262d | ||
|
|
8b1cdd5c6a | ||
|
|
3bd41fb67f | ||
|
|
19a9d113d9 | ||
|
|
61ee51b856 | ||
|
|
2c50c25a36 | ||
|
|
f5e7bf6e98 | ||
|
|
bba35d5cb5 | ||
|
|
1be4f4cf55 | ||
|
|
047069ca8a | ||
|
|
7bfdd8bc59 | ||
|
|
b8cb735291 |
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
|
||||
@@ -71,7 +71,7 @@ body:
|
||||
Before creating a new feature request, please keep the following in mind:
|
||||
|
||||
- **Do not submit a duplicate feature request**: You can review existing feature requests [here](https://github.com/ReVanced/revanced-patches/labels/Feature%20request).
|
||||
- **Review the contribution guidelines**: Make sure your bug report adheres to it. You can find the guidelines [here](https://github.com/ReVanced/revanced-patches/blob/main/CONTRIBUTING.md).
|
||||
- **Review the contribution guidelines**: Make sure your feature request adheres to it. You can find the guidelines [here](https://github.com/ReVanced/revanced-patches/blob/main/CONTRIBUTING.md).
|
||||
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
|
||||
- type: textarea
|
||||
attributes:
|
||||
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
|
||||
34
.github/workflows/pull_strings.yml
vendored
Normal file
34
.github/workflows/pull_strings.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Pull strings
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: 0 0 1 * *
|
||||
|
||||
jobs:
|
||||
pull:
|
||||
name: Pull strings
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Pull strings
|
||||
uses: crowdin/github-action@v1
|
||||
with:
|
||||
config: crowdin.yml
|
||||
download_translations: true
|
||||
localization_branch_name: feat/translations
|
||||
create_pull_request: true
|
||||
pull_request_title: "chore: Sync translations"
|
||||
pull_request_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)"
|
||||
pull_request_base_branch_name: "dev"
|
||||
commit_message: "chore: Sync translations"
|
||||
github_user_name: revanced-bot
|
||||
github_user_email: github@revanced.app
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
27
.github/workflows/push_strings.yml
vendored
Normal file
27
.github/workflows/push_strings.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Push strings
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- /src/main/resources/addresources/values/strings.xml
|
||||
|
||||
jobs:
|
||||
push:
|
||||
name: Push strings
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Push strings
|
||||
uses: crowdin/github-action@v1
|
||||
with:
|
||||
config: crowdin.yml
|
||||
upload_sources: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
@@ -6,10 +6,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@@ -41,6 +37,13 @@ jobs:
|
||||
- name: Install dependencies
|
||||
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
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
{
|
||||
"assets": [
|
||||
{
|
||||
"path": "build/libs/*.jar"
|
||||
"path": "build/libs/revanced-patches*"
|
||||
},
|
||||
{
|
||||
"path": "patches.json"
|
||||
|
||||
486
CHANGELOG.md
486
CHANGELOG.md
@@ -1,3 +1,489 @@
|
||||
# [4.7.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.7...v4.7.0-dev.8) (2024-04-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Hide tagged products, hide search suggestions ([#3019](https://github.com/ReVanced/revanced-patches/issues/3019)) ([e0d2fe5](https://github.com/ReVanced/revanced-patches/commit/e0d2fe5bd2e681b9a5252a8e4ad582cc019b1606))
|
||||
|
||||
# [4.7.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.6...v4.7.0-dev.7) (2024-04-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Hide playables ([8423515](https://github.com/ReVanced/revanced-patches/commit/842351548baa33737db09be1cbca9f87c1951341))
|
||||
|
||||
# [4.7.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.5...v4.7.0-dev.6) (2024-04-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Hide `Shop`, `Location` and `Save sound to playlist` buttons ([#3018](https://github.com/ReVanced/revanced-patches/issues/3018)) ([5210ac4](https://github.com/ReVanced/revanced-patches/commit/5210ac431c191987264865bf8e789ea9f3fdd360))
|
||||
|
||||
# [4.7.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.4...v4.7.0-dev.5) (2024-04-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide Shorts components:** Correctly hide Shorts if navigation tab is changed using device back button ([#3007](https://github.com/ReVanced/revanced-patches/issues/3007)) ([e5848e9](https://github.com/ReVanced/revanced-patches/commit/e5848e99c4cc838595164ef673a77fe60d28086b))
|
||||
|
||||
# [4.7.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.3...v4.7.0-dev.4) (2024-04-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Amazon:** Add `Always allow deep-linking` patch ([#3000](https://github.com/ReVanced/revanced-patches/issues/3000)) ([a92b7fb](https://github.com/ReVanced/revanced-patches/commit/a92b7fb43c8b1b45577360cdc6d883fe2815c2f2))
|
||||
* **Twitter:** Add `Sanitize sharing links` patch ([#3003](https://github.com/ReVanced/revanced-patches/issues/3003)) ([186b887](https://github.com/ReVanced/revanced-patches/commit/186b8874157eef1b882b05d491ba1d4ca2809535))
|
||||
|
||||
# [4.7.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.2...v4.7.0-dev.3) (2024-04-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Tumblr - Fix old versions:** Improve reliability by removing remnances of Tumblr Live ([#2988](https://github.com/ReVanced/revanced-patches/issues/2988)) ([897b4db](https://github.com/ReVanced/revanced-patches/commit/897b4dbce984270ae1fd7de5bd30bd05153e45f2))
|
||||
|
||||
# [4.7.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.1...v4.7.0-dev.2) (2024-04-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Strava - Unlock subscription:** Remove compatible version constraint ([80a5599](https://github.com/ReVanced/revanced-patches/commit/80a55991683d7b22626224fa2935a5bf9bfcbfee))
|
||||
|
||||
# [4.7.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.3...v4.7.0-dev.1) (2024-04-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Add option to hide horizontal shelves ([#2951](https://github.com/ReVanced/revanced-patches/issues/2951)) ([9ae0650](https://github.com/ReVanced/revanced-patches/commit/9ae0650c0005d882299996aa442410bab4261395))
|
||||
|
||||
## [4.6.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.2...v4.6.1-dev.3) (2024-04-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - GmsCore support:** Prompt to disable battery optimizations, if not done already ([#2958](https://github.com/ReVanced/revanced-patches/issues/2958)) ([82acb84](https://github.com/ReVanced/revanced-patches/commit/82acb84b5f6ff0722a2eb080b53da9dd3622502f))
|
||||
|
||||
## [4.6.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.1...v4.6.1-dev.2) (2024-04-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide load more button:** Include patch with `Hide layout components`, and hide button only in search feed ([#2959](https://github.com/ReVanced/revanced-patches/issues/2959)) ([b007e8e](https://github.com/ReVanced/revanced-patches/commit/b007e8e06a3afad79b40bec1c6a14604f059049c))
|
||||
|
||||
## [4.6.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.6.0...v4.6.1-dev.1) (2024-04-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Player flyout menu:** Add hide Lock screen menu ([#2985](https://github.com/ReVanced/revanced-patches/issues/2985)) ([308de4a](https://github.com/ReVanced/revanced-patches/commit/308de4a63ca99b8d30d6b3242f98d6f0e2aefb37))
|
||||
|
||||
# [4.6.0](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.6.0) (2024-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([dc96942](https://github.com/ReVanced/revanced-patches/commit/dc969422b5d50f21e6ea7a64b67dfc650fee6e36))
|
||||
* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([2954ba7](https://github.com/ReVanced/revanced-patches/commit/2954ba78d21d77308404961f79234bbec606d42e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2fde60e](https://github.com/ReVanced/revanced-patches/commit/2fde60eceb0a96fa857c32cd55c1fd7fe776a679))
|
||||
|
||||
# [4.6.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.2...v4.6.0-dev.1) (2024-03-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2fde60e](https://github.com/ReVanced/revanced-patches/commit/2fde60eceb0a96fa857c32cd55c1fd7fe776a679))
|
||||
|
||||
## [4.5.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.1...v4.5.1-dev.2) (2024-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([dc96942](https://github.com/ReVanced/revanced-patches/commit/dc969422b5d50f21e6ea7a64b67dfc650fee6e36))
|
||||
|
||||
## [4.5.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.5.1-dev.1) (2024-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([2954ba7](https://github.com/ReVanced/revanced-patches/commit/2954ba78d21d77308404961f79234bbec606d42e))
|
||||
|
||||
# [4.5.0](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0) (2024-03-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949))
|
||||
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730))
|
||||
|
||||
# [4.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.0-dev.1...v4.5.0-dev.2) (2024-03-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730))
|
||||
|
||||
# [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949))
|
||||
|
||||
# [4.4.0](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([395ccda](https://github.com/ReVanced/revanced-patches/commit/395ccda7b9218c522c7ca0f99f75a12036d3e3f3))
|
||||
* **YouTube - Client spoof:** Spoof all user agents ([44a8a13](https://github.com/ReVanced/revanced-patches/commit/44a8a1399897caaff3ff45db8549ddedb2f01b68))
|
||||
* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([6d88cb4](https://github.com/ReVanced/revanced-patches/commit/6d88cb49ec739700866290babcba5fb3032dbced))
|
||||
* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([9f50470](https://github.com/ReVanced/revanced-patches/commit/9f50470bf6582fe2f20a903a97bf66c41f296fb2))
|
||||
* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([8378c84](https://github.com/ReVanced/revanced-patches/commit/8378c8481634a63a5568480475757e64b7ec466e))
|
||||
* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([33ea122](https://github.com/ReVanced/revanced-patches/commit/33ea12228c2ae5dcadf3e7c7016d4bf6006d899a))
|
||||
* **YouTube:** Move setting to correct screen ([a16eda8](https://github.com/ReVanced/revanced-patches/commit/a16eda864515612d3a6b846082844df15eb49f56))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Instagram - Hide timeline ads:** Make compatible with latest versions ([a212f29](https://github.com/ReVanced/revanced-patches/commit/a212f29bd33bb5e10f024e058d26e20ee926190b))
|
||||
* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([7a25791](https://github.com/ReVanced/revanced-patches/commit/7a25791d53530b1236896b2c3d6275ee7556e8b7))
|
||||
* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([0785819](https://github.com/ReVanced/revanced-patches/commit/0785819dd5ad487c778b5baf09004cdab3687184))
|
||||
* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([10afc8c](https://github.com/ReVanced/revanced-patches/commit/10afc8cc71ff29fea4937fb12fd3d1edf9c581f5))
|
||||
* **YouTube - External downloader:** Add ability to use in-app download button ([d900011](https://github.com/ReVanced/revanced-patches/commit/d9000113a905c14f8409aa75008f1ef6a1aecd0c))
|
||||
* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([5916204](https://github.com/ReVanced/revanced-patches/commit/59162042b0a68edf7f94a3c21f838dada3c3f9c3))
|
||||
* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([2df0892](https://github.com/ReVanced/revanced-patches/commit/2df0892682406e67283c4aeaacebf8f222029833))
|
||||
* **YouTube - Hide Shorts components:** Hide sound metadata label ([ea7d1e0](https://github.com/ReVanced/revanced-patches/commit/ea7d1e0d08cc245117ffe8ad0df3c31c5e87f739))
|
||||
* **YouTube - Hide Shorts components:** Hide title and full video link label ([e7b64e1](https://github.com/ReVanced/revanced-patches/commit/e7b64e154e7fb8edd0037f5e171f4aa3ed9017f8))
|
||||
* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([497c067](https://github.com/ReVanced/revanced-patches/commit/497c067e80e560eb125f5fc30eef9763929b4ee4))
|
||||
* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([b4c7bf4](https://github.com/ReVanced/revanced-patches/commit/b4c7bf48084184e5f031f7f5139a9a29341d8ebf))
|
||||
* **YouTube Vanced:** Remove `Hide ads` patch ([87887e4](https://github.com/ReVanced/revanced-patches/commit/87887e4163dd9e242209f4d0fefb415f9bc7ca75))
|
||||
* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([f044dde](https://github.com/ReVanced/revanced-patches/commit/f044dde054861ff16846a6be6287f86fa3afb3d8))
|
||||
|
||||
# [4.4.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.14...v4.4.0-dev.15) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([8378c84](https://github.com/ReVanced/revanced-patches/commit/8378c8481634a63a5568480475757e64b7ec466e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([497c067](https://github.com/ReVanced/revanced-patches/commit/497c067e80e560eb125f5fc30eef9763929b4ee4))
|
||||
|
||||
# [4.4.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.13...v4.4.0-dev.14) (2024-03-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([5916204](https://github.com/ReVanced/revanced-patches/commit/59162042b0a68edf7f94a3c21f838dada3c3f9c3))
|
||||
|
||||
# [4.4.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.12...v4.4.0-dev.13) (2024-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Move setting to correct screen ([a16eda8](https://github.com/ReVanced/revanced-patches/commit/a16eda864515612d3a6b846082844df15eb49f56))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([2df0892](https://github.com/ReVanced/revanced-patches/commit/2df0892682406e67283c4aeaacebf8f222029833))
|
||||
* **YouTube - Hide Shorts components:** Hide sound metadata label ([ea7d1e0](https://github.com/ReVanced/revanced-patches/commit/ea7d1e0d08cc245117ffe8ad0df3c31c5e87f739))
|
||||
* **YouTube - Hide Shorts components:** Hide title and full video link label ([e7b64e1](https://github.com/ReVanced/revanced-patches/commit/e7b64e154e7fb8edd0037f5e171f4aa3ed9017f8))
|
||||
|
||||
# [4.4.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.11...v4.4.0-dev.12) (2024-03-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([33ea122](https://github.com/ReVanced/revanced-patches/commit/33ea12228c2ae5dcadf3e7c7016d4bf6006d899a))
|
||||
|
||||
# [4.4.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.10...v4.4.0-dev.11) (2024-03-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([7a25791](https://github.com/ReVanced/revanced-patches/commit/7a25791d53530b1236896b2c3d6275ee7556e8b7))
|
||||
* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([0785819](https://github.com/ReVanced/revanced-patches/commit/0785819dd5ad487c778b5baf09004cdab3687184))
|
||||
|
||||
# [4.4.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.9...v4.4.0-dev.10) (2024-03-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([9f50470](https://github.com/ReVanced/revanced-patches/commit/9f50470bf6582fe2f20a903a97bf66c41f296fb2))
|
||||
|
||||
# [4.4.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.8...v4.4.0-dev.9) (2024-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([395ccda](https://github.com/ReVanced/revanced-patches/commit/395ccda7b9218c522c7ca0f99f75a12036d3e3f3))
|
||||
|
||||
# [4.4.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.7...v4.4.0-dev.8) (2024-03-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([10afc8c](https://github.com/ReVanced/revanced-patches/commit/10afc8cc71ff29fea4937fb12fd3d1edf9c581f5))
|
||||
|
||||
# [4.4.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.6...v4.4.0-dev.7) (2024-03-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Client spoof:** Spoof all user agents ([44a8a13](https://github.com/ReVanced/revanced-patches/commit/44a8a1399897caaff3ff45db8549ddedb2f01b68))
|
||||
|
||||
# [4.4.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.5...v4.4.0-dev.6) (2024-03-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Instagram - Hide timeline ads:** Make compatible with latest versions ([a212f29](https://github.com/ReVanced/revanced-patches/commit/a212f29bd33bb5e10f024e058d26e20ee926190b))
|
||||
|
||||
# [4.4.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.4...v4.4.0-dev.5) (2024-03-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([f044dde](https://github.com/ReVanced/revanced-patches/commit/f044dde054861ff16846a6be6287f86fa3afb3d8))
|
||||
|
||||
# [4.4.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.3...v4.4.0-dev.4) (2024-03-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([b4c7bf4](https://github.com/ReVanced/revanced-patches/commit/b4c7bf48084184e5f031f7f5139a9a29341d8ebf))
|
||||
|
||||
# [4.4.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.2...v4.4.0-dev.3) (2024-03-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([6d88cb4](https://github.com/ReVanced/revanced-patches/commit/6d88cb49ec739700866290babcba5fb3032dbced))
|
||||
|
||||
# [4.4.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.1...v4.4.0-dev.2) (2024-03-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - External downloader:** Add ability to use in-app download button ([d900011](https://github.com/ReVanced/revanced-patches/commit/d9000113a905c14f8409aa75008f1ef6a1aecd0c))
|
||||
|
||||
# [4.4.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0-dev.1) (2024-03-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Vanced:** Remove `Hide ads` patch ([87887e4](https://github.com/ReVanced/revanced-patches/commit/87887e4163dd9e242209f4d0fefb415f9bc7ca75))
|
||||
|
||||
# [4.3.0](https://github.com/ReVanced/revanced-patches/compare/v4.2.0...v4.3.0) (2024-03-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Compile DEX without debugging information ([f5df957](https://github.com/ReVanced/revanced-patches/commit/f5df9578669f71a67411bc93a25a7e8da43610d0))
|
||||
* **Override certificate pinning:** Always overwrite with a generic network security configuration ([2a842a1](https://github.com/ReVanced/revanced-patches/commit/2a842a1e14e1993eb028ae0bd1a93e227bb929a6))
|
||||
* Remove extra space from patch description ([#2780](https://github.com/ReVanced/revanced-patches/issues/2780)) ([96a3f35](https://github.com/ReVanced/revanced-patches/commit/96a3f359266ff8d16ae9ee3c6ce2f16ce67a3b93))
|
||||
* Use deprecated members to ensure backwards compatibility ([083bd40](https://github.com/ReVanced/revanced-patches/commit/083bd4009231b9612394b4496ca1d329947d6577))
|
||||
* **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))
|
||||
* **YouTube - Spoof signature:** Fix tracking such as history or watch time ([bcd8b48](https://github.com/ReVanced/revanced-patches/commit/bcd8b48e70693dac1bfcc0bf4971d6b526065b59))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **OpeningHours:** Add `Fix crash` patch ([#2697](https://github.com/ReVanced/revanced-patches/issues/2697)) ([0d011b8](https://github.com/ReVanced/revanced-patches/commit/0d011b876ecf05031a7daa54ab7e6d3506728a47))
|
||||
* Remove unnecessary description from patch ([1a89dd9](https://github.com/ReVanced/revanced-patches/commit/1a89dd9f8cd0c614055a9da97338839b77a25ed1))
|
||||
* **Sync for Reddit:** Add `Fix /s/ links` patch ([f15ef3f](https://github.com/ReVanced/revanced-patches/commit/f15ef3f63460254236185f8e22c9395db4db9465))
|
||||
* **Twitter - Unlock downloads:** Unlock GIF downloads ([d0f91c8](https://github.com/ReVanced/revanced-patches/commit/d0f91c8550592723e1252e1af2971b508591dd59))
|
||||
* **VSCO - Unlock pro:** Constrain to last working version ([6dd4a7c](https://github.com/ReVanced/revanced-patches/commit/6dd4a7c29e48c3bc517bbdd7ed160624c36c2333))
|
||||
* **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))
|
||||
* **YouTube - Change header:** Improve patch option description ([3b8bc08](https://github.com/ReVanced/revanced-patches/commit/3b8bc08d4ed3a3a0f96d2f476e5059840b9f9d9b))
|
||||
* **YouTube - Change start page:** Add more start pages ([cc1d9b7](https://github.com/ReVanced/revanced-patches/commit/cc1d9b743633c619fb6acc428e884c1c9b53e10b))
|
||||
* **YouTube - Custom branding:** Improve patch option description ([e27f56c](https://github.com/ReVanced/revanced-patches/commit/e27f56c8a34d41167b290f47280276c1c6003876))
|
||||
* **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))
|
||||
* **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.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)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Infinity for Reddit - Unlock subscription:** Do not crash by patching billing client ([7d76e2e](https://github.com/ReVanced/revanced-patches/commit/7d76e2e43c69b2b75f40a15a9147d041c77cbcd9))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **X:** Add `Hide view count` patch ([bf064ec](https://github.com/ReVanced/revanced-patches/commit/bf064ecc1d5de8b592d14d34acfa1a4314c374ba))
|
||||
* **X:** Add `Unlock downloads` patch ([2c20844](https://github.com/ReVanced/revanced-patches/commit/2c20844eaae698f185a9d321e2c70bde4b485cee))
|
||||
|
||||
# [4.2.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.1.1-dev.1...v4.2.0-dev.1) (2024-02-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **X:** Add `Hide view count` patch ([bf064ec](https://github.com/ReVanced/revanced-patches/commit/bf064ecc1d5de8b592d14d34acfa1a4314c374ba))
|
||||
* **X:** Add `Unlock downloads` patch ([2c20844](https://github.com/ReVanced/revanced-patches/commit/2c20844eaae698f185a9d321e2c70bde4b485cee))
|
||||
|
||||
## [4.1.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.1.1-dev.1) (2024-02-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Infinity for Reddit - Unlock subscription:** Do not crash by patching billing client ([7d76e2e](https://github.com/ReVanced/revanced-patches/commit/7d76e2e43c69b2b75f40a15a9147d041c77cbcd9))
|
||||
|
||||
# [4.1.0](https://github.com/ReVanced/revanced-patches/compare/v4.0.2...v4.1.0) (2024-02-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Infinity for Reddit - Unlock subscription:** Restore functionality on v7.0.0 ([bf19af9](https://github.com/ReVanced/revanced-patches/commit/bf19af99cb522f9027a4b3ae42d6258ac71758e5))
|
||||
* **YouTube:** Correctly show channel page on tablet devices ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([c7c9700](https://github.com/ReVanced/revanced-patches/commit/c7c9700d93caeae105916d33376670f525276fac))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Custom filter:** Custom filtering of the protocol buffer ([#2682](https://github.com/ReVanced/revanced-patches/issues/2682)) ([872a5b6](https://github.com/ReVanced/revanced-patches/commit/872a5b6d8969ab1569cd57ece3c400c3741049be))
|
||||
* **YouTube:** Support version `19.04.37` ([#2687](https://github.com/ReVanced/revanced-patches/issues/2687)) ([c23e023](https://github.com/ReVanced/revanced-patches/commit/c23e0233cf5c28d354132443d227b42ddc4a3dad))
|
||||
|
||||
# [4.1.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.1.0-dev.1...v4.1.0-dev.2) (2024-02-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `19.04.37` ([#2687](https://github.com/ReVanced/revanced-patches/issues/2687)) ([c23e023](https://github.com/ReVanced/revanced-patches/commit/c23e0233cf5c28d354132443d227b42ddc4a3dad))
|
||||
|
||||
# [4.1.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.0.3-dev.2...v4.1.0-dev.1) (2024-02-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Custom filter:** Custom filtering of the protocol buffer ([#2682](https://github.com/ReVanced/revanced-patches/issues/2682)) ([872a5b6](https://github.com/ReVanced/revanced-patches/commit/872a5b6d8969ab1569cd57ece3c400c3741049be))
|
||||
|
||||
## [4.0.3-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.3-dev.1...v4.0.3-dev.2) (2024-02-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Infinity for Reddit - Unlock subscription:** Restore functionality on v7.0.0 ([bf19af9](https://github.com/ReVanced/revanced-patches/commit/bf19af99cb522f9027a4b3ae42d6258ac71758e5))
|
||||
|
||||
## [4.0.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.0.2...v4.0.3-dev.1) (2024-01-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Correctly show channel page on tablet devices ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([c7c9700](https://github.com/ReVanced/revanced-patches/commit/c7c9700d93caeae105916d33376670f525276fac))
|
||||
|
||||
## [4.0.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.1...v4.0.2) (2024-01-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Twitch:** Correct patch resources to fix build ([1b63898](https://github.com/ReVanced/revanced-patches/commit/1b63898413b24693b0b737df29adcf9142963dfa))
|
||||
* **YouTube:** Do not crash on startup for root installs ([#2655](https://github.com/ReVanced/revanced-patches/issues/2655)) ([02abace](https://github.com/ReVanced/revanced-patches/commit/02abace127c9ef906c06ded9135cbba2871bd1e6))
|
||||
|
||||
## [4.0.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.2-dev.1...v4.0.2-dev.2) (2024-01-28)
|
||||
|
||||
|
||||
|
||||
@@ -64,15 +64,15 @@ This document describes how to contribute to ReVanced Patches.
|
||||
|
||||
## 📖 Resources to help you get started
|
||||
|
||||
* The [documentation](https://github.com/ReVanced/revanced-patches/tree/docs/docs) provides the fundamentals of patches
|
||||
and everything necessary to create your own patch from scratch
|
||||
* The [documentation](https://github.com/ReVanced/revanced-patcher/tree/docs/docs) contains the fundamentals
|
||||
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
|
||||
* [Issues](https://github.com/ReVanced/revanced-patches/issues) are where we keep track of bugs and feature requests
|
||||
|
||||
## 🙏 Submitting a feature request
|
||||
|
||||
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**
|
||||
> 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
|
||||
|
||||
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
|
||||
|
||||
@@ -110,7 +110,7 @@ are unaffected by this change.
|
||||
|
||||
## 📝 How to contribute
|
||||
|
||||
1. Before contributing, it is recommended to open an issue to discuss your change
|
||||
1. Before contributing, it is recommended to open an issue to discuss your change
|
||||
with the maintainers of ReVanced Patches. This will help you determine whether your change is acceptable
|
||||
and whether it is worth your time to implement it
|
||||
2. Development happens on the `dev` branch. Fork the repository and create your branch from `dev`
|
||||
|
||||
22
README.md
22
README.md
@@ -67,7 +67,7 @@ This repository contains a collection of ReVanced Patches.
|
||||
|
||||
## ❓ 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.
|
||||
|
||||
## 💪 Features
|
||||
@@ -77,11 +77,11 @@ Some of the features the patches provide are:
|
||||
* 🚫 **Block ads**: Say goodbye to ads
|
||||
* ⭐ **Customize your app**: Personalize the appearance of apps with various layouts and themes
|
||||
* 🪄 **Add new features**: Extend the functionality of apps with lots of new features
|
||||
* ⚙️ **Miscellaneous and general purpose**: Rename packages, enable debugging, disable screen capture restrictions,
|
||||
export activities, etc.
|
||||
* ⚙️ **Miscellaneous and general purpose**: Rename packages, enable debugging, disable screen capture restrictions,
|
||||
export activities, etc.
|
||||
* ✨ **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
|
||||
|
||||
@@ -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).
|
||||
|
||||
### 📃 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
|
||||
|
||||
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
|
||||
|
||||
ReVanced Patches is licensed under the GPLv3 licence. Please see the [licence 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.
|
||||
Any modifications to ReVanced Patches must also be made available under the GPL along with build & install instructions.
|
||||
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.
|
||||
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 static final field INSTANCE Lapp/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -148,6 +152,12 @@ public final class app/revanced/patches/all/telephony/sim/spoof/SpoofSimCountryP
|
||||
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Pair;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/amazon/deeplinking/DeepLinkingPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/amazon/deeplinking/DeepLinkingPatch;
|
||||
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/backdrops/misc/pro/ProUnlockPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/backdrops/misc/pro/ProUnlockPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -280,12 +290,30 @@ public final class app/revanced/patches/messenger/inputfield/patch/DisableTyping
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch;
|
||||
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/mifitness/misc/login/FixLoginPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/login/FixLoginPatch;
|
||||
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/moneymanager/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/moneymanager/UnlockProPatch;
|
||||
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/music/ad/video/HideMusicVideoAds : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/ad/video/HideMusicVideoAds;
|
||||
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/music/ad/video/MusicVideoAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/ad/video/MusicVideoAdsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -298,6 +326,12 @@ public final class app/revanced/patches/music/audio/codecs/CodecsUnlockPatch : a
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback;
|
||||
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/music/audio/exclusiveaudio/ExclusiveAudioPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -310,6 +344,12 @@ public final class app/revanced/patches/music/interaction/permanentrepeat/Perman
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch;
|
||||
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/music/interaction/permanentshuffle/PermanentShuffleTogglePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -322,6 +362,12 @@ public final class app/revanced/patches/music/layout/compactheader/CompactHeader
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/compactheader/HideCategoryBar : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/layout/compactheader/HideCategoryBar;
|
||||
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/music/layout/minimizedplayback/MinimizedPlaybackPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -406,6 +452,12 @@ public final class app/revanced/patches/nyx/misc/pro/UnlockProPatch : app/revanc
|
||||
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 static final field INSTANCE Lapp/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -471,6 +523,13 @@ public final class app/revanced/patches/reddit/customclients/Constants {
|
||||
public static final field OAUTH_USER_AGENT Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public fun <init> (Ljava/util/Set;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
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/customclients/baconreader/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch;
|
||||
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -526,10 +585,12 @@ public final class app/revanced/patches/reddit/customclients/slide/api/SpoofClie
|
||||
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public final class app/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch : app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch : app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch;
|
||||
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/customclients/syncforreddit/annoyances/startup/DisableSyncForLemmyBottomSheetPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
@@ -550,6 +611,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/detec
|
||||
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 static final field INSTANCE Lapp/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -599,6 +666,7 @@ public abstract class app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportRes
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
protected final fun getGmsCoreVendor ()Ljava/lang/String;
|
||||
protected final fun getGmsCoreVendorGroupId ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
@@ -612,9 +680,19 @@ public abstract class app/revanced/patches/shared/misc/integrations/BaseIntegrat
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun invoke (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver : kotlin/jvm/functions/Function1 {
|
||||
public abstract fun invoke (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver$DefaultImpls {
|
||||
public static fun invoke (Lapp/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver;Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer;
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IRegisterResolver : kotlin/jvm/functions/Function1 {
|
||||
public abstract fun invoke (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer;
|
||||
}
|
||||
@@ -707,10 +785,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 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 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 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 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;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||
public final fun getCategories ()Ljava/util/Set;
|
||||
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||
@@ -782,12 +858,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 fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;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 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;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 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 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;
|
||||
@@ -976,6 +1062,12 @@ public final class app/revanced/patches/tumblr/featureflags/OverrideFeatureFlags
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/tumblr/fixes/FixOldVersionsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/tumblr/fixes/FixOldVersionsPatch;
|
||||
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/tumblr/live/DisableTumblrLivePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/tumblr/live/DisableTumblrLivePatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1065,6 +1157,18 @@ public final class app/revanced/patches/twitch/misc/settings/SettingsResourcePat
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitch/misc/settings/SettingsResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch;
|
||||
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/twitter/layout/viewcount/HideViewCountPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/layout/viewcount/HideViewCountPatch;
|
||||
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/twitter/misc/dynamiccolor/DynamicColorPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -1092,6 +1196,18 @@ 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 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/twitter/misc/links/SanitizeSharingLinksPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/SanitizeSharingLinksPatch;
|
||||
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 static final field INSTANCE Lapp/revanced/patches/vsco/misc/pro/UnlockProPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1152,8 +1268,8 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch;
|
||||
public final class app/revanced/patches/youtube/interaction/downloads/DownloadsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/DownloadsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
@@ -1420,6 +1536,10 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1430,7 +1550,6 @@ public final class app/revanced/patches/youtube/layout/tabletminiplayer/TabletMi
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)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 {
|
||||
@@ -1469,10 +1588,12 @@ public final class app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDevic
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
|
||||
public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Lkotlin/Triple;
|
||||
public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V
|
||||
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Triple;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
@@ -1530,6 +1651,13 @@ public final class app/revanced/patches/youtube/misc/minimizedplayback/Minimized
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
public final fun getHookNavigationButtonCreated ()Lkotlin/jvm/functions/Function1;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch;
|
||||
public final fun addControls (Ljava/lang/String;)V
|
||||
@@ -1579,9 +1707,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 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 getINTERACTIONS ()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 getALTERNATIVE_THUMBNAILS ()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 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;
|
||||
}
|
||||
|
||||
@@ -1698,6 +1831,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I
|
||||
public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
|
||||
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
|
||||
public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
|
||||
public static final fun returnEarly (Ljava/util/List;Z)V
|
||||
public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V
|
||||
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import org.gradle.kotlin.dsl.support.listFilesOrdered
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.9.22"
|
||||
alias(libs.plugins.kotlin)
|
||||
alias(libs.plugins.binary.compatibility.validator)
|
||||
`maven-publish`
|
||||
signing
|
||||
}
|
||||
|
||||
group = "app.revanced"
|
||||
@@ -12,7 +14,14 @@ repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
google()
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
maven {
|
||||
// A repository must be specified 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 {
|
||||
@@ -22,34 +31,38 @@ dependencies {
|
||||
implementation(libs.guava)
|
||||
// Used in JsonGenerator.
|
||||
implementation(libs.gson)
|
||||
|
||||
// A dependency to the Android library unfortunately fails the build, which is why this is required.
|
||||
compileOnly(project("dummy"))
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(11)
|
||||
}
|
||||
|
||||
tasks.withType(Jar::class) {
|
||||
exclude("app/revanced/meta")
|
||||
|
||||
manifest {
|
||||
attributes["Name"] = "ReVanced Patches"
|
||||
attributes["Description"] = "Patches for ReVanced."
|
||||
attributes["Version"] = version
|
||||
attributes["Timestamp"] = System.currentTimeMillis().toString()
|
||||
attributes["Source"] = "git@github.com:revanced/revanced-patches.git"
|
||||
attributes["Author"] = "ReVanced"
|
||||
attributes["Contact"] = "contact@revanced.app"
|
||||
attributes["Origin"] = "https://revanced.app"
|
||||
attributes["License"] = "GNU General Public License v3.0"
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_11)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
tasks {
|
||||
register<DefaultTask>("generateBundle") {
|
||||
description = "Generate DEX files and add them in the JAR file"
|
||||
withType(Jar::class) {
|
||||
exclude("app/revanced/meta")
|
||||
|
||||
manifest {
|
||||
attributes["Name"] = "ReVanced Patches"
|
||||
attributes["Description"] = "Patches for ReVanced."
|
||||
attributes["Version"] = version
|
||||
attributes["Timestamp"] = System.currentTimeMillis().toString()
|
||||
attributes["Source"] = "git@github.com:revanced/revanced-patches.git"
|
||||
attributes["Author"] = "ReVanced"
|
||||
attributes["Contact"] = "contact@revanced.app"
|
||||
attributes["Origin"] = "https://revanced.app"
|
||||
attributes["License"] = "GNU General Public License v3.0"
|
||||
}
|
||||
}
|
||||
|
||||
register("buildDexJar") {
|
||||
description = "Build and add a DEX to the JAR file"
|
||||
group = "build"
|
||||
|
||||
dependsOn(build)
|
||||
|
||||
@@ -57,39 +70,50 @@ tasks {
|
||||
val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools")
|
||||
.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
|
||||
|
||||
exec {
|
||||
workingDir = workingDirectory
|
||||
commandLine = listOf(d8, artifacts)
|
||||
commandLine = listOf(d8, "--release", patchesJar)
|
||||
}
|
||||
|
||||
exec {
|
||||
workingDir = workingDirectory
|
||||
commandLine = listOf("zip", "-u", artifacts, "classes.dex")
|
||||
commandLine = listOf("zip", "-u", patchesJar, "classes.dex")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register<JavaExec>("generateMeta") {
|
||||
description = "Generate metadata for this bundle"
|
||||
register<JavaExec>("generatePatchesFiles") {
|
||||
description = "Generate patches files"
|
||||
|
||||
dependsOn(build)
|
||||
|
||||
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
|
||||
named("publish") {
|
||||
dependsOn("generateBundle")
|
||||
dependsOn("generateMeta")
|
||||
publish {
|
||||
dependsOn("buildDexJar")
|
||||
dependsOn("generatePatchesFiles")
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
create<MavenPublication>("revanced-patches-publication") {
|
||||
from(components["java"])
|
||||
@@ -120,4 +144,10 @@ publishing {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
useGpgCmd()
|
||||
|
||||
sign(publishing.publications["revanced-patches-publication"])
|
||||
}
|
||||
|
||||
8
crowdin.yml
Normal file
8
crowdin.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
project_id_env: "CROWDIN_PROJECT_ID"
|
||||
api_token_env: "CROWDIN_PERSONAL_TOKEN"
|
||||
|
||||
preserve_hierarchy: false
|
||||
files:
|
||||
- source: src/main/resources/addresources/values/strings.xml
|
||||
translation: src/main/resources/addresources/values-%android_code%/strings.xml
|
||||
skip_untranslated_strings: true
|
||||
@@ -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.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 4.0.2-dev.2
|
||||
version = 4.7.0-dev.8
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[versions]
|
||||
revanced-patcher = "19.2.0"
|
||||
smali = "3.0.3"
|
||||
revanced-patcher = "19.3.1"
|
||||
smali = "3.0.5"
|
||||
guava = "33.0.0-jre"
|
||||
gson = "2.10.1"
|
||||
binary-compatibility-validator = "0.13.2"
|
||||
binary-compatibility-validator = "0.14.0"
|
||||
kotlin = "1.9.22"
|
||||
|
||||
[libraries]
|
||||
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]
|
||||
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
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
|
||||
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/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.9.1",
|
||||
"semantic-release": "^23.0.0"
|
||||
"semantic-release": "^23.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -326,9 +326,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "8.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz",
|
||||
"integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.2.0.tgz",
|
||||
"integrity": "sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^9.0.0",
|
||||
@@ -564,6 +564,26 @@
|
||||
"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": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
@@ -1195,9 +1215,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/merge-streams": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz",
|
||||
"integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.2.0.tgz",
|
||||
"integrity": "sha512-UTce8mUwUW0RikMb/eseJ7ys0BRkZVFB86orHzrfW12ZmFtym5zua8joZ4L7okH2dDFHkcFjqnZ5GocWBXOFtA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -1282,6 +1302,12 @@
|
||||
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
|
||||
"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": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
@@ -1376,6 +1402,81 @@
|
||||
"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": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
|
||||
@@ -1818,9 +1919,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -1888,9 +1989,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
|
||||
"integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.4"
|
||||
@@ -2052,12 +2153,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/globby": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz",
|
||||
"integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==",
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz",
|
||||
"integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sindresorhus/merge-streams": "^1.0.0",
|
||||
"@sindresorhus/merge-streams": "^2.1.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"ignore": "^5.2.4",
|
||||
"path-type": "^5.0.0",
|
||||
@@ -2142,9 +2243,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
|
||||
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
|
||||
"integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
@@ -2153,6 +2254,15 @@
|
||||
"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": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz",
|
||||
@@ -2178,9 +2288,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz",
|
||||
"integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.1.tgz",
|
||||
"integrity": "sha512-My1KCEPs6A0hb4qCVzYp8iEvA8j8YqcvXLZZH8C9OFuTYpYjHE7N2dtG3mRl1HMD4+VGXpF3XcDVcxGBT7yDZQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.0",
|
||||
@@ -2191,9 +2301,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-kCnwztfX0KZJSLOBrcL0emLeFako55NWMovvyPP2AjsghNk9RB1yjSI+jVumPHYZsNXegNoqupSW9IY3afSH8w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.0.2",
|
||||
@@ -2213,9 +2323,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
|
||||
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@@ -2629,9 +2739,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz",
|
||||
"integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==",
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz",
|
||||
"integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
@@ -2641,14 +2751,14 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.0.0.tgz",
|
||||
"integrity": "sha512-sNEx8nn9Ktcm6pL0TnRz8tnXq/mSS0Q1FRSwJOAqw4lAB4l49UeDf85Gm1n9RPFm5qurCPjwi1StAQT2XExhZw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^6.2.0",
|
||||
"cardinal": "^2.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
"cli-highlight": "^2.1.11",
|
||||
"cli-table3": "^0.6.3",
|
||||
"node-emoji": "^2.1.3",
|
||||
"supports-hyperlinks": "^3.0.0"
|
||||
@@ -2657,7 +2767,7 @@
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"marked": ">=1 <12"
|
||||
"marked": ">=1 <13"
|
||||
}
|
||||
},
|
||||
"node_modules/meow": {
|
||||
@@ -2739,6 +2849,17 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"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": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
@@ -5551,6 +5672,15 @@
|
||||
"inBundle": true,
|
||||
"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": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -5695,6 +5825,27 @@
|
||||
"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": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.18.1.tgz",
|
||||
@@ -5860,9 +6011,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg-up/node_modules/type-fest": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.1.tgz",
|
||||
"integrity": "sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==",
|
||||
"version": "4.10.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
|
||||
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
@@ -5889,9 +6040,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg/node_modules/type-fest": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.1.tgz",
|
||||
"integrity": "sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==",
|
||||
"version": "4.10.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
|
||||
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
@@ -5994,9 +6145,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/semantic-release": {
|
||||
"version": "23.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.0.tgz",
|
||||
"integrity": "sha512-Jz7jEWO2igTtske112gC4PPE2whCMVrsgxUPG3/SZI7VE357suIUZFlJd1Yu0g2I6RPc2HxNEfUg7KhmDTjwqg==",
|
||||
"version": "23.0.2",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.2.tgz",
|
||||
"integrity": "sha512-OnVYJ6Xgzwe1x8MKswba7RU9+5djS1MWRTrTn5qsq3xZYpslroZkV9Pt0dA2YcIuieeuSZWJhn+yUWoBUHO5Fw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@semantic-release/commit-analyzer": "^11.0.0",
|
||||
@@ -6017,8 +6168,8 @@
|
||||
"hosted-git-info": "^7.0.0",
|
||||
"import-from-esm": "^1.3.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"marked": "^11.0.0",
|
||||
"marked-terminal": "^6.0.0",
|
||||
"marked": "^12.0.0",
|
||||
"marked-terminal": "^7.0.0",
|
||||
"micromatch": "^4.0.2",
|
||||
"p-each-series": "^3.0.0",
|
||||
"p-reduce": "^3.0.0",
|
||||
@@ -6247,9 +6398,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
@@ -6481,9 +6632,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/spdx-license-ids": {
|
||||
"version": "3.0.16",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
|
||||
"integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
|
||||
"version": "3.0.17",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
|
||||
"integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/split2": {
|
||||
@@ -6655,6 +6806,27 @@
|
||||
"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": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.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"
|
||||
|
||||
buildCache {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package app.revanced.meta
|
||||
package app.revanced.generator
|
||||
|
||||
import app.revanced.patcher.PatchSet
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import com.google.gson.GsonBuilder
|
||||
import java.io.File
|
||||
|
||||
internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
||||
internal class JsonPatchesFileGenerator : PatchesFileGenerator {
|
||||
override fun generate(patches: PatchSet) = patches.map {
|
||||
JsonPatch(
|
||||
it.name!!,
|
||||
@@ -20,9 +20,9 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
||||
option.values,
|
||||
option.title,
|
||||
option.description,
|
||||
option.required
|
||||
option.required,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}.let {
|
||||
File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it))
|
||||
@@ -35,7 +35,7 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
||||
val compatiblePackages: Set<Patch.CompatiblePackage>? = null,
|
||||
val use: Boolean = true,
|
||||
val requiresIntegrations: Boolean = false,
|
||||
val options: List<Option>
|
||||
val options: List<Option>,
|
||||
) {
|
||||
class Option(
|
||||
val key: String,
|
||||
@@ -46,4 +46,4 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
|
||||
val required: Boolean,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
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,29 +7,34 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||
@Patch(
|
||||
name = "Export all activities",
|
||||
description = "Makes all app activities exportable.",
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ExportAllActivitiesPatch : ResourcePatch() {
|
||||
private const val EXPORTED_FLAG = "android:exported"
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
val activities = document.getElementsByTagName("activity")
|
||||
|
||||
for(i in 0..activities.length) {
|
||||
for (i in 0..activities.length) {
|
||||
activities.item(i)?.apply {
|
||||
val exportedAttribute = attributes.getNamedItem(EXPORTED_FLAG)
|
||||
|
||||
if (exportedAttribute != null) {
|
||||
if (exportedAttribute.nodeValue != "true")
|
||||
if (exportedAttribute.nodeValue != "true") {
|
||||
exportedAttribute.nodeValue = "true"
|
||||
}
|
||||
}
|
||||
// Reason why the attribute is added in the case it does not exist:
|
||||
// https://github.com/revanced/revanced-patches/pull/1751/files#r1141481604
|
||||
else document.createAttribute(EXPORTED_FLAG)
|
||||
.apply { value = "true" }
|
||||
.let(attributes::setNamedItem)
|
||||
else {
|
||||
document.createAttribute(EXPORTED_FLAG)
|
||||
.apply { value = "true" }
|
||||
.let(attributes::setNamedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||
@Patch(
|
||||
name = "Predictive back gesture",
|
||||
description = "Enables the predictive back gesture introduced on Android 13.",
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object PredictiveBackGesturePatch : ResourcePatch() {
|
||||
|
||||
@@ -8,16 +8,18 @@ import org.w3c.dom.Element
|
||||
@Patch(
|
||||
name = "Enable Android debugging",
|
||||
description = "Enables Android debugging capabilities. This can slow down the app.",
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object EnableAndroidDebuggingPatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
||||
val applicationNode = dom
|
||||
.file
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
val applicationNode =
|
||||
document
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
|
||||
// set application as debuggable
|
||||
applicationNode.setAttribute("android:debuggable", "true")
|
||||
|
||||
@@ -4,6 +4,7 @@ import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
|
||||
@@ -11,16 +12,17 @@ import java.io.File
|
||||
name = "Override certificate pinning",
|
||||
description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
|
||||
dependencies = [EnableAndroidDebuggingPatch::class],
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object OverrideCertificatePinningPatch : ResourcePatch() {
|
||||
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.
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
val applicationNode = document.getElementsByTagName("application").item(0) as Element
|
||||
|
||||
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
|
||||
@@ -31,10 +33,8 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
|
||||
|
||||
// In case the file does not exist create the "network_security_config.xml" file.
|
||||
File(resXmlDirectory, "network_security_config.xml").apply {
|
||||
if (!exists()) {
|
||||
createNewFile()
|
||||
writeText(
|
||||
"""
|
||||
writeText(
|
||||
"""
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
@@ -54,22 +54,8 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
|
||||
</trust-anchors>
|
||||
</debug-overrides>
|
||||
</network-security-config>
|
||||
"""
|
||||
)
|
||||
} 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\" />"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
""".trimIndentMultiline(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,20 +11,21 @@ import java.io.Closeable
|
||||
@Patch(
|
||||
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.",
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ChangePackageNamePatch : ResourcePatch(), Closeable {
|
||||
private val packageNameOption = stringPatchOption(
|
||||
key = "packageName",
|
||||
default = "Default",
|
||||
values = mapOf("Default" to "Default"),
|
||||
title = "Package name",
|
||||
description = "The name of the package to rename the app to.",
|
||||
required = true
|
||||
) {
|
||||
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
||||
}
|
||||
private val packageNameOption =
|
||||
stringPatchOption(
|
||||
key = "packageName",
|
||||
default = "Default",
|
||||
values = mapOf("Default" to "Default"),
|
||||
title = "Package name",
|
||||
description = "The name of the package to rename the app to.",
|
||||
required = true,
|
||||
) {
|
||||
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
||||
}
|
||||
|
||||
private lateinit var context: ResourceContext
|
||||
|
||||
@@ -43,20 +44,27 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
|
||||
fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
|
||||
val packageName = packageNameOption.value!!
|
||||
|
||||
return if (packageName == packageNameOption.default)
|
||||
return if (packageName == packageNameOption.default) {
|
||||
fallbackPackageName.also { packageNameOption.value = it }
|
||||
else
|
||||
} else {
|
||||
packageName
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() = context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val replacementPackageName = packageNameOption.value
|
||||
override fun close() =
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
|
||||
manifest.setAttribute(
|
||||
"package",
|
||||
if (replacementPackageName != packageNameOption.default) replacementPackageName
|
||||
else "${manifest.getAttribute("package")}.revanced"
|
||||
)
|
||||
}
|
||||
val replacementPackageName = packageNameOption.value
|
||||
|
||||
val manifest = document.getElementsByTagName("manifest").item(0) as Element
|
||||
manifest.setAttribute(
|
||||
"package",
|
||||
if (replacementPackageName != packageNameOption.default) {
|
||||
replacementPackageName
|
||||
} else {
|
||||
"${manifest.getAttribute("package")}.revanced"
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.*
|
||||
* An identifier of an app. For example, `youtube`.
|
||||
*/
|
||||
private typealias AppId = String
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private typealias PatchResources = MutableSet<BaseResource>
|
||||
|
||||
/**
|
||||
* A map of resources belonging to a patch.
|
||||
*/
|
||||
private typealias AppResources = MutableMap<PatchId, PatchResources>
|
||||
|
||||
/**
|
||||
* A map of resources belonging to an app.
|
||||
*/
|
||||
@@ -67,40 +70,44 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
override fun execute(context: ResourceContext) {
|
||||
this.context = context
|
||||
|
||||
resources = buildMap {
|
||||
/**
|
||||
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
|
||||
*
|
||||
* @param value The value of the resource. For example, `values` or `values-de`.
|
||||
* @param resourceKind The kind of the resource. For example, `strings` or `arrays`.
|
||||
* @param transform A function that transforms the [Node]s from the XML files to a [BaseResource].
|
||||
*/
|
||||
fun addResources(
|
||||
value: Value,
|
||||
resourceKind: String,
|
||||
transform: (Node) -> BaseResource,
|
||||
) {
|
||||
inputStreamFromBundledResource(
|
||||
"addresources",
|
||||
"$value/$resourceKind.xml"
|
||||
)?.let { stream ->
|
||||
// Add the resources associated with the given value to the map,
|
||||
// instead of overwriting it.
|
||||
// This covers the example case such as adding strings and arrays of the same value.
|
||||
getOrPut(value, ::mutableMapOf).apply {
|
||||
context.xmlEditor[stream].use {
|
||||
it.file.getElementsByTagName("app").asSequence().forEach { app ->
|
||||
val appId = app.attributes.getNamedItem("id").textContent
|
||||
resources =
|
||||
buildMap {
|
||||
/**
|
||||
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
|
||||
*
|
||||
* @param value The value of the resource. For example, `values` or `values-de`.
|
||||
* @param resourceKind The kind of the resource. For example, `strings` or `arrays`.
|
||||
* @param transform A function that transforms the [Node]s from the XML files to a [BaseResource].
|
||||
*/
|
||||
fun addResources(
|
||||
value: Value,
|
||||
resourceKind: String,
|
||||
transform: (Node) -> BaseResource,
|
||||
) {
|
||||
inputStreamFromBundledResource(
|
||||
"addresources",
|
||||
"$value/$resourceKind.xml",
|
||||
)?.let { stream ->
|
||||
// Add the resources associated with the given value to the map,
|
||||
// instead of overwriting it.
|
||||
// This covers the example case such as adding strings and arrays of the same value.
|
||||
getOrPut(value, ::mutableMapOf).apply {
|
||||
context.xmlEditor[stream].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
getOrPut(appId, ::mutableMapOf).apply {
|
||||
app.forEachChildElement { patch ->
|
||||
val patchId = patch.attributes.getNamedItem("id").textContent
|
||||
document.getElementsByTagName("app").asSequence().forEach { app ->
|
||||
val appId = app.attributes.getNamedItem("id").textContent
|
||||
|
||||
getOrPut(patchId, ::mutableSetOf).apply {
|
||||
patch.forEachChildElement { resourceNode ->
|
||||
val resource = transform(resourceNode)
|
||||
getOrPut(appId, ::mutableMapOf).apply {
|
||||
app.forEachChildElement { patch ->
|
||||
val patchId = patch.attributes.getNamedItem("id").textContent
|
||||
|
||||
add(resource)
|
||||
getOrPut(patchId, ::mutableSetOf).apply {
|
||||
patch.forEachChildElement { resourceNode ->
|
||||
val resource = transform(resourceNode)
|
||||
|
||||
add(resource)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,23 +116,22 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stage all resources to a temporary map.
|
||||
// Staged resources consumed by AddResourcesPatch#invoke(PatchClass)
|
||||
// are later used in AddResourcesPatch#close.
|
||||
try {
|
||||
val addStringResources = { value: Value ->
|
||||
addResources(value, "strings", StringResource::fromNode)
|
||||
// Stage all resources to a temporary map.
|
||||
// Staged resources consumed by AddResourcesPatch#invoke(PatchClass)
|
||||
// are later used in AddResourcesPatch#close.
|
||||
try {
|
||||
val addStringResources = { value: Value ->
|
||||
addResources(value, "strings", StringResource::fromNode)
|
||||
}
|
||||
Locale.getISOLanguages().asSequence().map { "values-$it" }.forEach { addStringResources(it) }
|
||||
addStringResources("values")
|
||||
|
||||
addResources("values", "arrays", ArrayResource::fromNode)
|
||||
} catch (e: Exception) {
|
||||
throw PatchException("Failed to read resources", e)
|
||||
}
|
||||
Locale.getISOLanguages().asSequence().map { "values-$it" }.forEach { addStringResources(it) }
|
||||
addStringResources("values")
|
||||
|
||||
addResources("values", "arrays", ArrayResource::fromNode)
|
||||
} catch (e: Exception) {
|
||||
throw PatchException("Failed to read resources", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,8 +142,10 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
*
|
||||
* @return True if the resource was added, false if it already existed.
|
||||
*/
|
||||
operator fun invoke(value: Value, resource: BaseResource) =
|
||||
getOrPut(value, ::mutableSetOf).add(resource)
|
||||
operator fun invoke(
|
||||
value: Value,
|
||||
resource: BaseResource,
|
||||
) = getOrPut(value, ::mutableSetOf).add(resource)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
operator fun invoke(value: Value, resources: Iterable<BaseResource>) =
|
||||
getOrPut(value, ::mutableSetOf).addAll(resources)
|
||||
operator fun invoke(
|
||||
value: Value,
|
||||
resources: Iterable<BaseResource>,
|
||||
) = getOrPut(value, ::mutableSetOf).addAll(resources)
|
||||
|
||||
/**
|
||||
* Adds a [StringResource].
|
||||
@@ -177,10 +187,9 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
*/
|
||||
operator fun invoke(
|
||||
name: String,
|
||||
items: List<String>
|
||||
items: List<String>,
|
||||
) = invoke("values", ArrayResource(name, items))
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
},
|
||||
): Boolean {
|
||||
val (appId, patchId) = patch.parseIds()
|
||||
|
||||
@@ -218,7 +227,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
// Stage resources for the given patch to AddResourcesPatch associated with their value.
|
||||
resources.forEach { (value, resources) ->
|
||||
resources[appId]?.get(patchId)?.let { patchResources ->
|
||||
if (invoke(value, patchResources)) result = true
|
||||
if (invoke(value, patchResources)) result = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,28 +241,32 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
override fun close() {
|
||||
operator fun MutableMap<String, Pair<DomFileEditor, Node>>.invoke(
|
||||
value: Value,
|
||||
resource: BaseResource
|
||||
resource: BaseResource,
|
||||
) {
|
||||
// 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.
|
||||
val resourceFileName = when (resource) {
|
||||
is StringResource -> "strings"
|
||||
is ArrayResource -> "arrays"
|
||||
else -> throw NotImplementedError("Unsupported resource type")
|
||||
}
|
||||
|
||||
getOrPut(resourceFileName) {
|
||||
val targetFile = context["res/$value/$resourceFileName.xml"].also {
|
||||
it.parentFile?.mkdirs()
|
||||
it.createNewFile()
|
||||
val resourceFileName =
|
||||
when (resource) {
|
||||
is StringResource -> "strings"
|
||||
is ArrayResource -> "arrays"
|
||||
else -> throw NotImplementedError("Unsupported resource type")
|
||||
}
|
||||
|
||||
getOrPut(resourceFileName) {
|
||||
val targetFile =
|
||||
context.get("res/$value/$resourceFileName.xml").also {
|
||||
it.parentFile?.mkdirs()
|
||||
it.createNewFile()
|
||||
}
|
||||
|
||||
context.xmlEditor[targetFile.path].let { editor ->
|
||||
val document = editor.file
|
||||
|
||||
// Save the target node here as well
|
||||
// in order to avoid having to call editor.getNode("resources")
|
||||
// every time addUsingEditors is called but also save the editor so that it can be closed later.
|
||||
editor to editor.getNode("resources")
|
||||
// in order to avoid having to call document.getNode("resources")
|
||||
// but also save the document so that it can be closed later.
|
||||
editor to document.getNode("resources")
|
||||
}
|
||||
}.let { (_, targetNode) ->
|
||||
targetNode.addResource(resource) { invoke(value, it) }
|
||||
@@ -261,17 +274,17 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
}
|
||||
|
||||
forEach { (value, resources) ->
|
||||
// A map of editors associated by their kind (e.g. strings, arrays).
|
||||
// Each editor 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 of document associated by their kind (e.g. strings, arrays).
|
||||
// Each document is accompanied by the target node to which resources are added.
|
||||
// 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.
|
||||
// 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.
|
||||
val resourceFileEditors = mutableMapOf<String, Pair<DomFileEditor, Node>>()
|
||||
// This map is later accessed to close all documents for the current resource value.
|
||||
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
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
abstract class BaseTransformInstructionsPatch<T> : BytecodePatch() {
|
||||
abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
|
||||
abstract fun filterMap(
|
||||
classDef: ClassDef,
|
||||
method: Method,
|
||||
instruction: Instruction,
|
||||
instructionIndex: Int
|
||||
instructionIndex: Int,
|
||||
): T?
|
||||
|
||||
abstract fun transform(mutableMethod: MutableMethod, entry: T)
|
||||
|
||||
@@ -8,16 +8,17 @@ import org.w3c.dom.Element
|
||||
@Patch(description = "Sets allowAudioPlaybackCapture in manifest to true.")
|
||||
internal object RemoveCaptureRestrictionResourcePatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) {
|
||||
// create an xml editor instance
|
||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
// get the application node
|
||||
val applicationNode = dom
|
||||
.file
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
val applicationNode =
|
||||
document
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
|
||||
// set allowAudioPlaybackCapture attribute to true
|
||||
applicationNode.setAttribute("android:allowAudioPlaybackCapture", "true")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.amazon.deeplinking
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object DeepLinkingFingerprint : MethodFingerprint(
|
||||
"Z",
|
||||
parameters = listOf("L"),
|
||||
accessFlags = AccessFlags.PRIVATE.value,
|
||||
strings = listOf("https://www.", "android.intent.action.VIEW")
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package app.revanced.patches.amazon.deeplinking
|
||||
|
||||
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.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Always allow deep-linking",
|
||||
description = "Open Amazon links, even if the app is not set to handle Amazon links.",
|
||||
compatiblePackages = [CompatiblePackage("com.amazon.mShop.android.shopping")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DeepLinkingPatch : BytecodePatch(
|
||||
setOf(DeepLinkingFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
DeepLinkingFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
) ?: throw DeepLinkingFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -1,102 +1,63 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline
|
||||
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckOneFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckTwoFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.GenericMediaAdFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint
|
||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Hide timeline ads",
|
||||
description = "Removes ads from the timeline.",
|
||||
compatiblePackages = [CompatiblePackage("com.instagram.android", ["275.0.0.27.98"])]
|
||||
compatiblePackages = [CompatiblePackage("com.instagram.android")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideTimelineAdsPatch : BytecodePatch(
|
||||
setOf(
|
||||
ShowAdFingerprint,
|
||||
MediaFingerprint,
|
||||
PaidPartnershipAdFingerprint // Unlike the other ads this one is resolved from all classes.
|
||||
)
|
||||
IsAdCheckOneFingerprint,
|
||||
IsAdCheckTwoFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// region Resolve required methods to check for ads.
|
||||
// The exact function of the following methods is unknown.
|
||||
// They are used to check if a post is an ad.
|
||||
val isAdCheckOneMethod = IsAdCheckOneFingerprint.result?.method ?: throw IsAdCheckOneFingerprint.exception
|
||||
val isAdCheckTwoMethod = IsAdCheckTwoFingerprint.result?.method ?: throw IsAdCheckTwoFingerprint.exception
|
||||
|
||||
ShowAdFingerprint.result ?: throw ShowAdFingerprint.exception
|
||||
ShowAdFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
// The register that holds the post object.
|
||||
val postRegister = getInstruction<FiveRegisterInstruction>(1).registerC
|
||||
|
||||
PaidPartnershipAdFingerprint.result ?: throw PaidPartnershipAdFingerprint.exception
|
||||
// At this index the check for an ad can be performed.
|
||||
val checkIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
MediaFingerprint.result?.let {
|
||||
GenericMediaAdFingerprint.resolve(context, it.classDef)
|
||||
ShoppingAdFingerprint.resolve(context, it.classDef)
|
||||
|
||||
return@let
|
||||
} ?: throw MediaFingerprint.exception
|
||||
|
||||
// endregion
|
||||
|
||||
ShowAdFingerprint.result!!.apply {
|
||||
// region Create instructions.
|
||||
|
||||
val scanStart = scanResult.patternScanResult!!.startIndex
|
||||
val jumpIndex = scanStart - 1
|
||||
|
||||
val mediaInstanceRegister = mutableMethod.getInstruction<FiveRegisterInstruction>(scanStart).registerC
|
||||
val freeRegister = mutableMethod.getInstruction<OneRegisterInstruction>(jumpIndex).registerA
|
||||
|
||||
val returnFalseLabel = "an_ad"
|
||||
|
||||
val checkForAdInstructions =
|
||||
listOf(GenericMediaAdFingerprint, PaidPartnershipAdFingerprint, ShoppingAdFingerprint)
|
||||
.map(MediaAdFingerprint::toString)
|
||||
.joinToString("\n") {
|
||||
"""
|
||||
invoke-virtual {v$mediaInstanceRegister}, $it
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :$returnFalseLabel
|
||||
""".trimIndent()
|
||||
}.let { "$it\nconst/4 v0, 0x1\nreturn v0" }
|
||||
|
||||
// endregion
|
||||
|
||||
// region Patch.
|
||||
|
||||
val insertIndex = scanStart + 3
|
||||
|
||||
mutableMethod.addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
checkForAdInstructions,
|
||||
ExternalLabel(
|
||||
returnFalseLabel,
|
||||
mutableMethod.getInstruction(mutableMethod.implementation!!.instructions.size - 2 /* return false = ad */)
|
||||
)
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
// region Jump to checks for ads from previous patch.
|
||||
|
||||
mutableMethod.apply {
|
||||
// If either check returns true, the post is an ad and is hidden by returning false.
|
||||
addInstructionsWithLabels(
|
||||
jumpIndex + 1,
|
||||
"if-nez v$freeRegister, :start_check",
|
||||
ExternalLabel("start_check", getInstruction(insertIndex))
|
||||
checkIndex,
|
||||
"""
|
||||
invoke-virtual { v$postRegister }, $isAdCheckOneMethod
|
||||
move-result v0
|
||||
if-nez v0, :hide_ad
|
||||
|
||||
invoke-static { v$postRegister }, $isAdCheckTwoMethod
|
||||
move-result v0
|
||||
if-eqz v0, :not_an_ad
|
||||
|
||||
:hide_ad
|
||||
const/4 v0, 0x0 # Returning false to hide the ad.
|
||||
return v0
|
||||
""",
|
||||
ExternalLabel("not_an_ad", getInstruction(checkIndex)),
|
||||
)
|
||||
}.removeInstruction(jumpIndex)
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
} ?: throw ShowAdFingerprint.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object IsAdCheckOneFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf(),
|
||||
opcodes = listOf(
|
||||
Opcode.XOR_INT_LIT8,
|
||||
Opcode.IF_NE,
|
||||
Opcode.RETURN,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
),
|
||||
)
|
||||
@@ -1,8 +1,14 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object GenericMediaAdFingerprint : MediaAdFingerprint(
|
||||
internal object IsAdCheckTwoFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
@@ -12,7 +18,5 @@ internal object GenericMediaAdFingerprint : MediaAdFingerprint(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.RETURN,
|
||||
)
|
||||
) {
|
||||
override fun toString() = result!!.method.toString()
|
||||
}
|
||||
),
|
||||
)
|
||||
@@ -1,7 +0,0 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object MediaFingerprint : MethodFingerprint(
|
||||
strings = listOf("force_overlay", "Media#updateFields", "live_reels_metadata")
|
||||
)
|
||||
@@ -10,16 +10,12 @@ internal object ShowAdFingerprint : MethodFingerprint(
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
|
||||
listOf("L", "L", "Z", "Z"),
|
||||
opcodes = listOf(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.RETURN,
|
||||
Opcode.CONST_4,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
|
||||
internal abstract class MediaAdFingerprint(
|
||||
returnType: String? = "Z",
|
||||
accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters: Iterable<String>? = listOf(),
|
||||
opcodes: Iterable<Opcode>?,
|
||||
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
|
||||
) : MethodFingerprint(
|
||||
returnType,
|
||||
accessFlags,
|
||||
parameters,
|
||||
opcodes,
|
||||
customFingerprint = customFingerprint
|
||||
) {
|
||||
abstract override fun toString(): String
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
||||
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object PaidPartnershipAdFingerprint : MediaAdFingerprint(
|
||||
"V",
|
||||
null,
|
||||
listOf("L", "L"),
|
||||
listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
Opcode.IPUT_BOOLEAN
|
||||
),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("ClipsEditMetadataController;")
|
||||
}
|
||||
) {
|
||||
override fun toString() = result!!.let {
|
||||
val adCheckIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val adCheckInstruction = it.method.implementation!!.instructions.elementAt(adCheckIndex)
|
||||
|
||||
val adCheckMethod = (adCheckInstruction as ReferenceInstruction).reference as MethodReference
|
||||
|
||||
adCheckMethod.toString()
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
||||
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object ShoppingAdFingerprint : MediaAdFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.XOR_INT_LIT8,
|
||||
Opcode.IF_EQZ,
|
||||
)
|
||||
) {
|
||||
override fun toString() = result!!.method.toString()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package app.revanced.patches.mifitness.misc.locale
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.mifitness.misc.locale.fingerprints.SyncBluetoothLanguageFingerprint
|
||||
import app.revanced.patches.mifitness.misc.login.FixLoginPatch
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Force English locale",
|
||||
description = "Forces wearable devices to use the English locale.",
|
||||
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
|
||||
dependencies = [FixLoginPatch::class],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ForceEnglishLocalePatch : BytecodePatch(
|
||||
setOf(SyncBluetoothLanguageFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SyncBluetoothLanguageFingerprint.result?.let {
|
||||
val resolvePhoneLocaleInstruction = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val registerIndexToUpdate =
|
||||
getInstruction<OneRegisterInstruction>(resolvePhoneLocaleInstruction).registerA
|
||||
|
||||
replaceInstruction(
|
||||
resolvePhoneLocaleInstruction,
|
||||
"const-string v$registerIndexToUpdate, \"en_gb\"",
|
||||
)
|
||||
}
|
||||
} ?: throw SyncBluetoothLanguageFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.mifitness.misc.locale.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object SyncBluetoothLanguageFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" &&
|
||||
methodDef.name == "syncBluetoothLanguage"
|
||||
},
|
||||
opcodes = listOf(Opcode.MOVE_RESULT_OBJECT),
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
package app.revanced.patches.mifitness.misc.login
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.mifitness.misc.login.fingerprints.XiaomiAccountManagerConstructorFingerprint
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Fix login",
|
||||
description = "Fixes login for uncertified Mi Fitness app",
|
||||
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object FixLoginPatch : BytecodePatch(
|
||||
setOf(XiaomiAccountManagerConstructorFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
XiaomiAccountManagerConstructorFingerprint.result?.mutableMethod?.addInstruction(
|
||||
0,
|
||||
"const/16 p2, 0x0",
|
||||
) ?: throw XiaomiAccountManagerConstructorFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.mifitness.misc.login.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;"
|
||||
},
|
||||
parameters = listOf(
|
||||
"Landroid/content/Context;",
|
||||
"Z",
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
package app.revanced.patches.music.ad.video
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsParentFingerprint
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Hide music video ads",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideMusicVideoAds : BytecodePatch(
|
||||
setOf(ShowMusicVideoAdsParentFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
ShowMusicVideoAdsParentFingerprint.result?.let {
|
||||
val showMusicVideoAdsMethod = context
|
||||
.toMethodWalker(it.mutableMethod)
|
||||
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod
|
||||
|
||||
showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
|
||||
} ?: throw ShowMusicVideoAdsParentFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("This patch class has been renamed to HideMusicVideoAds.")
|
||||
object MusicVideoAdsPatch : BytecodePatch(
|
||||
dependencies = setOf(HideMusicVideoAds::class),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package app.revanced.patches.music.ad.video
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
|
||||
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
|
||||
|
||||
@Patch(
|
||||
name = "Music video ads",
|
||||
description = "Removes ads in the music player.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object MusicVideoAdsPatch : BytecodePatch(
|
||||
setOf(ShowMusicVideoAdsConstructorFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
|
||||
|
||||
val result = ShowMusicVideoAdsFingerprint.result!!
|
||||
|
||||
result.mutableMethod.addInstruction(
|
||||
result.scanResult.patternScanResult!!.startIndex,
|
||||
"""
|
||||
const/4 p1, 0x0
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package app.revanced.patches.music.ad.video.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 ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
)
|
||||
@@ -1,14 +0,0 @@
|
||||
package app.revanced.patches.music.ad.video.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object ShowMusicVideoAdsFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf(
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.music.ad.video.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IGET_OBJECT,
|
||||
),
|
||||
strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error."),
|
||||
)
|
||||
@@ -10,13 +10,12 @@ import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprin
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@Patch(
|
||||
name = "Codecs unlock",
|
||||
description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
@Deprecated("This patch is no longer needed as the feature is now enabled by default.")
|
||||
object CodecsUnlockPatch : BytecodePatch(
|
||||
setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint)
|
||||
setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val codecsLockResult = CodecsLockFingerprint.result!!
|
||||
@@ -25,13 +24,13 @@ object CodecsUnlockPatch : BytecodePatch(
|
||||
|
||||
val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex
|
||||
val instructionIndex = scanResultStartIndex +
|
||||
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
|
||||
// for 5.16.xx and lower
|
||||
-3
|
||||
} else {
|
||||
// since 5.17.xx
|
||||
-2
|
||||
}
|
||||
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
|
||||
// for 5.16.xx and lower
|
||||
-3
|
||||
} else {
|
||||
// since 5.17.xx
|
||||
-2
|
||||
}
|
||||
|
||||
val allCodecsResult = AllCodecsReferenceFingerprint.result!!
|
||||
val allCodecsMethod =
|
||||
@@ -41,7 +40,7 @@ object CodecsUnlockPatch : BytecodePatch(
|
||||
|
||||
implementation.replaceInstruction(
|
||||
instructionIndex,
|
||||
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction()
|
||||
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,36 @@
|
||||
package app.revanced.patches.music.audio.exclusiveaudio
|
||||
|
||||
import app.revanced.util.exception
|
||||
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.music.audio.exclusiveaudio.fingerprints.AllowExclusiveAudioPlaybackFingerprint
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Exclusive audio playback",
|
||||
name = "Enable exclusive audio playback",
|
||||
description = "Enables the option to play audio without video.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ExclusiveAudioPatch : BytecodePatch(
|
||||
setOf(AllowExclusiveAudioPlaybackFingerprint)
|
||||
object EnableExclusiveAudioPlayback : BytecodePatch(
|
||||
setOf(AllowExclusiveAudioPlaybackFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AllowExclusiveAudioPlaybackFingerprint.result?.mutableMethod?.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
""",
|
||||
)
|
||||
} ?: throw AllowExclusiveAudioPlaybackFingerprint.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("This patch class has been renamed to EnableExclusiveAudioPlayback.")
|
||||
object ExclusiveAudioPatch : BytecodePatch(emptySet()) {
|
||||
override fun execute(context: BytecodeContext) = EnableExclusiveAudioPlayback.execute(context)
|
||||
}
|
||||
@@ -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,25 +1,32 @@
|
||||
package app.revanced.patches.music.interaction.permanentshuffle
|
||||
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.music.interaction.permanentshuffle.fingerprints.DisableShuffleFingerprint
|
||||
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Permanent shuffle",
|
||||
description = "Permanently remember your shuffle preference " +
|
||||
"even if the playlist ends or another track is played.",
|
||||
"even if the playlist ends or another track is played.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object PermanentShuffleTogglePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
|
||||
object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
DisableShuffleFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
|
||||
?: throw DisableShuffleFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("This patch class has been renamed to PermanentShufflePatch.")
|
||||
object PermanentShuffleTogglePatch : BytecodePatch(
|
||||
dependencies = setOf(PermanentShufflePatch::class),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package app.revanced.patches.music.layout.compactheader
|
||||
|
||||
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.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x
|
||||
|
||||
@Patch(
|
||||
name = "Compact header",
|
||||
description = "Hides the music category bar at the top of the homepage.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
use = false
|
||||
)
|
||||
@Suppress("unused")
|
||||
object CompactHeaderPatch : BytecodePatch(
|
||||
setOf(CompactHeaderConstructorFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val result = CompactHeaderConstructorFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
|
||||
val insertIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
|
||||
method.addInstructions(
|
||||
insertIndex, """
|
||||
const/16 v2, 0x8
|
||||
invoke-virtual {v${register}, v2}, Landroid/view/View;->setVisibility(I)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.music.layout.compactheader
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.music.layout.compactheader.fingerprints.ConstructCategoryBarFingerprint
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Hide category bar",
|
||||
description = "Hides the category bar at the top of the homepage.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideCategoryBar : BytecodePatch(
|
||||
setOf(ConstructCategoryBarFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
ConstructCategoryBarFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
const/16 v2, 0x8
|
||||
invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V
|
||||
""",
|
||||
)
|
||||
}
|
||||
} ?: throw ConstructCategoryBarFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("This patch class has been renamed to HideCategoryBar.")
|
||||
object CompactHeaderPatch : BytecodePatch(
|
||||
dependencies = setOf(HideCategoryBar::class),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
}
|
||||
}
|
||||
@@ -5,19 +5,19 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object CompactHeaderConstructorFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L"), listOf(
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
internal object ConstructCategoryBarFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
listOf("Landroid/content/Context;", "L", "L", "L"),
|
||||
listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.CONST,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST
|
||||
)
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
),
|
||||
)
|
||||
@@ -1,26 +1,39 @@
|
||||
package app.revanced.patches.music.layout.minimizedplayback
|
||||
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
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.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
|
||||
|
||||
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.BackgroundPlaybackDisableFingerprint
|
||||
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Minimized playback music",
|
||||
description = "Enables minimized playback on Kids music.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
name = "Minimized playback",
|
||||
description = "Unlocks options for picture-in-picture and background playback.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object MinimizedPlaybackPatch : BytecodePatch(setOf(MinimizedPlaybackManagerFingerprint)) {
|
||||
override fun execute(context: BytecodeContext) =
|
||||
MinimizedPlaybackManagerFingerprint.result?.mutableMethod?.addInstruction(
|
||||
object MinimizedPlaybackPatch : BytecodePatch(
|
||||
setOf(
|
||||
KidsMinimizedPlaybackPolicyControllerFingerprint,
|
||||
BackgroundPlaybackDisableFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction(
|
||||
0,
|
||||
"return-void",
|
||||
) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
|
||||
|
||||
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
return-void
|
||||
"""
|
||||
) ?: throw MinimizedPlaybackManagerFingerprint.exception
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
) ?: throw BackgroundPlaybackDisableFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
|
||||
"Z",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
listOf("L"),
|
||||
listOf(
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET,
|
||||
Opcode.AND_INT_LIT16,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IGET,
|
||||
),
|
||||
)
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
|
||||
internal object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
listOf("I", "L", "Z"),
|
||||
@@ -22,5 +22,5 @@ internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
)
|
||||
),
|
||||
)
|
||||
@@ -2,41 +2,44 @@ package app.revanced.patches.music.layout.premium
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint
|
||||
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Hide get premium",
|
||||
description = "Removes all \"Get Premium\" evidences from the avatar menu.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
name = "Hide 'Get Music Premium' label",
|
||||
description = "Hides the red \"Get Music Premium\" label from the account menu.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideGetPremiumPatch : BytecodePatch(setOf(HideGetPremiumParentFingerprint)) {
|
||||
object HideGetPremiumPatch : BytecodePatch(
|
||||
setOf(HideGetPremiumFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val parentResult = HideGetPremiumParentFingerprint.result!!
|
||||
HideGetPremiumFingerprint.resolve(context, parentResult.classDef)
|
||||
HideGetPremiumFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
val startIndex = parentResult.scanResult.patternScanResult!!.startIndex
|
||||
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(insertIndex)
|
||||
val getPremiumViewRegister = setVisibilityInstruction.registerC
|
||||
val visibilityRegister = setVisibilityInstruction.registerD
|
||||
|
||||
val parentMethod = parentResult.mutableMethod
|
||||
parentMethod.replaceInstruction(
|
||||
startIndex,
|
||||
"""
|
||||
const/4 v1, 0x0
|
||||
"""
|
||||
)
|
||||
replaceInstruction(
|
||||
insertIndex,
|
||||
"const/16 v$visibilityRegister, 0x8",
|
||||
)
|
||||
|
||||
val result = HideGetPremiumFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
method.addInstruction(
|
||||
startIndex,
|
||||
"""
|
||||
const/16 v0, 0x8
|
||||
"""
|
||||
)
|
||||
addInstruction(
|
||||
insertIndex + 1,
|
||||
"invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " +
|
||||
"Landroid/view/View;->setVisibility(I)V",
|
||||
)
|
||||
}
|
||||
} ?: throw HideGetPremiumFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object HideGetPremiumFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
listOf(),
|
||||
listOf(
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.CONST_16,
|
||||
Opcode.GOTO,
|
||||
Opcode.NOP,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
),
|
||||
listOf("FEmusic_history", "FEmusic_offline"),
|
||||
)
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package app.revanced.patches.music.layout.premium.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object HideGetPremiumParentFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||
Opcode.IGET_BOOLEAN,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC
|
||||
),
|
||||
listOf("FEmusic_history"),
|
||||
)
|
||||
@@ -1,71 +1,84 @@
|
||||
package app.revanced.patches.music.layout.upgradebutton
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.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.patcher.util.smali.toInstructions
|
||||
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
|
||||
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.BuilderInstruction22t
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch(
|
||||
name = "Remove upgrade button",
|
||||
description = "Removes the upgrade tab from the pivot bar.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object RemoveUpgradeButtonPatch : BytecodePatch(
|
||||
setOf(PivotBarConstructorFingerprint)
|
||||
setOf(PivotBarConstructorFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val result = PivotBarConstructorFingerprint.result!!
|
||||
val implementation = result.mutableMethod.implementation!!
|
||||
PivotBarConstructorFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val pivotBarElementFieldReference = getInstruction(it.scanResult.patternScanResult!!.endIndex - 1)
|
||||
.getReference<FieldReference>()
|
||||
|
||||
val pivotBarElementFieldRef =
|
||||
(implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference
|
||||
val register = (getInstructions().first() as Instruction35c).registerC
|
||||
|
||||
val register = (implementation.instructions.first() as Instruction35c).registerC
|
||||
// first compile all the needed instructions
|
||||
val instructionList = """
|
||||
invoke-interface { v0 }, Ljava/util/List;->size()I
|
||||
move-result v1
|
||||
const/4 v2, 0x4
|
||||
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
|
||||
iput-object v0, v$register, $pivotBarElementFieldRef
|
||||
""".toInstructions().toMutableList()
|
||||
// First compile all the needed instructions.
|
||||
val instructionList = """
|
||||
invoke-interface { v0 }, Ljava/util/List;->size()I
|
||||
move-result v1
|
||||
const/4 v2, 0x4
|
||||
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
|
||||
iput-object v0, v$register, $pivotBarElementFieldReference
|
||||
""".toInstructions().toMutableList()
|
||||
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
val endIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
// Replace the instruction to retain the label at given index.
|
||||
replaceInstruction(
|
||||
endIndex - 1,
|
||||
instructionList[0], // invoke-interface.
|
||||
)
|
||||
// Do not forget to remove this instruction since we added it already.
|
||||
instructionList.removeFirst()
|
||||
|
||||
// replace the instruction to retain the label at given index
|
||||
implementation.replaceInstruction(
|
||||
endIndex - 1, instructionList[0] // invoke-interface
|
||||
)
|
||||
// do not forget to remove this instruction since we added it already
|
||||
instructionList.removeFirst()
|
||||
val exitInstruction = instructionList.last() // iput-object
|
||||
addInstruction(
|
||||
endIndex,
|
||||
exitInstruction,
|
||||
)
|
||||
// Do not forget to remove this instruction since we added it already.
|
||||
instructionList.removeLast()
|
||||
|
||||
val exitInstruction = instructionList.last() // iput-object
|
||||
implementation.addInstruction(
|
||||
endIndex, exitInstruction
|
||||
)
|
||||
// do not forget to remove this instruction since we added it already
|
||||
instructionList.removeLast()
|
||||
// Add the necessary if statement to remove the upgrade tab button in case it exists.
|
||||
instructionList.add(
|
||||
2, // if-le.
|
||||
BuilderInstruction22t(
|
||||
Opcode.IF_LE,
|
||||
1,
|
||||
2,
|
||||
newLabel(endIndex),
|
||||
),
|
||||
)
|
||||
|
||||
// add the necessary if statement to remove the upgrade tab button in case it exists
|
||||
instructionList.add(
|
||||
2, // if-le
|
||||
BuilderInstruction22t(
|
||||
Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(endIndex)
|
||||
)
|
||||
)
|
||||
|
||||
implementation.addInstructions(
|
||||
endIndex, instructionList
|
||||
)
|
||||
addInstructions(
|
||||
endIndex,
|
||||
instructionList,
|
||||
)
|
||||
}
|
||||
} ?: throw PivotBarConstructorFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +1,19 @@
|
||||
package app.revanced.patches.music.layout.upgradebutton.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 PivotBarConstructorFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
listOf("L", "Z"),
|
||||
listOf(
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.GOTO,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.IGET,
|
||||
Opcode.CONST,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.GOTO,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.IGET,
|
||||
Opcode.CONST,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.GOTO,
|
||||
Opcode.NOP,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
)
|
||||
Opcode.RETURN_VOID,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2,12 +2,11 @@ package app.revanced.patches.music.misc.gms
|
||||
|
||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorOption
|
||||
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
|
||||
import app.revanced.patches.music.misc.gms.fingerprints.*
|
||||
import app.revanced.patches.music.misc.integrations.fingerprints.ApplicationInitFingerprint
|
||||
import app.revanced.patches.music.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
|
||||
import app.revanced.patches.shared.fingerprints.CastContextFetchFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
|
||||
|
||||
@Suppress("unused")
|
||||
object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
@@ -21,7 +20,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
CastContextFetchFingerprint,
|
||||
),
|
||||
mainActivityOnCreateFingerprint = ApplicationInitFingerprint,
|
||||
mainActivityOnCreateFingerprint = MusicActivityOnCreateFingerprint,
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
compatiblePackages = setOf(CompatiblePackage("com.google.android.apps.youtube.music")),
|
||||
@@ -32,7 +31,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
CastContextFetchFingerprint,
|
||||
PrimeMethodFingerprint,
|
||||
)
|
||||
),
|
||||
) {
|
||||
override val gmsCoreVendor by gmsCoreVendorOption
|
||||
override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.music.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object MusicActivityOnCreateFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
parameters = listOf("Landroid/os/Bundle;"),
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.type.endsWith("/MusicActivity;")
|
||||
}
|
||||
)
|
||||
@@ -1,14 +1,12 @@
|
||||
package app.revanced.patches.music.misc.gms.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
|
||||
|
||||
|
||||
internal object ServiceCheckFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
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)
|
||||
object IntegrationsPatch : BaseIntegrationsPatch(
|
||||
"Lapp/revanced/integrations/utils/ReVancedUtils;",
|
||||
setOf(
|
||||
ApplicationInitFingerprint,
|
||||
),
|
||||
setOf(ApplicationInitFingerprint),
|
||||
)
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
package app.revanced.patches.music.premium.backgroundplay
|
||||
|
||||
import app.revanced.util.exception
|
||||
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.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
|
||||
|
||||
|
||||
@Patch(
|
||||
name = "Background play",
|
||||
description = "Enables playing music in the background.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object BackgroundPlayPatch : BytecodePatch(setOf(BackgroundPlaybackDisableFingerprint)) {
|
||||
override fun execute(context: BytecodeContext) =
|
||||
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0, """
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
) ?: throw BackgroundPlaybackDisableFingerprint.exception
|
||||
}
|
||||
import app.revanced.patches.music.layout.minimizedplayback.MinimizedPlaybackPatch
|
||||
@Deprecated("This patch has been merged into MinimizedPlaybackPatch.")
|
||||
object BackgroundPlayPatch : BytecodePatch(
|
||||
dependencies = setOf(MinimizedPlaybackPatch::class),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package app.revanced.patches.music.premium.backgroundplay.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 BackgroundPlaybackDisableFingerprint : MethodFingerprint(
|
||||
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf(
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET,
|
||||
Opcode.AND_INT_LIT16,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.CONST,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.GOTO,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_BOOLEAN,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.RETURN,
|
||||
Opcode.RETURN,
|
||||
Opcode.RETURN
|
||||
)
|
||||
)
|
||||
@@ -6,23 +6,24 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import org.w3c.dom.Element
|
||||
|
||||
|
||||
@Patch(
|
||||
name = "Remove broadcasts restriction",
|
||||
description = "Enables starting/stopping NetGuard via broadcasts.",
|
||||
compatiblePackages = [CompatiblePackage("eu.faircode.netguard")],
|
||||
use = false
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object RemoveBroadcastsRestrictionPatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
||||
val applicationNode = dom
|
||||
.file
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
applicationNode.getElementsByTagName("receiver").also { list ->
|
||||
val applicationNode =
|
||||
document
|
||||
.getElementsByTagName("application")
|
||||
.item(0) as Element
|
||||
|
||||
applicationNode.getElementsByTagName("receiver").also { list ->
|
||||
for (i in 0 until list.length) {
|
||||
val element = list.item(i) as? Element ?: continue
|
||||
if (element.getAttribute("android:name") == "eu.faircode.netguard.WidgetAdmin") {
|
||||
|
||||
@@ -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"
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.xmlEditor[RESOURCE_FILE_PATH].use {
|
||||
it.file.getElementsByTagName("merge").item(0).childNodes.apply {
|
||||
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
document.getElementsByTagName("merge").item(0).childNodes.apply {
|
||||
val attributes = arrayOf("height", "width")
|
||||
|
||||
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.patches.reddit.ad.comments.fingerprints.HideCommentAdsFingerprint
|
||||
|
||||
@Patch(description = "Removes ads in the comments.",)
|
||||
@Patch(description = "Removes ads in the comments.")
|
||||
object HideCommentAdsPatch : BytecodePatch(
|
||||
setOf(HideCommentAdsFingerprint)
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.patches.reddit.customclients.ads
|
||||
|
||||
import app.revanced.patcher.PatchClass
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patches.reddit.customclients.ads.fingerprints.IsAdsEnabledFingerprint
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
abstract class BaseDisableAdsPatch(
|
||||
dependencies: Set<PatchClass> = emptySet(),
|
||||
compatiblePackages: Set<CompatiblePackage>,
|
||||
) : BytecodePatch(
|
||||
name = "Disable ads",
|
||||
dependencies = dependencies,
|
||||
compatiblePackages = compatiblePackages,
|
||||
fingerprints = setOf(IsAdsEnabledFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = listOf(IsAdsEnabledFingerprint).returnEarly()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints
|
||||
package app.revanced.patches.reddit.customclients.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -7,5 +7,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
internal object IsAdsEnabledFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
strings = listOf("SyncIapHelper")
|
||||
)
|
||||
strings = listOf("SyncIapHelper"),
|
||||
)
|
||||
@@ -5,6 +5,7 @@ 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.infinityforreddit.api.SpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints.BillingClientOnServiceConnected
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints.StartSubscriptionActivityFingerprint
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@@ -12,13 +13,14 @@ import app.revanced.util.returnEarly
|
||||
name = "Unlock subscription",
|
||||
description = "Unlocks the subscription feature but requires a custom client ID.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("ml.docilealligator.infinityforreddit")
|
||||
CompatiblePackage("ml.docilealligator.infinityforreddit"),
|
||||
],
|
||||
dependencies = [SpoofClientPatch::class]
|
||||
dependencies = [SpoofClientPatch::class],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object UnlockSubscriptionPatch : BytecodePatch(
|
||||
setOf(StartSubscriptionActivityFingerprint)
|
||||
setOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = listOf(StartSubscriptionActivityFingerprint).returnEarly()
|
||||
override fun execute(context: BytecodeContext) =
|
||||
listOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected).returnEarly()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object BillingClientOnServiceConnected : MethodFingerprint(
|
||||
strings = listOf("Billing service connected"),
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforlemmy.ads
|
||||
|
||||
import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
|
||||
|
||||
@Suppress("unused")
|
||||
object DisableAdsPatch : BaseDisableAdsPatch(
|
||||
dependencies = setOf(DisablePiracyDetectionPatch::class),
|
||||
compatiblePackages = setOf(CompatiblePackage("com.laurencedawson.reddit_sync")),
|
||||
)
|
||||
@@ -1,30 +1,8 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.ads
|
||||
|
||||
import app.revanced.util.exception
|
||||
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.ads.fingerprints.IsAdsEnabledFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
|
||||
import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch
|
||||
|
||||
@Patch(
|
||||
name = "Disable ads",
|
||||
dependencies = [DisablePiracyDetectionPatch::class],
|
||||
compatiblePackages = [CompatiblePackage("com.laurencedawson.reddit_sync")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisableAdsPatch : BytecodePatch(setOf(IsAdsEnabledFingerprint)) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
IsAdsEnabledFingerprint.result?.mutableMethod?.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
} ?: throw IsAdsEnabledFingerprint.exception
|
||||
}
|
||||
}
|
||||
object DisableAdsPatch : BaseDisableAdsPatch(
|
||||
compatiblePackages = setOf(CompatiblePackage("io.syncapps.lemmy_sync")),
|
||||
)
|
||||
|
||||
@@ -6,18 +6,13 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
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)) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// 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.
|
||||
PiracyDetectionFingerprint.result?.mutableMethod?.apply {
|
||||
addInstruction(
|
||||
0,
|
||||
"""
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
addInstruction(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: ")
|
||||
)
|
||||
@@ -2,7 +2,7 @@ package app.revanced.patches.shared.misc.gms
|
||||
|
||||
import app.revanced.patcher.PatchClass
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -12,7 +12,7 @@ import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AC
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_METHOD_NAME
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.returnEarly
|
||||
@@ -32,7 +32,7 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
* @param toPackageName The package name to fall back to if no custom package name is specified in patch options.
|
||||
* @param primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched.
|
||||
* @param earlyReturnFingerprints The fingerprints of methods that need to be returned early.
|
||||
* @param mainActivityOnCreateFingerprint The fingerprint of the main activity's onCreate method.
|
||||
* @param mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method.
|
||||
* @param integrationsPatchDependency The patch responsible for the integrations.
|
||||
* @param gmsCoreSupportResourcePatch The corresponding resource patch that is used to patch the resources.
|
||||
* @param dependencies Additional dependencies of this patch.
|
||||
@@ -53,22 +53,25 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
) : BytecodePatch(
|
||||
name = "GmsCore support",
|
||||
description = "Allows patched Google apps to run without root and under a different package name " +
|
||||
"by using GmsCore instead of Google Play Services.",
|
||||
"by using GmsCore instead of Google Play Services.",
|
||||
dependencies = setOf(
|
||||
ChangePackageNamePatch::class,
|
||||
gmsCoreSupportResourcePatch::class,
|
||||
integrationsPatchDependency
|
||||
integrationsPatchDependency,
|
||||
) + dependencies,
|
||||
compatiblePackages = compatiblePackages,
|
||||
fingerprints = setOf(GmsCoreSupportFingerprint, mainActivityOnCreateFingerprint) + fingerprints,
|
||||
requiresIntegrations = true
|
||||
fingerprints = setOf(
|
||||
GmsCoreSupportFingerprint,
|
||||
mainActivityOnCreateFingerprint,
|
||||
) + fingerprints,
|
||||
requiresIntegrations = true,
|
||||
) {
|
||||
init {
|
||||
// Manually register all options of the resource patch so that they are visible in the patch API.
|
||||
gmsCoreSupportResourcePatch.options.values.forEach(options::register)
|
||||
}
|
||||
|
||||
internal abstract val gmsCoreVendor: String?
|
||||
internal abstract val gmsCoreVendorGroupId: String?
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
|
||||
@@ -77,7 +80,7 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
val transformations = arrayOf(
|
||||
::commonTransform,
|
||||
::contentUrisTransform,
|
||||
packageNameTransform(fromPackageName, packageName)
|
||||
packageNameTransform(fromPackageName, packageName),
|
||||
)
|
||||
context.transformStringReferences transform@{ string ->
|
||||
transformations.forEach { transform ->
|
||||
@@ -93,16 +96,17 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
// Return these methods early to prevent the app from crashing.
|
||||
earlyReturnFingerprints.toList().returnEarly()
|
||||
|
||||
// Check the availability of GmsCore.
|
||||
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstruction(
|
||||
1, // Hack to not disturb other patches (such as the integrations patch).
|
||||
"invoke-static {}, Lapp/revanced/integrations/youtube/patches/GmsCoreSupport;->checkAvailability()V"
|
||||
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
|
||||
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" +
|
||||
"checkGmsCore(Landroid/app/Activity;)V",
|
||||
) ?: throw mainActivityOnCreateFingerprint.exception
|
||||
|
||||
// Change the vendor of GmsCore in ReVanced Integrations.
|
||||
GmsCoreSupportFingerprint.result?.mutableClass?.methods
|
||||
?.single { it.name == GET_GMS_CORE_VENDOR_METHOD_NAME }
|
||||
?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendor\"")
|
||||
?.single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME }
|
||||
?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"")
|
||||
?: throw GmsCoreSupportFingerprint.exception
|
||||
}
|
||||
|
||||
@@ -130,8 +134,8 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
BuilderInstruction21c(
|
||||
Opcode.CONST_STRING,
|
||||
instruction.registerA,
|
||||
ImmutableStringReference(transformedString)
|
||||
)
|
||||
ImmutableStringReference(transformedString),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -145,10 +149,11 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
"com.google.android.gms",
|
||||
in PERMISSIONS,
|
||||
in ACTIONS,
|
||||
in AUTHORITIES -> referencedString.replace("com.google", gmsCoreVendor!!)
|
||||
in AUTHORITIES,
|
||||
-> referencedString.replace("com.google", gmsCoreVendorGroupId!!)
|
||||
|
||||
// No vendor prefix for whatever reason...
|
||||
"subscribedfeeds" -> "$gmsCoreVendor.subscribedfeeds"
|
||||
"subscribedfeeds" -> "$gmsCoreVendorGroupId.subscribedfeeds"
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -161,7 +166,7 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
if (str.startsWith(uriPrefix)) {
|
||||
return str.replace(
|
||||
uriPrefix,
|
||||
"content://${authority.replace("com.google", gmsCoreVendor!!)}"
|
||||
"content://${authority.replace("com.google", gmsCoreVendorGroupId!!)}",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -169,18 +174,18 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
// gms also has a 'subscribedfeeds' authority, check for that one too
|
||||
val subFeedsUriPrefix = "content://subscribedfeeds"
|
||||
if (str.startsWith(subFeedsUriPrefix)) {
|
||||
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendor.subscribedfeeds")
|
||||
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.subscribedfeeds")
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
|
||||
}
|
||||
|
||||
private fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string ->
|
||||
when (string) {
|
||||
"$fromPackageName.SuggestionsProvider",
|
||||
"$fromPackageName.fileprovider" -> string.replace(fromPackageName, toPackageName)
|
||||
"$fromPackageName.fileprovider",
|
||||
-> string.replace(fromPackageName, toPackageName)
|
||||
|
||||
else -> null
|
||||
}
|
||||
@@ -273,6 +278,9 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
// fido
|
||||
"com.google.android.gms.fido.fido2.privileged.START",
|
||||
|
||||
// gass
|
||||
"com.google.android.gms.gass.START",
|
||||
|
||||
// games
|
||||
"com.google.android.gms.games.service.START",
|
||||
"com.google.android.gms.games.PLAY_GAMES_UPGRADE",
|
||||
@@ -292,8 +300,18 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
// misc
|
||||
"com.google.android.gms.gmscompliance.service.START",
|
||||
"com.google.android.gms.oss.licenses.service.START",
|
||||
"com.google.android.gms.tapandpay.service.BIND",
|
||||
"com.google.android.gms.measurement.START",
|
||||
"com.google.android.gms.languageprofile.service.START",
|
||||
"com.google.android.gms.clearcut.service.START",
|
||||
"com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE",
|
||||
|
||||
// potoken
|
||||
"com.google.android.gms.potokens.service.START",
|
||||
|
||||
// droidguard/ safetynet
|
||||
"com.google.android.gms.droidguard.service.START",
|
||||
"com.google.android.gms.safetynet.service.START",
|
||||
"com.google.android.gms.tapandpay.service.BIND"
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -314,9 +332,9 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
"com.google.android.gms.fonts",
|
||||
|
||||
// phenotype
|
||||
"com.google.android.gms.phenotype"
|
||||
"com.google.android.gms.phenotype",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,21 +22,25 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||
private val fromPackageName: String,
|
||||
private val toPackageName: String,
|
||||
private val spoofedPackageSignature: String,
|
||||
dependencies: Set<PatchClass> = setOf()
|
||||
dependencies: Set<PatchClass> = setOf(),
|
||||
) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class, AddResourcesPatch::class) + dependencies) {
|
||||
internal val gmsCoreVendorOption = stringPatchOption(
|
||||
key = "gmsCoreVendor",
|
||||
default = "com.mgoogle",
|
||||
values = mapOf(
|
||||
"Vanced" to "com.mgoogle",
|
||||
"ReVanced" to "app.revanced"
|
||||
),
|
||||
title = "GmsCore Vendor",
|
||||
description = "The group id of the GmsCore vendor.",
|
||||
required = true
|
||||
) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) }
|
||||
internal val gmsCoreVendorGroupIdOption =
|
||||
stringPatchOption(
|
||||
key = "gmsCoreVendorGroupId",
|
||||
default = "app.revanced",
|
||||
values =
|
||||
mapOf(
|
||||
"ReVanced" to "app.revanced",
|
||||
),
|
||||
title = "GmsCore vendor group ID",
|
||||
description = "The vendor's group ID for GmsCore.",
|
||||
required = true,
|
||||
) { it!!.matches(Regex(PACKAGE_NAME_REGEX_PATTERN)) }
|
||||
|
||||
protected val gmsCoreVendor by gmsCoreVendorOption
|
||||
protected val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
|
||||
|
||||
@Deprecated("Use gmsCoreVendorGroupId instead.", ReplaceWith("gmsCoreVendorGroupId"))
|
||||
protected val gmsCoreVendor by gmsCoreVendorGroupIdOption
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
AddResourcesPatch(BaseGmsCoreSupportResourcePatch::class)
|
||||
@@ -49,26 +53,31 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||
* Add metadata to manifest to support spoofing the package name and signature of GmsCore.
|
||||
*/
|
||||
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)
|
||||
child.block()
|
||||
appendChild(child)
|
||||
}
|
||||
|
||||
xmlEditor["AndroidManifest.xml"].use {
|
||||
val applicationNode = it
|
||||
.file
|
||||
.getElementsByTagName("application")
|
||||
.item(0)
|
||||
xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
val applicationNode =
|
||||
document
|
||||
.getElementsByTagName("application")
|
||||
.item(0)
|
||||
|
||||
// Spoof package name and signature.
|
||||
applicationNode.adoptChild("meta-data") {
|
||||
setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_NAME")
|
||||
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME")
|
||||
setAttribute("android:value", fromPackageName)
|
||||
}
|
||||
|
||||
applicationNode.adoptChild("meta-data") {
|
||||
setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_SIGNATURE")
|
||||
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_SIGNATURE")
|
||||
setAttribute("android:value", spoofedPackageSignature)
|
||||
}
|
||||
|
||||
@@ -76,7 +85,7 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||
applicationNode.adoptChild("meta-data") {
|
||||
// TODO: The name of this metadata should be dynamic.
|
||||
setAttribute("android:name", "app.revanced.MICROG_PACKAGE_NAME")
|
||||
setAttribute("android:value", "$gmsCoreVendor.android.gms")
|
||||
setAttribute("android:value", "$gmsCoreVendorGroupId.android.gms")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,27 +96,31 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||
private fun ResourceContext.patchManifest() {
|
||||
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
|
||||
|
||||
val manifest = this["AndroidManifest.xml"].readText()
|
||||
this["AndroidManifest.xml"].writeText(
|
||||
val manifest = this.get("AndroidManifest.xml").readText()
|
||||
this.get("AndroidManifest.xml").writeText(
|
||||
manifest.replace(
|
||||
"package=\"$fromPackageName",
|
||||
"package=\"$packageName"
|
||||
"package=\"$packageName",
|
||||
).replace(
|
||||
"android:authorities=\"$fromPackageName",
|
||||
"android:authorities=\"$packageName"
|
||||
"android:authorities=\"$packageName",
|
||||
).replace(
|
||||
"$fromPackageName.permission.C2D_MESSAGE",
|
||||
"$packageName.permission.C2D_MESSAGE"
|
||||
"$packageName.permission.C2D_MESSAGE",
|
||||
).replace(
|
||||
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
|
||||
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||
).replace(
|
||||
"com.google.android.c2dm",
|
||||
"$gmsCoreVendor.android.c2dm"
|
||||
"$gmsCoreVendorGroupId.android.c2dm",
|
||||
).replace(
|
||||
"</queries>",
|
||||
"<package android:name=\"$gmsCoreVendor.android.gms\"/></queries>"
|
||||
)
|
||||
"<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
internal object GmsCoreSupportFingerprint : MethodFingerprint(
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type.endsWith("GmsCoreSupport;")
|
||||
}
|
||||
},
|
||||
) {
|
||||
const val GET_GMS_CORE_VENDOR_METHOD_NAME = "getGmsCoreVendor"
|
||||
const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId"
|
||||
}
|
||||
|
||||
@@ -11,23 +11,25 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
|
||||
abstract class BaseIntegrationsPatch(
|
||||
private val hooks: Set<IntegrationsFingerprint>
|
||||
private val hooks: Set<IntegrationsFingerprint>,
|
||||
) : BytecodePatch(hooks) {
|
||||
|
||||
@Deprecated(
|
||||
"Use the constructor without the integrationsDescriptor parameter",
|
||||
ReplaceWith("AbstractIntegrationsPatch(hooks)")
|
||||
ReplaceWith("BaseIntegrationsPatch(hooks)"),
|
||||
)
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
constructor(
|
||||
integrationsDescriptor: String,
|
||||
hooks: Set<IntegrationsFingerprint>
|
||||
hooks: Set<IntegrationsFingerprint>,
|
||||
) : this(hooks)
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) throw PatchException(
|
||||
"Integrations have not been merged yet. This patch can not succeed without merging the integrations."
|
||||
)
|
||||
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) {
|
||||
throw PatchException(
|
||||
"Integrations have not been merged yet. This patch can not succeed without merging the integrations.",
|
||||
)
|
||||
}
|
||||
|
||||
hooks.forEach { hook ->
|
||||
hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
@@ -47,6 +49,7 @@ abstract class BaseIntegrationsPatch(
|
||||
opcodes: Iterable<Opcode?>? = null,
|
||||
strings: Iterable<String>? = null,
|
||||
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
|
||||
private val insertIndexResolver: ((Method) -> Int) = object : IHookInsertIndexResolver {},
|
||||
private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
|
||||
) : MethodFingerprint(
|
||||
returnType,
|
||||
@@ -54,20 +57,47 @@ abstract class BaseIntegrationsPatch(
|
||||
parameters,
|
||||
opcodes,
|
||||
strings,
|
||||
customFingerprint
|
||||
customFingerprint,
|
||||
) {
|
||||
@Deprecated("Previous constructor that is missing the insert index." +
|
||||
"Here only for binary compatibility, " +
|
||||
"and this can be removed after the next major version update.")
|
||||
constructor(
|
||||
returnType: String? = null,
|
||||
accessFlags: Int? = null,
|
||||
parameters: Iterable<String>? = null,
|
||||
opcodes: Iterable<Opcode?>? = null,
|
||||
strings: Iterable<String>? = null,
|
||||
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
|
||||
contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
|
||||
) : this(
|
||||
returnType,
|
||||
accessFlags,
|
||||
parameters,
|
||||
opcodes,
|
||||
strings,
|
||||
customFingerprint,
|
||||
object : IHookInsertIndexResolver {},
|
||||
contextRegisterResolver
|
||||
)
|
||||
|
||||
fun invoke(integrationsDescriptor: String) {
|
||||
result?.mutableMethod?.let { method ->
|
||||
val insertIndex = insertIndexResolver(method)
|
||||
val contextRegister = contextRegisterResolver(method)
|
||||
|
||||
method.addInstruction(
|
||||
0,
|
||||
"sput-object v$contextRegister, " +
|
||||
"$integrationsDescriptor->context:Landroid/content/Context;"
|
||||
insertIndex,
|
||||
"invoke-static/range { v$contextRegister .. v$contextRegister }, " +
|
||||
"$integrationsDescriptor->setContext(Landroid/content/Context;)V",
|
||||
)
|
||||
} ?: throw PatchException("Could not find hook target fingerprint.")
|
||||
}
|
||||
|
||||
interface IHookInsertIndexResolver : (Method) -> Int {
|
||||
override operator fun invoke(method: Method) = 0
|
||||
}
|
||||
|
||||
interface IRegisterResolver : (Method) -> Int {
|
||||
override operator fun invoke(method: Method) = method.implementation!!.registerCount - 1
|
||||
}
|
||||
@@ -76,4 +106,4 @@ abstract class BaseIntegrationsPatch(
|
||||
private companion object {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/shared/Utils;"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
object ResourceMappingPatch : ResourcePatch() {
|
||||
internal lateinit var resourceMappings: List<ResourceElement>
|
||||
private set
|
||||
@@ -17,7 +16,7 @@ object ResourceMappingPatch : ResourcePatch() {
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
// 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
|
||||
val mappings = Collections.synchronizedList(mutableListOf<ResourceElement>())
|
||||
@@ -25,7 +24,9 @@ object ResourceMappingPatch : ResourcePatch() {
|
||||
for (threadIndex in 0 until THREAD_COUNT) {
|
||||
threadPoolExecutor.execute thread@{
|
||||
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 jobSize = resourcesLength / THREAD_COUNT
|
||||
|
||||
@@ -59,4 +60,4 @@ object ResourceMappingPatch : ResourcePatch() {
|
||||
}
|
||||
|
||||
data class ResourceElement(val type: String, val name: String, val id: Long)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,18 @@ import java.io.Closeable
|
||||
*/
|
||||
abstract class BaseSettingsResourcePatch(
|
||||
private val rootPreference: Pair<IntentPreference, String>? = null,
|
||||
dependencies: Set<PatchClass> = emptySet()
|
||||
dependencies: Set<PatchClass> = emptySet(),
|
||||
) : ResourcePatch(
|
||||
dependencies = setOf(AddResourcesPatch::class) + dependencies
|
||||
), MutableSet<BasePreference> by mutableSetOf(), Closeable {
|
||||
dependencies = setOf(AddResourcesPatch::class) + dependencies,
|
||||
),
|
||||
MutableSet<BasePreference> by mutableSetOf(),
|
||||
Closeable {
|
||||
private lateinit var context: ResourceContext
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.copyResources(
|
||||
"settings",
|
||||
ResourceGroup("xml", "revanced_prefs.xml")
|
||||
ResourceGroup("xml", "revanced_prefs.xml"),
|
||||
)
|
||||
|
||||
this.context = context
|
||||
@@ -39,24 +41,34 @@ abstract class BaseSettingsResourcePatch(
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
fun Node.addPreference(preference: BasePreference) {
|
||||
fun Node.addPreference(preference: BasePreference, prepend: Boolean = false) {
|
||||
preference.serialize(ownerDocument) { resource ->
|
||||
// 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.
|
||||
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.
|
||||
rootPreference?.let { (intentPreference, fragment) ->
|
||||
context.xmlEditor["res/xml/$fragment.xml"].use {
|
||||
it.getNode("PreferenceScreen").addPreference(intentPreference)
|
||||
context.xmlEditor["res/xml/$fragment.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
|
||||
document.getNode("PreferenceScreen").addPreference(intentPreference, true)
|
||||
}
|
||||
}
|
||||
|
||||
// Add all preferences to the ReVanced fragment.
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package app.revanced.patches.shared.misc.settings.preference
|
||||
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||
import java.io.Closeable
|
||||
|
||||
abstract class BasePreferenceScreen(
|
||||
private val root: MutableSet<Screen> = mutableSetOf()
|
||||
private val root: MutableSet<Screen> = mutableSetOf(),
|
||||
) : Closeable {
|
||||
|
||||
override fun close() {
|
||||
@@ -24,33 +25,27 @@ abstract class BasePreferenceScreen(
|
||||
titleKey: String = "${key}_title",
|
||||
private val summaryKey: String? = "${key}_summary",
|
||||
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) {
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return PreferenceScreen(
|
||||
key,
|
||||
titleKey,
|
||||
summaryKey,
|
||||
sorting,
|
||||
// Screens and preferences are sorted at runtime by integrations code,
|
||||
// so they appear in alphabetical order for the localized language in use.
|
||||
preferences = preferences + categories.map { it.transform() }
|
||||
// so title sorting uses the localized language in use.
|
||||
preferences = preferences + categories.map { it.transform() },
|
||||
)
|
||||
}
|
||||
|
||||
private fun ensureScreenInserted() {
|
||||
// Add to screens if not yet done
|
||||
if (!root.contains(this))
|
||||
if (!root.contains(this)) {
|
||||
root.add(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun addPreferences(vararg preferences: BasePreference) {
|
||||
@@ -61,13 +56,13 @@ abstract class BasePreferenceScreen(
|
||||
open inner class Category(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
preferences: MutableSet<BasePreference> = mutableSetOf()
|
||||
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||
) : BasePreferenceCollection(key, titleKey, preferences) {
|
||||
override fun transform(): PreferenceCategory {
|
||||
return PreferenceCategory(
|
||||
key,
|
||||
titleKey,
|
||||
preferences = preferences
|
||||
preferences = preferences,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,8 +70,9 @@ abstract class BasePreferenceScreen(
|
||||
ensureScreenInserted()
|
||||
|
||||
// Add to the categories if not done yet.
|
||||
if (!categories.contains(this))
|
||||
if (!categories.contains(this)) {
|
||||
categories.add(this)
|
||||
}
|
||||
|
||||
this.preferences.addAll(preferences)
|
||||
}
|
||||
@@ -86,8 +82,8 @@ abstract class BasePreferenceScreen(
|
||||
abstract class BasePreferenceCollection(
|
||||
val key: String? = null,
|
||||
val titleKey: String = "${key}_title",
|
||||
val preferences: MutableSet<BasePreference> = mutableSetOf()
|
||||
val preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||
) {
|
||||
abstract fun transform(): BasePreference
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
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 org.w3c.dom.Document
|
||||
|
||||
/**
|
||||
* 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 summaryKey The preference summary key.
|
||||
* @param tag The preference tag.
|
||||
* @param intent The intent to open.
|
||||
*
|
||||
* @see Intent
|
||||
*/
|
||||
class IntentPreference(
|
||||
key: String? = null,
|
||||
@@ -21,7 +18,7 @@ class IntentPreference(
|
||||
summaryKey: String? = "${key}_summary",
|
||||
tag: String = "Preference",
|
||||
val intent: Intent,
|
||||
) : BasePreference(null, titleKey, summaryKey, tag) {
|
||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
|
||||
@@ -6,10 +6,12 @@ import org.w3c.dom.Document
|
||||
/**
|
||||
* 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 summaryKey The preference summary key.
|
||||
* @param tag The preference tag.
|
||||
* @param selectable Whether the preference is selectable.
|
||||
* @param tag The tag or full class name of the preference.
|
||||
* @param selectable If the preference is selectable and responds to tap events.
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
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 titleKey The key of the preference title.
|
||||
* @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 preferences The preferences in this screen.
|
||||
*/
|
||||
@@ -17,14 +19,40 @@ open class PreferenceScreen(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
sorting: Sorting = Sorting.BY_TITLE,
|
||||
tag: String = "PreferenceScreen",
|
||||
val preferences: Set<BasePreference>
|
||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||
|
||||
val preferences: Set<BasePreference>,
|
||||
// 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) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
preferences.forEach {
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user