mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-15 15:33:13 +00:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdab92faf2 | ||
|
|
50acd3d3b5 | ||
|
|
49a369a340 | ||
|
|
be8620bf91 | ||
|
|
32ed4c9f04 | ||
|
|
9c44497d40 | ||
|
|
8e604139e3 | ||
|
|
3de3a82afb | ||
|
|
d39fb7ca03 | ||
|
|
2d995d3757 | ||
|
|
464c98093a | ||
|
|
6ac5ed441f | ||
|
|
7925ca97c4 | ||
|
|
0c5f117d5d | ||
|
|
6ab475c284 | ||
|
|
75ac69455b | ||
|
|
e42043b939 | ||
|
|
5237c3a1a6 | ||
|
|
7d6f205fd9 | ||
|
|
f82aae930b | ||
|
|
83b11c92af | ||
|
|
a9abab97d7 | ||
|
|
a70da4f6c4 | ||
|
|
e53b490edf | ||
|
|
bfe995f635 | ||
|
|
19cc4a3e91 | ||
|
|
16f6486258 | ||
|
|
47360ea3b7 | ||
|
|
5c5b3d562d | ||
|
|
a62316a8c8 | ||
|
|
14f7d514d2 | ||
|
|
78d901338f | ||
|
|
9ae3d0546c | ||
|
|
3076a16d14 | ||
|
|
f8e1f2fe18 | ||
|
|
a9611f304e | ||
|
|
7c0e183df5 | ||
|
|
15e1ced2c9 | ||
|
|
bde7f99b5b | ||
|
|
60866af97d | ||
|
|
6580f71392 | ||
|
|
9c57961680 | ||
|
|
1d7a9ac437 | ||
|
|
51e08fb0b6 | ||
|
|
91feea1c50 | ||
|
|
fc8bfff427 | ||
|
|
9a3307c1b1 | ||
|
|
eff806c5e3 | ||
|
|
b45a44ff3f | ||
|
|
391e8fa8f6 | ||
|
|
dbf0668f28 | ||
|
|
b228640e4f | ||
|
|
0ddb2df640 | ||
|
|
c9525d0c26 | ||
|
|
3c5832eda2 | ||
|
|
eef7e87bbf | ||
|
|
535f621f20 | ||
|
|
695a0d14ad | ||
|
|
f70e54545b | ||
|
|
353f036a72 |
61
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
Normal file
61
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: 🐞 Bug report
|
||||
description: Report a very clearly broken issue.
|
||||
title: 'bug: <title>'
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ReVanced bug report
|
||||
|
||||
Important to note that your issue may have already been reported before. Please check for existing issues [here](https://github.com/revanced/revanced-patches/labels/bug).
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Error while patching
|
||||
- Error at runtime
|
||||
- Cosmetic
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: How did you find the bug? Any additional details that might help?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Add the steps to reproduce this bug including your environment.
|
||||
placeholder: Step 1. Download some files. Step 2. ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots or videos
|
||||
description: Add screenshots or videos that show the bug here.
|
||||
placeholder: Drag and drop the screenshots/videos into this box.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Solution
|
||||
description: If applicable, add a possible solution.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
validations:
|
||||
required: false
|
||||
24
.github/ISSUE_TEMPLATE/bug-report.md
vendored
24
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report on patches
|
||||
title: 'problem: `some-patch`'
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## 🐞 Issue
|
||||
|
||||
<!-- Describe your issue in detail here -->
|
||||
|
||||
## ⚙ Reproduce
|
||||
|
||||
<!-- Include your environment and steps to reproduce the issue as detailed as possible -->
|
||||
|
||||
## 🛠 Solution
|
||||
|
||||
<!-- If applicable, add a possible solution -->
|
||||
|
||||
## ⚠ Additional context
|
||||
|
||||
<!-- Add any other context about the problem here -->
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📃 Documentation
|
||||
url: https://github.com/revanced/revanced-documentation/
|
||||
about: Don't know how or where to start? Check out our documentation!
|
||||
- name: 🗨 Discussions
|
||||
url: https://github.com/revanced/revanced-suggestions/discussions
|
||||
about: Got something you think should change or be added? Search for or start a new discussion!
|
||||
46
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
Normal file
46
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: ⭐ Feature request
|
||||
description: Create a detailed feature request.
|
||||
title: 'feat: <title>'
|
||||
labels: [feature-request]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ReVanced feature request
|
||||
|
||||
Do not submit requests for patches here. Please submit them [here](https://github.com/orgs/revanced/discussions/categories/patches) instead.
|
||||
Important to note that your feature request may have already been made before. Please check for existing feature requests [here](https://github.com/revanced/revanced-patches/labels/feature-request).
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Functionality
|
||||
- Cosmetic
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue
|
||||
description: What is the current problem. Why does it require a feature request?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature
|
||||
description: Describe your feature in detail. How does it solve the issue?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Why should your feature should be considered?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
validations:
|
||||
required: false
|
||||
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest a change to some patch. Do not submit suggestions for patches here.
|
||||
title: 'feat: some feature'
|
||||
labels: feature-request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## 🐞 Issue
|
||||
|
||||
<!-- Explain here, what the current problem is and why it leads you to request a feature change -->
|
||||
|
||||
## ❗ Solution
|
||||
|
||||
<!-- Explain how your current issue can be solved -->
|
||||
|
||||
## ❓ Motivation
|
||||
|
||||
<!-- Explain why your feature should be considered -->
|
||||
|
||||
## ⚠ Additional context
|
||||
|
||||
<!-- Add any other context or screenshots about the feature request here -->
|
||||
142
CHANGELOG.md
142
CHANGELOG.md
@@ -1,3 +1,145 @@
|
||||
## [2.33.2](https://github.com/revanced/revanced-patches/compare/v2.33.1...v2.33.2) (2022-08-07)
|
||||
|
||||
## [2.33.1](https://github.com/revanced/revanced-patches/compare/v2.33.0...v2.33.1) (2022-08-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* spoof `X-Android-Cert` of Firebase `authToken` api request ([#315](https://github.com/revanced/revanced-patches/issues/315)) ([c81d61f](https://github.com/revanced/revanced-patches/commit/c81d61f685449590473fa5205e7709f81872a9b9))
|
||||
|
||||
# [2.33.0](https://github.com/revanced/revanced-patches/compare/v2.32.1...v2.33.0) (2022-08-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* bump music patches to 5.17.51 ([#307](https://github.com/revanced/revanced-patches/issues/307)) ([c303589](https://github.com/revanced/revanced-patches/commit/c303589bd8d1956ce2e3c4c285d45a648b5db30f))
|
||||
|
||||
## [2.32.1](https://github.com/revanced/revanced-patches/compare/v2.32.0...v2.32.1) (2022-08-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* incorrect compatibilty attribute ([#296](https://github.com/revanced/revanced-patches/issues/296)) ([0ab3e97](https://github.com/revanced/revanced-patches/commit/0ab3e9724157c628555964273c6b65f9f48f9664))
|
||||
|
||||
# [2.32.0](https://github.com/revanced/revanced-patches/compare/v2.31.0...v2.32.0) (2022-08-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `promo-code-unlock` patch ([#292](https://github.com/revanced/revanced-patches/issues/292)) ([d5df2e6](https://github.com/revanced/revanced-patches/commit/d5df2e68f47cbb3d374b8ce24769872959014051))
|
||||
|
||||
# [2.31.0](https://github.com/revanced/revanced-patches/compare/v2.30.1...v2.31.0) (2022-08-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove `force-vp9-codec` patch ([#287](https://github.com/revanced/revanced-patches/issues/287)) ([e428978](https://github.com/revanced/revanced-patches/commit/e42897801b20e7439969954753e2c15c85eb41b5))
|
||||
|
||||
## [2.30.1](https://github.com/revanced/revanced-patches/compare/v2.30.0...v2.30.1) (2022-08-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* migrate to new patcher api ([f43446e](https://github.com/revanced/revanced-patches/commit/f43446ed189e583302fcd899f5eb7517f2a77144))
|
||||
|
||||
# [2.30.0](https://github.com/revanced/revanced-patches/compare/v2.29.0...v2.30.0) (2022-08-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* incorrect fingerprint version [skip ci] ([f8c62ae](https://github.com/revanced/revanced-patches/commit/f8c62ae16b088ff6d0e96a4ef62dc707cd83beb9))
|
||||
* rollback to `Dependencies` annotation ([36a2ae8](https://github.com/revanced/revanced-patches/commit/36a2ae886c63f1d22bb1cca9e7110af6c3f6f2d3))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* set the correct theme of the settings screen ([70d850c](https://github.com/revanced/revanced-patches/commit/70d850cf295d306b0de9419efe6a4bbf3857d3a0))
|
||||
|
||||
# [2.29.0](https://github.com/revanced/revanced-patches/compare/v2.28.2...v2.29.0) (2022-08-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add "Application Icon Path" option to branding ([1748d1e](https://github.com/revanced/revanced-patches/commit/1748d1e5badf61213d793ff7ae1d090ea2ea82f0))
|
||||
* add "Application Name" option to branding and move renaming to CustomBrandingPatch.kt ([8dafe05](https://github.com/revanced/revanced-patches/commit/8dafe05b2c5e2b0291d46b02717d910721673712))
|
||||
|
||||
## [2.28.2](https://github.com/revanced/revanced-patches/compare/v2.28.1...v2.28.2) (2022-08-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove requirement for solution [skip ci] ([#271](https://github.com/revanced/revanced-patches/issues/271)) ([553fad3](https://github.com/revanced/revanced-patches/commit/553fad3fe1bb79bdf34e9f91c0e1cbfda78e1054))
|
||||
|
||||
## [2.28.1](https://github.com/revanced/revanced-patches/compare/v2.28.0...v2.28.1) (2022-07-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing permission to reboot app ([#260](https://github.com/revanced/revanced-patches/issues/260)) ([6ced6df](https://github.com/revanced/revanced-patches/commit/6ced6df8ed7642dea51e1acd1c12f4de4874b972))
|
||||
|
||||
# [2.28.0](https://github.com/revanced/revanced-patches/compare/v2.27.0...v2.28.0) (2022-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `custom-video-buffer` patch ([9f117c7](https://github.com/revanced/revanced-patches/commit/9f117c74cdbdcf98eae97cf4c37f0baca451d695))
|
||||
|
||||
# [2.27.0](https://github.com/revanced/revanced-patches/compare/v2.26.0...v2.27.0) (2022-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `settings` patch ([0e229a4](https://github.com/revanced/revanced-patches/commit/0e229a46cb5b8b74183c47a6eae08d667f941406))
|
||||
|
||||
# [2.26.0](https://github.com/revanced/revanced-patches/compare/v2.25.3...v2.26.0) (2022-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `ResourceUtils` helper class ([e0e1144](https://github.com/revanced/revanced-patches/commit/e0e11447a7ac184d43c75955854c52c6992ff667))
|
||||
|
||||
## [2.25.3](https://github.com/revanced/revanced-patches/compare/v2.25.2...v2.25.3) (2022-07-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* actually call `VideoInformation.setCurrentVideoId` first ([5c62d0a](https://github.com/revanced/revanced-patches/commit/5c62d0a2e0217de1b9563a41b4e94ed63230440f))
|
||||
|
||||
## [2.25.2](https://github.com/revanced/revanced-patches/compare/v2.25.1...v2.25.2) (2022-07-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* rename `default-video-quality` to `remember-video-quality` ([7f6cdfd](https://github.com/revanced/revanced-patches/commit/7f6cdfd7c2b5e72742bbb92e4d584f722cb82cae))
|
||||
|
||||
## [2.25.1](https://github.com/revanced/revanced-patches/compare/v2.25.0...v2.25.1) (2022-07-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `default-video-quality` patch crashing ([#227](https://github.com/revanced/revanced-patches/issues/227)) ([379327a](https://github.com/revanced/revanced-patches/commit/379327a6b2325ef93c7107472343dd9fd85a0f56))
|
||||
|
||||
# [2.25.0](https://github.com/revanced/revanced-patches/compare/v2.24.0...v2.25.0) (2022-07-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `general-reddit-ads` patch ([#235](https://github.com/revanced/revanced-patches/issues/235)) ([d63c016](https://github.com/revanced/revanced-patches/commit/d63c016d38d2a5b1d152abccdb582990987a1911))
|
||||
|
||||
# [2.24.0](https://github.com/revanced/revanced-patches/compare/v2.23.0...v2.24.0) (2022-07-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* `music-microg-support` patch ([#208](https://github.com/revanced/revanced-patches/issues/208)) ([50863e9](https://github.com/revanced/revanced-patches/commit/50863e97cc8eba7e1ad6d11b4821baa45fdd29c4))
|
||||
|
||||
# [2.23.0](https://github.com/revanced/revanced-patches/compare/v2.22.2...v2.23.0) (2022-07-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* bump compatibility of YouTube Music patches to v5.16.51 ([#238](https://github.com/revanced/revanced-patches/issues/238)) ([4fa2a12](https://github.com/revanced/revanced-patches/commit/4fa2a127d715f953a1e4efacaecbc218209a01f3))
|
||||
|
||||
## [2.22.2](https://github.com/revanced/revanced-patches/compare/v2.22.1...v2.22.2) (2022-07-26)
|
||||
|
||||
|
||||
|
||||
42
README.md
42
README.md
@@ -9,6 +9,15 @@ Official patches by ReVanced
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `timeline-ads` | Removes ads from the Twitter timeline. | all |
|
||||
</details>
|
||||
|
||||
### 📦 `com.reddit.frontpage`
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
|
||||
</details>
|
||||
|
||||
### 📦 `com.google.android.apps.youtube.music`
|
||||
@@ -16,14 +25,24 @@ Official patches by ReVanced
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | 5.14.53 |
|
||||
| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | 5.14.53 |
|
||||
| `compact-header` | Hides the music category bar at the top of the homepage. | 5.14.53 |
|
||||
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | 5.14.53 |
|
||||
| `background-play` | Enables playing music in the background. | 5.14.53 |
|
||||
| `music-video-ads` | Removes ads in the music player. | 5.14.53 |
|
||||
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | 5.14.53 |
|
||||
| `exclusive-audio-playback` | Enables the option to play music without video. | 5.14.53 |
|
||||
| `minimized-playback-music` | Enables minimized playback on Kids music. | 5.17.51 |
|
||||
| `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | 5.16.51 |
|
||||
| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | 5.17.51 |
|
||||
| `compact-header` | Hides the music category bar at the top of the homepage. | 5.16.51 |
|
||||
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | 5.17.51 |
|
||||
| `background-play` | Enables playing music in the background. | 5.17.51 |
|
||||
| `music-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | 5.17.51 |
|
||||
| `music-video-ads` | Removes ads in the music player. | 5.17.51 |
|
||||
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | 5.17.51 |
|
||||
| `exclusive-audio-playback` | Enables the option to play music without video. | 5.17.51 |
|
||||
</details>
|
||||
|
||||
### 📦 `de.dwd.warnapp`
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all |
|
||||
</details>
|
||||
|
||||
### 📦 `com.google.android.youtube`
|
||||
@@ -31,6 +50,7 @@ Official patches by ReVanced
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `swipe-controls` | Adds volume and brightness swipe controls. | 17.29.34 |
|
||||
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 17.29.34 |
|
||||
| `minimized-playback` | Enables minimized and background playback. | 17.29.34 |
|
||||
| `amoled` | Enables pure black theme. | 17.29.34 |
|
||||
@@ -39,19 +59,21 @@ Official patches by ReVanced
|
||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 17.29.34 |
|
||||
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 17.29.34 |
|
||||
| `premium-heading` | Shows premium branding on the home screen. | all |
|
||||
| `custom-branding` | Changes the YouTube launcher icon to be ReVanced's. | all |
|
||||
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
|
||||
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 17.29.34 |
|
||||
| `old-quality-layout` | Enables the original quality flyout menu. | 17.29.34 |
|
||||
| `hide-shorts-button` | Hides the shorts button on the navigation bar. | 17.29.34 |
|
||||
| `hide-watermark` | Hides creator's watermarks on videos. | 17.29.34 |
|
||||
| `sponsorblock` | Integrate SponsorBlock. | 17.29.34 |
|
||||
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 17.29.34 |
|
||||
| `force-vp9-codec` | Forces the VP9 codec for videos. | 17.29.34 |
|
||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 17.29.34 |
|
||||
| `always-autorepeat` | Always repeats the playing video again. | 17.29.34 |
|
||||
| `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG | 17.29.34 |
|
||||
| `settings` | Adds settings for ReVanced to YouTube. | all |
|
||||
| `enable-debugging` | Enables app debugging by patching the manifest file. | all |
|
||||
| `custom-playback-speed` | Adds more video playback speed options. | 17.29.34 |
|
||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 17.29.34 |
|
||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 17.29.34 |
|
||||
| `video-ads` | Removes ads in the video player. | 17.29.34 |
|
||||
| `general-ads` | Removes general ads. | 17.29.34 |
|
||||
| `hide-infocard-suggestions` | Hides infocards in videos. | 17.29.34 |
|
||||
|
||||
@@ -22,7 +22,7 @@ repositories {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
|
||||
implementation("app.revanced:revanced-patcher:2.4.0")
|
||||
implementation("app.revanced:revanced-patcher:3.3.2")
|
||||
implementation("app.revanced:multidexlib2:2.5.2.r2")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
kotlin.code.style = official
|
||||
version = 2.22.2
|
||||
version = 2.33.2
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
import org.w3c.dom.Node
|
||||
import java.io.OutputStream
|
||||
import java.nio.file.Files
|
||||
|
||||
// TODO: this method does not make sense here
|
||||
@@ -146,7 +145,7 @@ fun ResourceData.injectStrings(
|
||||
// open source strings.xml
|
||||
val sourceInputStream = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath")
|
||||
?: throw PatchResultError("failed to open '$patchDirectoryPath/$relativePath'")
|
||||
xmlEditor[sourceInputStream, OutputStream.nullOutputStream()].use { sourceStringsXml ->
|
||||
xmlEditor[sourceInputStream].use { sourceStringsXml ->
|
||||
val strings = sourceStringsXml.file.getElementsByTagName("resources").item(0).childNodes
|
||||
|
||||
// open target strings.xml
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||
import app.revanced.patcher.extensions.PatchExtensions.description
|
||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.util.patch.implementation.JarPatchBundle
|
||||
import app.revanced.patcher.util.patch.impl.JarPatchBundle
|
||||
import java.io.File
|
||||
|
||||
object Generator {
|
||||
@@ -27,7 +27,11 @@ object Generator {
|
||||
|
||||
bundle.map {
|
||||
val packageName = it.compatiblePackages?.first()?.name!!
|
||||
packages.getOrElse(packageName) { packages.put(packageName, mutableListOf()) }?.add(it)
|
||||
if (!packages.contains(packageName)) {
|
||||
packages[packageName] = mutableListOf()
|
||||
}
|
||||
|
||||
packages[packageName]?.add(it)
|
||||
}
|
||||
|
||||
for (pkg in packages) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
|
||||
@@ -5,10 +5,9 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class CodecsUnlockCompatibility
|
||||
|
||||
|
||||
@@ -12,17 +12,14 @@ import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("codec-lock-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Labwj;",
|
||||
"Lacfr;",
|
||||
"a",
|
||||
)
|
||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||
@CodecsUnlockCompatibility
|
||||
@Version("0.0.1")
|
||||
object CodecsLockFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L", "L"), listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, null, listOf(
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
@@ -37,5 +34,6 @@ object CodecsLockFingerprint : MethodFingerprint(
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.RETURN_OBJECT
|
||||
)
|
||||
)
|
||||
),
|
||||
listOf("eac3_supported")
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ import app.revanced.patcher.util.smali.toInstruction
|
||||
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
||||
import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint
|
||||
import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Patch
|
||||
@Name("codecs-unlock")
|
||||
@@ -25,19 +26,29 @@ class CodecsUnlockPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
var result = CodecsLockFingerprint.result!!
|
||||
val codecsLockResult = CodecsLockFingerprint.result!!
|
||||
|
||||
val implementation = result.mutableMethod.implementation!!
|
||||
val implementation = codecsLockResult.mutableMethod.implementation!!
|
||||
|
||||
val instructionIndex = result.patternScanResult!!.startIndex
|
||||
val scanResultStartIndex = codecsLockResult.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
|
||||
}
|
||||
|
||||
result = AllCodecsReferenceFingerprint.result!!
|
||||
val codecMethod =
|
||||
data.toMethodWalker(result.method).nextMethod(result.patternScanResult!!.startIndex).getMethod()
|
||||
val allCodecsResult = AllCodecsReferenceFingerprint.result!!
|
||||
val allCodecsMethod =
|
||||
data.toMethodWalker(allCodecsResult.method)
|
||||
.nextMethod(allCodecsResult.patternScanResult!!.startIndex)
|
||||
.getMethod()
|
||||
|
||||
implementation.replaceInstruction(
|
||||
instructionIndex,
|
||||
"invoke-static {}, ${codecMethod.definingClass}->${codecMethod.name}()Ljava/util/Set;".toInstruction()
|
||||
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction()
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
|
||||
@@ -5,10 +5,9 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class ExclusiveAudioCompatibility
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
|
||||
@@ -5,10 +5,9 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class HideGetPremiumCompatibility
|
||||
|
||||
|
||||
@@ -3,12 +3,16 @@ package app.revanced.patches.music.layout.tastebuilder.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
/**
|
||||
* -- Note 2022-08-05 --
|
||||
* Since 5.17.xx the tastebuilder component is dismissible, so this patch is less useful
|
||||
* also it is partly litho now
|
||||
*/
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class RemoveTasteBuilderCompatibility
|
||||
|
||||
|
||||
@@ -5,10 +5,9 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class RemoveUpgradeButtonCompatibility
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.music.misc.microg.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class MusicMicroGPatchCompatibility
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.music.misc.microg.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("google-play-utility-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lnuv;", "b"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@MusicMicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
object GooglePlayUtilityFingerprint : MethodFingerprint(
|
||||
"I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), null, listOf("This should never happen.", "MetadataValueReader", "GooglePlayServicesUtil", "com.android.vending", "android.hardware.type.embedded")
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.patches.music.misc.microg.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||
|
||||
@Name("google-play-prime-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lrwi;", "a"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@MusicMicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
object PrimeFingerprint : MethodFingerprint(
|
||||
null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending")
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.music.misc.microg.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("google-play-service-checker-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lnuv;", "d"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||
@MusicMicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
object ServiceCheckFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), null, listOf("Google Play Services not available")
|
||||
)
|
||||
@@ -0,0 +1,160 @@
|
||||
package app.revanced.patches.music.misc.microg.patch.bytecode
|
||||
|
||||
import app.revanced.extensions.equalsAny
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||
import app.revanced.patches.music.misc.microg.patch.resource.MusicMicroGResourcePatch
|
||||
import app.revanced.patches.youtube.misc.microg.patch.resource.enum.StringReplaceMode
|
||||
import app.revanced.patches.music.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.microg.fingerprints.*
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.MutableMethodImplementation
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
|
||||
import org.jf.dexlib2.iface.reference.StringReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
||||
|
||||
@Patch
|
||||
@DependsOn([MusicMicroGResourcePatch::class])
|
||||
@Name("music-microg-support")
|
||||
@Description("Allows YouTube Music ReVanced to run without root and under a different package name.")
|
||||
@MusicMicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
class MusicMicroGBytecodePatch : BytecodePatch(
|
||||
listOf(
|
||||
ServiceCheckFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
PrimeFingerprint,
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
disablePlayServiceChecks()
|
||||
data.classes.forEach { classDef ->
|
||||
var proxiedClass: MutableClass? = null
|
||||
|
||||
classDef.methods.forEach methodLoop@{ method ->
|
||||
val implementation = method.implementation ?: return@methodLoop
|
||||
|
||||
var proxiedImplementation: MutableMethodImplementation? = null
|
||||
|
||||
implementation.instructions.forEachIndexed { i, instruction ->
|
||||
if (instruction.opcode != Opcode.CONST_STRING) return@forEachIndexed
|
||||
|
||||
val stringValue = ((instruction as Instruction21c).reference as StringReference).string
|
||||
|
||||
val replaceMode = if (stringValue.equalsAny(
|
||||
"com.google.android.gms",
|
||||
"com.google.android.gms.chimera",
|
||||
"com.google.android.c2dm.intent.REGISTER",
|
||||
"com.google.android.c2dm.permission.SEND",
|
||||
"com.google.iid.TOKEN_REQUEST",
|
||||
"com.google",
|
||||
"com.google.android.gms.chimera.GmsIntentOperationService",
|
||||
"com.google.android.gms.phenotype.internal.IPhenotypeCallbacks",
|
||||
"com.google.android.gms.phenotype.internal.IPhenotypeService",
|
||||
"com.google.android.gms.phenotype.service.START",
|
||||
"com.google.android.gms.phenotype.PACKAGE_NAME",
|
||||
"com.google.android.gms.phenotype.UPDATE",
|
||||
"com.google.android.gms.phenotype",
|
||||
"com.google.android.gms.auth.accounts",
|
||||
"com.google.android.c2dm.intent.REGISTRATION",
|
||||
"com.google.android.gsf.action.GET_GLS",
|
||||
"com.google.android.gsf.login",
|
||||
"content://com.google.settings/partner",
|
||||
"content://com.google.android.gms.phenotype/",
|
||||
"content://com.google.android.gsf.gservices",
|
||||
"content://com.google.android.gsf.gservices/prefix",
|
||||
"com.google.android.c2dm.intent.RECEIVE"
|
||||
)
|
||||
) {
|
||||
StringReplaceMode.REPLACE_WITH_MICROG
|
||||
} else if (stringValue.equalsAny(
|
||||
"com.google.android.apps.youtube.music.SuggestionsProvider", "com.google.android.apps.youtube.music.fileprovider"
|
||||
)
|
||||
) {
|
||||
StringReplaceMode.REPLACE_WITH_REVANCED
|
||||
} else {
|
||||
StringReplaceMode.DO_NOT_REPLACE
|
||||
}
|
||||
|
||||
if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) {
|
||||
if (proxiedClass == null) {
|
||||
proxiedClass = data.proxy(classDef).resolve()
|
||||
}
|
||||
|
||||
if (proxiedImplementation == null) {
|
||||
proxiedImplementation = proxiedClass!!.methods.first {
|
||||
it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes)
|
||||
}.implementation!!
|
||||
}
|
||||
|
||||
val newString = if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace(
|
||||
"com.google.android.apps.youtube.music", REVANCED_MUSIC_PACKAGE_NAME
|
||||
)
|
||||
else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME)
|
||||
|
||||
proxiedImplementation!!.replaceInstruction(
|
||||
i, BuilderInstruction21c(
|
||||
Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private fun disablePlayServiceChecks() {
|
||||
listOf(
|
||||
ServiceCheckFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
).forEach { fingerprint ->
|
||||
val result = fingerprint.result!!
|
||||
val stringInstructions = when (result.method.returnType.first()) {
|
||||
'V' -> "return-void"
|
||||
'I' -> """
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
"""
|
||||
|
||||
else -> throw Exception("This case should never happen.")
|
||||
}
|
||||
result.mutableMethod.addInstructions(
|
||||
0, stringInstructions
|
||||
)
|
||||
}
|
||||
|
||||
val primeMethod = PrimeFingerprint.result!!.mutableMethod
|
||||
val implementation = primeMethod.implementation!!
|
||||
|
||||
var register = 2
|
||||
val index = implementation.instructions.indexOfFirst {
|
||||
if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false
|
||||
|
||||
val instructionString = ((it as Instruction21c).reference as StringReference).string
|
||||
if (instructionString != "com.google.android.apps.youtube.music") return@indexOfFirst false
|
||||
|
||||
register = it.registerA
|
||||
return@indexOfFirst true
|
||||
}
|
||||
|
||||
primeMethod.replaceInstruction(
|
||||
index, "const-string v$register, \"$REVANCED_MUSIC_PACKAGE_NAME\""
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package app.revanced.patches.music.misc.microg.patch.resource
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||
import app.revanced.patches.music.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME
|
||||
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||
|
||||
@Name("music-microg-resource-patch")
|
||||
@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.")
|
||||
@MusicMicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
class MusicMicroGResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
|
||||
val manifest = data["AndroidManifest.xml"].readText()
|
||||
|
||||
data["AndroidManifest.xml"].writeText(
|
||||
manifest.replace(
|
||||
"package=\"com.google.android.apps.youtube.music", "package=\"$REVANCED_MUSIC_PACKAGE_NAME"
|
||||
).replace(
|
||||
"android:label=\"@string/app_name", "android:label=\"$REVANCED_MUSIC_APP_NAME"
|
||||
).replace(
|
||||
"android:label=\"@string/app_launcher_name", "android:label=\"$REVANCED_MUSIC_APP_NAME"
|
||||
).replace(
|
||||
"android:authorities=\"com.google.android.apps.youtube.music", "android:authorities=\"$REVANCED_MUSIC_PACKAGE_NAME"
|
||||
).replace(
|
||||
"com.google.android.apps.youtube.music.permission.C2D_MESSAGE", "$REVANCED_MUSIC_PACKAGE_NAME.permission.C2D_MESSAGE"
|
||||
).replace(
|
||||
"com.google.android.c2dm", "$BASE_MICROG_PACKAGE_NAME.android.c2dm"
|
||||
).replace(
|
||||
"</queries>", "<package android:name=\"$BASE_MICROG_PACKAGE_NAME.android.gms\"/></queries>"
|
||||
)
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.music.misc.microg.shared
|
||||
|
||||
object Constants {
|
||||
internal const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle"
|
||||
internal const val REVANCED_MUSIC_APP_NAME = "YouTube Music ReVanced"
|
||||
internal const val REVANCED_MUSIC_PACKAGE_NAME = "app.revanced.android.apps.youtube.music"
|
||||
}
|
||||
@@ -5,10 +5,9 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
|
||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class BackgroundPlayCompatibility
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.annotations
|
||||
package app.revanced.patches.reddit.ad.general.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.26.35", "17.27.39", "17.28.34", "17.29.34")
|
||||
"com.reddit.frontpage", arrayOf()
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class ForceVP9Compatibility
|
||||
internal annotation class GeneralAdsCompatibility
|
||||
@@ -0,0 +1,55 @@
|
||||
package app.revanced.patches.reddit.ad.general.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.ad.general.annotations.GeneralAdsCompatibility
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.StringReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
||||
|
||||
@Patch
|
||||
@Name("general-reddit-ads")
|
||||
@Description("Removes general ads from the Reddit frontpage and subreddits.")
|
||||
@GeneralAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class GeneralAdsPatch : BytecodePatch() {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
data.classes.forEach { classDef ->
|
||||
classDef.methods.forEach methodLoop@{ method ->
|
||||
val implementation = method.implementation ?: return@methodLoop
|
||||
|
||||
implementation.instructions.forEachIndexed { i, instruction ->
|
||||
if (instruction.opcode != Opcode.CONST_STRING) return@forEachIndexed
|
||||
if (((instruction as ReferenceInstruction).reference as StringReference).string != "AdPost") return@forEachIndexed
|
||||
|
||||
val proxiedClass = data.proxy(classDef).resolve()
|
||||
|
||||
val proxiedImplementation = proxiedClass.methods.first {
|
||||
it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes)
|
||||
}.implementation!!
|
||||
|
||||
var newString = "AdPost1"
|
||||
if (proxiedImplementation.instructions[i - 1].opcode == Opcode.CONST_STRING) {
|
||||
newString = "SubredditPost"
|
||||
}
|
||||
proxiedImplementation.replaceInstruction(
|
||||
i, BuilderInstruction21c(
|
||||
Opcode.CONST_STRING, (proxiedImplementation.instructions[i] as BuilderInstruction21c).registerA, ImmutableStringReference(newString)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.warnwetter.misc.firebasegetcert.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"de.dwd.warnapp", arrayOf()
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class FirebaseGetCertPatchCompatibility
|
||||
@@ -0,0 +1,25 @@
|
||||
package app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility
|
||||
|
||||
@Name("messaging-app-certificate-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lcom/google/firebase/installations/remote/c;", "f"
|
||||
)
|
||||
@FirebaseGetCertPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
object GetMessagingCertFingerprint : MethodFingerprint(
|
||||
"Ljava/lang/String;",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
listOf(
|
||||
"ContentValues",
|
||||
"Could not get fingerprint hash for package: ",
|
||||
"No such package: "
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
package app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility
|
||||
|
||||
@Name("registration-app-certificate-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lcom/google/firebase/remoteconfig/internal/ConfigFetchHttpClient;", "f"
|
||||
)
|
||||
@FirebaseGetCertPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
object GetReqistrationCertFingerprint : MethodFingerprint(
|
||||
"Ljava/lang/String;",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
listOf(
|
||||
"FirebaseRemoteConfig",
|
||||
"Could not get fingerprint hash for package: ",
|
||||
"No such package: "
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.patches.warnwetter.misc.firebasegetcert.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints.*
|
||||
import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility
|
||||
|
||||
@Name("spoof-cert-patch")
|
||||
@Description("Spoofs the X-Android-Cert header.")
|
||||
@FirebaseGetCertPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
class FirebaseGetCertPatch : BytecodePatch(
|
||||
listOf(
|
||||
GetReqistrationCertFingerprint,
|
||||
GetMessagingCertFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val spoofedInstruction =
|
||||
"""
|
||||
const-string v0, "0799DDF0414D3B3475E88743C91C0676793ED450"
|
||||
return-object v0
|
||||
"""
|
||||
|
||||
val registrationCertMethod = GetReqistrationCertFingerprint.result!!.mutableMethod
|
||||
val messagingCertMethod = GetMessagingCertFingerprint.result!!.mutableMethod
|
||||
|
||||
registrationCertMethod.addInstructions(
|
||||
0,
|
||||
spoofedInstruction
|
||||
)
|
||||
messagingCertMethod.addInstructions(
|
||||
0,
|
||||
spoofedInstruction
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.warnwetter.misc.promocode.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"de.dwd.warnapp", arrayOf()
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class PromoCodeUnlockCompatibility
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.warnwetter.misc.promocode.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.warnwetter.misc.promocode.annotations.PromoCodeUnlockCompatibility
|
||||
|
||||
@Name("promo-code-unlock-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lde/dwd/warnapp/model/PromoTokenVerification;", "isValid"
|
||||
)
|
||||
@PromoCodeUnlockCompatibility
|
||||
@Version("0.0.1")
|
||||
object PromoCodeUnlockFingerprint : MethodFingerprint(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{ methodDef ->
|
||||
methodDef.definingClass.endsWith("PromoTokenVerification;") && methodDef.name == "isValid"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.warnwetter.misc.promocode.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.warnwetter.misc.firebasegetcert.patch.FirebaseGetCertPatch
|
||||
import app.revanced.patches.warnwetter.misc.promocode.annotations.PromoCodeUnlockCompatibility
|
||||
import app.revanced.patches.warnwetter.misc.promocode.fingerprints.PromoCodeUnlockFingerprint
|
||||
|
||||
@DependsOn(
|
||||
[
|
||||
FirebaseGetCertPatch::class
|
||||
]
|
||||
)
|
||||
@Patch
|
||||
@Name("promo-code-unlock")
|
||||
@Description("Disables the validation of promo code. Any code will work to unlock all features.")
|
||||
@PromoCodeUnlockCompatibility
|
||||
@Version("0.0.1")
|
||||
class PromoCodeUnlockPatch : BytecodePatch(
|
||||
listOf(
|
||||
PromoCodeUnlockFingerprint
|
||||
)
|
||||
) {
|
||||
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val method = PromoCodeUnlockFingerprint.result!!.mutableMethod
|
||||
method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||
@@ -38,7 +38,7 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
||||
@Patch
|
||||
@Dependencies([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
|
||||
@DependsOn([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
|
||||
@Name("general-ads")
|
||||
@Description("Removes general ads.")
|
||||
@GeneralAdsCompatibility
|
||||
@@ -174,7 +174,6 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
|
||||
}
|
||||
|
||||
Opcode.CONST_STRING -> {
|
||||
|
||||
when (((instruction as Instruction21c).reference as StringReference).string) {
|
||||
stringReferences[0] -> {
|
||||
val stringInstruction = instructions.elementAt(3)
|
||||
@@ -200,23 +199,23 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
|
||||
stringReferences[2] -> { // Litho ads
|
||||
// create proxied method.
|
||||
val proxy = data.proxy(classDef)
|
||||
val mutableClass = proxy.resolve()
|
||||
val proxiedClass = proxy.resolve()
|
||||
|
||||
// add getIsEmpty method
|
||||
mutableClass.addGetIsEmptyMethod()
|
||||
proxiedClass.addGetIsEmptyMethod()
|
||||
|
||||
// get required method to patch and get references from
|
||||
val lithoMethod = getLithoMethod(mutableClass)
|
||||
val lithoMethod = getLithoMethod(proxiedClass)
|
||||
?: return PatchResultError("Could not find required litho method to patch.")
|
||||
val lithoMethodImplementation = lithoMethod.implementation!!
|
||||
|
||||
// create and add getTemplateName method
|
||||
val getTemplateMethod =
|
||||
mutableClass.createGetTemplateNameMethod(lithoMethodImplementation)
|
||||
mutableClass.addMethod(getTemplateMethod)
|
||||
proxiedClass.createGetTemplateNameMethod(lithoMethodImplementation)
|
||||
proxiedClass.addMethod(getTemplateMethod)
|
||||
|
||||
val lithoInstructions = lithoMethodImplementation.instructions
|
||||
val thisType = mutableClass.type
|
||||
val thisType = proxiedClass.type
|
||||
val templateNameParameterType = getTemplateMethod.parameterTypes.first()
|
||||
|
||||
// get reference descriptors
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.reso
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfocardSuggestionsCompatibility
|
||||
@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("hide-infocard-suggestions")
|
||||
@Description("Hides infocards in videos.")
|
||||
@HideInfocardSuggestionsCompatibility
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility
|
||||
@@ -17,7 +17,7 @@ import app.revanced.patches.youtube.ad.video.fingerprints.ShowVideoAdsFingerprin
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("video-ads")
|
||||
@Description("Removes ads in the video player.")
|
||||
@VideoAdsCompatibility
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
|
||||
@@ -22,7 +22,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction11n
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("seekbar-tapping")
|
||||
@Description("Enables tap-to-seek on the seekbar of the video player.")
|
||||
@SeekbarTappingCompatibility
|
||||
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
|
||||
@@ -17,12 +17,12 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.playeroverlay.patch.PlayerOverlaysHookPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
|
||||
|
||||
@Patch(include = false)
|
||||
@Patch
|
||||
@Name("swipe-controls")
|
||||
@Description("Adds volume and brightness swipe controls.")
|
||||
@SwipeControlsCompatibility
|
||||
@Version("0.0.2")
|
||||
@Dependencies(
|
||||
@DependsOn(
|
||||
[
|
||||
IntegrationsPatch::class,
|
||||
PlayerTypeHookPatch::class,
|
||||
|
||||
@@ -6,7 +6,7 @@ import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.amoled.annotations.AmoledCompatibility
|
||||
@@ -15,7 +15,7 @@ import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
|
||||
@Patch
|
||||
@Dependencies([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@Name("amoled")
|
||||
@Description("Enables pure black theme.")
|
||||
@AmoledCompatibility
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
@@ -21,7 +21,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@Dependencies([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
|
||||
@DependsOn([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
|
||||
@Name("hide-autoplay-button")
|
||||
@Description("Hides the autoplay button in the video player.")
|
||||
@AutoplayButtonCompatibility
|
||||
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.branding.header.annotations.PremiumHeadingCompatibility
|
||||
@@ -17,7 +17,7 @@ import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.exists
|
||||
|
||||
@Patch
|
||||
@Dependencies([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@Name("premium-heading")
|
||||
@Description("Shows premium branding on the home screen.")
|
||||
@PremiumHeadingCompatibility
|
||||
|
||||
@@ -4,20 +4,21 @@ import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.branding.icon.annotations.CustomBrandingCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.nio.file.Files
|
||||
|
||||
@Patch
|
||||
@Dependencies([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@Name("custom-branding")
|
||||
@Description("Changes the YouTube launcher icon to be ReVanced's.")
|
||||
@Description("Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).")
|
||||
@CustomBrandingCompatibility
|
||||
@Version("0.0.1")
|
||||
class CustomBrandingPatch : ResourcePatch() {
|
||||
@@ -25,6 +26,7 @@ class CustomBrandingPatch : ResourcePatch() {
|
||||
val resDirectory = data["res"]
|
||||
if (!resDirectory.isDirectory) return PatchResultError("The res folder can not be found.")
|
||||
|
||||
// Icon branding
|
||||
val iconNames = arrayOf(
|
||||
"adaptiveproduct_youtube_background_color_108",
|
||||
"adaptiveproduct_youtube_foreground_color_108",
|
||||
@@ -40,15 +42,59 @@ class CustomBrandingPatch : ResourcePatch() {
|
||||
"mdpi" to 48
|
||||
).forEach { (iconDirectory, size) ->
|
||||
iconNames.forEach iconLoop@{ iconName ->
|
||||
val iconFile = this.javaClass.classLoader.getResourceAsStream("branding/$size/$iconName.png")
|
||||
val iconFile = getIconStream("branding/$size/$iconName.png")
|
||||
?: return PatchResultError("The icon $iconName can not be found.")
|
||||
|
||||
Files.write(
|
||||
resDirectory.resolve("mipmap-$iconDirectory").resolve("$iconName.png").toPath(), iconFile.readAllBytes()
|
||||
resDirectory.resolve("mipmap-$iconDirectory").resolve("$iconName.png").toPath(),
|
||||
iconFile.readAllBytes()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Name branding
|
||||
val appName: String by options[keyAppName]
|
||||
|
||||
val manifest = data["AndroidManifest.xml"]
|
||||
manifest.writeText(
|
||||
manifest.readText()
|
||||
.replace(
|
||||
"android:label=\"@string/application_name",
|
||||
"android:label=\"$appName"
|
||||
)
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
override val options = PatchOptions(
|
||||
PatchOption.StringOption(
|
||||
key = keyAppName,
|
||||
default = "YouTube ReVanced",
|
||||
title = "Application Name",
|
||||
description = "The name of the application it will show on your home screen.",
|
||||
required = true
|
||||
),
|
||||
PatchOption.StringOption(
|
||||
key = keyAppIconPath,
|
||||
default = null,
|
||||
title = "Application Icon Path",
|
||||
description = "A path to the icon of the application."
|
||||
)
|
||||
)
|
||||
|
||||
private fun getIconStream(iconPath: String): InputStream? {
|
||||
val appIconPath: String? by options[keyAppIconPath]
|
||||
if (appIconPath == null) {
|
||||
return this.javaClass.classLoader.getResourceAsStream(iconPath)
|
||||
}
|
||||
val file = File(appIconPath!!).resolve(iconPath)
|
||||
if (!file.exists()) return null
|
||||
return FileInputStream(file)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val keyAppName = "appName"
|
||||
private const val keyAppIconPath = "appIconPath"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
@@ -14,7 +14,7 @@ import app.revanced.patches.youtube.layout.castbutton.annotations.CastButtonComp
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("hide-cast-button")
|
||||
@Description("Hides the cast button in the video player.")
|
||||
@CastButtonCompatibility
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.createbutton.annotations.CreateButtonCompatibility
|
||||
@@ -22,7 +22,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class])
|
||||
@Name("disable-create-button")
|
||||
@Description("Hides the create button in the navigation bar.")
|
||||
@CreateButtonCompatibility
|
||||
|
||||
@@ -10,7 +10,7 @@ import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.reso
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.fullscreenpanels.annotations.FullscreenPanelsCompatibility
|
||||
@@ -20,7 +20,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch
|
||||
@Name("disable-fullscreen-panels")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Description("Disables video description and comments panel in fullscreen view.")
|
||||
@FullscreenPanelsCompatibility
|
||||
@Version("0.0.1")
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.data.impl.toMethodWalker
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
@@ -24,7 +24,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
|
||||
@Patch
|
||||
@Name("minimized-playback")
|
||||
@Description("Enables minimized and background playback.")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@MinimizedPlaybackCompatibility
|
||||
@Version("0.0.1")
|
||||
class MinimizedPlaybackPatch : BytecodePatch(
|
||||
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
|
||||
@@ -16,7 +16,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("old-quality-layout")
|
||||
@Description("Enables the original quality flyout menu.")
|
||||
@OldQualityLayoutCompatibility
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
@@ -20,7 +20,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class, VideoIdPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, VideoIdPatch::class])
|
||||
@Name("return-youtube-dislike")
|
||||
@Description("Shows the dislike count of videos using the Return YouTube Dislike API.")
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility
|
||||
@@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("hide-shorts-button")
|
||||
@Description("Hides the shorts button on the navigation bar.")
|
||||
@ShortsButtonCompatibility
|
||||
|
||||
@@ -13,7 +13,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
@@ -37,7 +37,7 @@ import org.jf.dexlib2.immutable.ImmutableMethodParameter
|
||||
import org.jf.dexlib2.util.MethodUtil
|
||||
|
||||
@Patch
|
||||
@Dependencies(
|
||||
@DependsOn(
|
||||
dependencies = [IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class, SponsorBlockResourcePatch::class, VideoIdPatch::class]
|
||||
)
|
||||
@Name("sponsorblock")
|
||||
|
||||
@@ -2,20 +2,19 @@ package app.revanced.patches.youtube.layout.sponsorblock.resource.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.DomFileEditor
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import java.io.OutputStream
|
||||
import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
||||
import java.nio.file.Files
|
||||
|
||||
@Name("sponsorblock-resource-patch")
|
||||
@SponsorBlockCompatibility
|
||||
@Dependencies([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@Version("0.0.1")
|
||||
class SponsorBlockResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
@@ -29,7 +28,7 @@ class SponsorBlockResourcePatch : ResourcePatch() {
|
||||
|
||||
// copy nodes from the resources node to the real resource node
|
||||
"resources".copyXmlNode(
|
||||
data.xmlEditor[stringsResourceInputStream, OutputStream.nullOutputStream()],
|
||||
data.xmlEditor[stringsResourceInputStream],
|
||||
data.xmlEditor["res/$stringsResourcePath"]
|
||||
).close() // close afterwards
|
||||
|
||||
@@ -78,7 +77,7 @@ class SponsorBlockResourcePatch : ResourcePatch() {
|
||||
|
||||
val targetXmlEditor = data.xmlEditor["res/$path/$resource.xml"]
|
||||
"RelativeLayout".copyXmlNode(
|
||||
data.xmlEditor[hostingResourceStream, OutputStream.nullOutputStream()],
|
||||
data.xmlEditor[hostingResourceStream],
|
||||
targetXmlEditor
|
||||
).also {
|
||||
val children = targetXmlEditor.file.getElementsByTagName("RelativeLayout").item(0).childNodes
|
||||
@@ -102,27 +101,4 @@ class SponsorBlockResourcePatch : ResourcePatch() {
|
||||
}
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the specified node of the source [DomFileEditor] to the target [DomFileEditor].
|
||||
* @param source the source [DomFileEditor].
|
||||
* @param target the target [DomFileEditor]-
|
||||
*/
|
||||
private fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoCloseable {
|
||||
val hostNodes = source.file.getElementsByTagName(this).item(0).childNodes
|
||||
|
||||
val destinationResourceFile = target.file
|
||||
val destinationNode = destinationResourceFile.getElementsByTagName(this).item(0)
|
||||
|
||||
for (index in 0 until hostNodes.length) {
|
||||
val node = hostNodes.item(index).cloneNode(true)
|
||||
destinationResourceFile.adoptNode(node)
|
||||
destinationNode.appendChild(node)
|
||||
}
|
||||
|
||||
return AutoCloseable {
|
||||
source.close()
|
||||
target.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.reso
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.watermark.annotations.HideWatermarkCompatibility
|
||||
@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.layout.watermark.fingerprints.HideWatermarkF
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("hide-watermark")
|
||||
@Description("Hides creator's watermarks on videos.")
|
||||
@HideWatermarkCompatibility
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
@@ -20,8 +20,8 @@ import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearch
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch(include = false)
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("enable-wide-searchbar")
|
||||
@Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.")
|
||||
@WideSearchbarCompatibility
|
||||
|
||||
@@ -10,7 +10,7 @@ import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.reso
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility
|
||||
@@ -18,8 +18,8 @@ import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFinge
|
||||
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
|
||||
@Patch(include = false)
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Name("always-autorepeat")
|
||||
@Description("Always repeats the playing video again.")
|
||||
@AutoRepeatCompatibility
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.customplaybackspeed.annotations.CustomPlaybackSpeedCompatibility
|
||||
@@ -25,7 +25,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
|
||||
@Patch
|
||||
@Name("custom-playback-speed")
|
||||
@Description("Adds more video playback speed options.")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@CustomPlaybackSpeedCompatibility
|
||||
@Version("0.0.1")
|
||||
class CustomPlaybackSpeedPatch : BytecodePatch(
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("force-vp9-codec-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lpzs;", "aI"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@ForceVP9Compatibility
|
||||
@Version("0.0.1")
|
||||
object ForceVP9CodecFingerprint : MethodFingerprint(
|
||||
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf(
|
||||
Opcode.SGET, Opcode.IF_NEZ, Opcode.INVOKE_STATIC
|
||||
), null, null
|
||||
)
|
||||
|
||||
/*
|
||||
public static boolean aI(Context context, int i) {
|
||||
if (b == 0) {
|
||||
aH(context);
|
||||
}
|
||||
return b >= i; // Override to: return Lapp/revanced/integrations/patches/ForceCodecPatch->shouldForceVP9()
|
||||
}
|
||||
|
||||
.method public static aI(Landroid/content/Context;I)Z
|
||||
sget v0, Lpzs;->b:I
|
||||
if-nez v0, :cond_7
|
||||
invoke-static {p0}, Lpzs;->aH(Landroid/content/Context;)V
|
||||
:cond_7
|
||||
//remove after here, and inject only our code
|
||||
sget p0, Lpzs;->b:I
|
||||
if-lt p0, p1, :cond_d
|
||||
const/4 p0, 0x1
|
||||
return p0
|
||||
:cond_d
|
||||
const/4 p0, 0x0
|
||||
return p0
|
||||
.end method
|
||||
*/
|
||||
@@ -1,73 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("force-vp9-codec-fingerprint-two")
|
||||
@MatchingMethod(
|
||||
"Lpzs;", "aO"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@ForceVP9Compatibility
|
||||
@Version("0.0.1")
|
||||
object ForceVP9CodecFingerprintTwo : MethodFingerprint(
|
||||
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("I"), listOf(
|
||||
Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT_OBJECT, Opcode.CONST_4
|
||||
), null, null
|
||||
)
|
||||
|
||||
/*
|
||||
public static boolean aO(int i) {
|
||||
Pair aG = aG();
|
||||
return (aG == null ? 0 : Math.min(((Integer) aG.first).intValue(), ((Integer) aG.second).intValue())) >= i;
|
||||
//replace line with: return Lapp/revanced/integrations/patches/ForceCodecPatch/shouldForceVP9();
|
||||
}
|
||||
|
||||
becomes:
|
||||
public static boolean aO(int i) {
|
||||
return Lapp/revanced/integrations/patches/ForceCodecPatch/shouldForceVP9();
|
||||
}
|
||||
|
||||
.method public static aO(I)Z
|
||||
invoke-static {}, Lpzs;->aG()Landroid/util/Pair;
|
||||
move-result-object v0
|
||||
const/4 v1, 0x0
|
||||
if-nez v0, :cond_9
|
||||
const/4 v0, 0x0
|
||||
goto :goto_1d
|
||||
:cond_9
|
||||
iget-object v2, v0, Landroid/util/Pair;->first:Ljava/lang/Object;
|
||||
check-cast v2, Ljava/lang/Integer;
|
||||
invoke-virtual {v2}, Ljava/lang/Integer;->intValue()I
|
||||
move-result v2
|
||||
iget-object v0, v0, Landroid/util/Pair;->second:Ljava/lang/Object;
|
||||
check-cast v0, Ljava/lang/Integer;
|
||||
invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I
|
||||
move-result v0
|
||||
invoke-static {v2, v0}, Ljava/lang/Math;->min(II)I
|
||||
move-result v0
|
||||
:goto_1d
|
||||
if-lt v0, p0, :cond_21
|
||||
const/4 p0, 0x1
|
||||
return p0
|
||||
:cond_21
|
||||
return v1
|
||||
.end method
|
||||
|
||||
|
||||
becomes:
|
||||
.method public static aO(I)Z
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/ForceCodecPatch;->shouldForceVP9()Z
|
||||
move-result v0
|
||||
return v0
|
||||
.end method
|
||||
|
||||
|
||||
*/
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("force-vp9-codec-parent-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lqaa;", "U"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@ForceVP9Compatibility
|
||||
@Version("0.0.1")
|
||||
object ForceVP9ParentFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf(), null,
|
||||
listOf(
|
||||
"sys.display-size", "x"
|
||||
)
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Name("replace-device-info-parent-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lvjb;", "e"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@ForceVP9Compatibility
|
||||
@Version("0.0.1")
|
||||
object ReplaceDeviceInfoFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), null,
|
||||
null,
|
||||
customFingerprint = { methodDef ->
|
||||
methodDef.implementation!!.instructions.any {
|
||||
((it as? ReferenceInstruction)?.reference as? FieldReference)?.definingClass.equals("Landroid/os/Build;")
|
||||
&& ((it as? ReferenceInstruction)?.reference as? FieldReference)?.name.equals("MANUFACTURER")
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@Name("replace-device-info-parent-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lvjb;", "b"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@ForceVP9Compatibility
|
||||
@Version("0.0.1")
|
||||
object ReplaceDeviceInfoParentFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), null,
|
||||
listOf(
|
||||
"Failed to read the client side experiments map from the disk"
|
||||
)
|
||||
)
|
||||
@@ -1,87 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.forcevp9.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
|
||||
import app.revanced.patches.youtube.misc.forcevp9.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch(include = false)
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@Name("force-vp9-codec")
|
||||
@Description("Forces the VP9 codec for videos.")
|
||||
@ForceVP9Compatibility
|
||||
@Version("0.0.1")
|
||||
class ForceVP9CodecPatch : BytecodePatch(
|
||||
listOf(
|
||||
ForceVP9ParentFingerprint, ReplaceDeviceInfoParentFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val classDef = ForceVP9ParentFingerprint.result!!.classDef
|
||||
ForceVP9CodecFingerprint.resolve(data, classDef)
|
||||
ForceVP9CodecFingerprintTwo.resolve(data, classDef)
|
||||
|
||||
replaceInstructions(ForceVP9CodecFingerprint.result!!)
|
||||
replaceInstructions(ForceVP9CodecFingerprintTwo.result!!)
|
||||
|
||||
ReplaceDeviceInfoFingerprint.resolve(data, ReplaceDeviceInfoParentFingerprint.result!!.classDef)
|
||||
var method = ReplaceDeviceInfoFingerprint.result!!.mutableMethod
|
||||
replaceDeviceInfos("Manufacturer", method)
|
||||
replaceDeviceInfos("Model", method)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private fun replaceInstructions(result: MethodFingerprintResult) {
|
||||
val method = result.mutableMethod
|
||||
method.removeInstructions(0, method.implementation!!.instructions.size - 1)
|
||||
method.addInstructions(
|
||||
0, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/ForceCodecPatch;->shouldForceVP9()Z
|
||||
move-result v0
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun replaceDeviceInfos(name: String, method: MutableMethod) {
|
||||
var impl = method.implementation!!
|
||||
//find target instruction for Build.name.uppercase() and replace that with our method
|
||||
impl.instructions.filter {
|
||||
((it as? ReferenceInstruction)?.reference as? FieldReference)?.let { field ->
|
||||
//sget-object v1, Landroid/os/Build;->MANUFACTURER:Ljava/lang/String;
|
||||
//sget-object v1, Landroid/os/Build;->MODEL:Ljava/lang/String;
|
||||
field.definingClass == "Landroid/os/Build;" && field.name == name.uppercase()
|
||||
} == true
|
||||
}.forEach { instruction ->
|
||||
val index = method.implementation!!.instructions.indexOf(instruction)
|
||||
val register = (instruction as OneRegisterInstruction).registerA
|
||||
|
||||
// inject the call to
|
||||
method.removeInstruction(index)
|
||||
method.addInstructions(
|
||||
index, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/ForceCodecPatch;->get$name()Ljava/lang/String;
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility
|
||||
@@ -18,12 +18,12 @@ import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch(false)
|
||||
@Patch
|
||||
@Name("hdr-auto-brightness")
|
||||
@Description("Makes the brightness of HDR videos follow the system default.")
|
||||
@HDRBrightnessCompatibility
|
||||
@Version("0.0.2")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
class HDRBrightnessPatch : BytecodePatch(
|
||||
listOf(
|
||||
HDRBrightnessFingerprintXXZ
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||
@@ -28,7 +28,7 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
||||
|
||||
@Patch
|
||||
@Dependencies(
|
||||
@DependsOn(
|
||||
[
|
||||
MicroGResourcePatch::class,
|
||||
HideCastButtonPatch::class,
|
||||
|
||||
@@ -6,16 +6,16 @@ import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
|
||||
import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
|
||||
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NAME
|
||||
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
|
||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
|
||||
|
||||
@Name("microg-resource-patch")
|
||||
@Dependencies([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsResourcePatch::class])
|
||||
@Description("Resource patch to allow YouTube ReVanced to run without root and under a different package name.")
|
||||
@MicroGPatchCompatibility
|
||||
@Version("0.0.1")
|
||||
@@ -27,34 +27,40 @@ class MicroGResourcePatch : ResourcePatch() {
|
||||
settingsElementIntent.setAttribute("android:targetClass", "org.microg.gms.ui.SettingsActivity")
|
||||
|
||||
val settingsElement = it.file.createElement("Preference")
|
||||
settingsElement.setAttribute("android:title", "MicroG")
|
||||
settingsElement.setAttribute("android:title", "@string/microg_settings")
|
||||
settingsElement.appendChild(settingsElementIntent)
|
||||
|
||||
it.file.firstChild.appendChild(settingsElement)
|
||||
}
|
||||
|
||||
val manifest = data.get("AndroidManifest.xml").readText()
|
||||
|
||||
data.get("AndroidManifest.xml").writeText(
|
||||
manifest.replace(
|
||||
"package=\"com.google.android.youtube", "package=\"$REVANCED_PACKAGE_NAME"
|
||||
).replace(
|
||||
"android:label=\"@string/application_name", "android:label=\"$REVANCED_APP_NAME"
|
||||
).replace(
|
||||
"android:authorities=\"com.google.android.youtube", "android:authorities=\"$REVANCED_PACKAGE_NAME"
|
||||
).replace(
|
||||
"com.google.android.youtube.permission.C2D_MESSAGE", "$REVANCED_PACKAGE_NAME.permission.C2D_MESSAGE"
|
||||
).replace( // TODO: might not be needed
|
||||
"com.google.android.youtube.lifecycle-trojan", "$REVANCED_PACKAGE_NAME.lifecycle-trojan"
|
||||
).replace( // TODO: might not be needed
|
||||
"com.google.android.youtube.photopicker_images", "$REVANCED_PACKAGE_NAME.photopicker_images"
|
||||
).replace(
|
||||
"com.google.android.c2dm", "$BASE_MICROG_PACKAGE_NAME.android.c2dm"
|
||||
).replace(
|
||||
"</queries>", "<package android:name=\"$BASE_MICROG_PACKAGE_NAME.android.gms\"/></queries>"
|
||||
val settingsFragment = data["res/xml/settings_fragment.xml"]
|
||||
settingsFragment.writeText(
|
||||
settingsFragment.readText().replace(
|
||||
"android:targetPackage=\"com.google.android.youtube",
|
||||
"android:targetPackage=\"$REVANCED_PACKAGE_NAME"
|
||||
)
|
||||
)
|
||||
|
||||
val manifest = data["AndroidManifest.xml"]
|
||||
manifest.writeText(
|
||||
manifest.readText()
|
||||
.replace(
|
||||
"package=\"com.google.android.youtube", "package=\"$REVANCED_PACKAGE_NAME"
|
||||
).replace(
|
||||
"android:authorities=\"com.google.android.youtube", "android:authorities=\"$REVANCED_PACKAGE_NAME"
|
||||
).replace(
|
||||
"com.google.android.youtube.permission.C2D_MESSAGE", "$REVANCED_PACKAGE_NAME.permission.C2D_MESSAGE"
|
||||
).replace( // might not be needed
|
||||
"com.google.android.youtube.lifecycle-trojan", "$REVANCED_PACKAGE_NAME.lifecycle-trojan"
|
||||
).replace( // might not be needed
|
||||
"com.google.android.youtube.photopicker_images", "$REVANCED_PACKAGE_NAME.photopicker_images"
|
||||
).replace(
|
||||
"com.google.android.c2dm", "$BASE_MICROG_PACKAGE_NAME.android.c2dm"
|
||||
).replace(
|
||||
"</queries>", "<package android:name=\"$BASE_MICROG_PACKAGE_NAME.android.gms\"/></queries>"
|
||||
)
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,4 @@ package app.revanced.patches.youtube.misc.microg.shared
|
||||
object Constants {
|
||||
internal const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle"
|
||||
internal const val REVANCED_PACKAGE_NAME = "app.revanced.android.youtube"
|
||||
internal const val REVANCED_APP_NAME = "YouTube ReVanced"
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.playeroverlay.annotation.PlayerOverlaysHookCompatibility
|
||||
@@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlay
|
||||
@Description("Hook for adding custom overlays to the video player.")
|
||||
@PlayerOverlaysHookCompatibility
|
||||
@Version("0.0.1")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
class PlayerOverlaysHookPatch : BytecodePatch(
|
||||
listOf(
|
||||
PlayerOverlaysOnFinishInflateFingerprint
|
||||
|
||||
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.annotation.PlayerTypeHookCompatibility
|
||||
@@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.playertype.fingerprint.UpdatePlayerType
|
||||
@Description("Hook to get the current player type of WatchWhileActivity")
|
||||
@PlayerTypeHookCompatibility
|
||||
@Version("0.0.1")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
class PlayerTypeHookPatch : BytecodePatch(
|
||||
listOf(
|
||||
UpdatePlayerTypeFingerprint
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.22.36", "17.24.35", "17.26.35", "17.27.39")
|
||||
"com.google.android.youtube", arrayOf("17.22.36", "17.24.35", "17.26.35", "17.27.39", "17.28.34", "17.29.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
|
||||
@@ -4,18 +4,18 @@ package app.revanced.patches.youtube.misc.quality.fingerprints
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.quality.annotations.DefaultVideoQualityCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("video-quality-setter-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lkec", "a"
|
||||
"Lkec;", "a"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||
@DirectPatternScanMethod
|
||||
@DefaultVideoQualityCompatibility
|
||||
@Version("0.0.1")
|
||||
object VideoQualitySetterFingerprint : MethodFingerprint(
|
||||
|
||||
@@ -1,80 +1,69 @@
|
||||
package app.revanced.patches.youtube.misc.quality.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.quality.annotations.DefaultVideoQualityCompatibility
|
||||
import app.revanced.patches.youtube.misc.quality.fingerprints.VideoQualityReferenceFingerprint
|
||||
import app.revanced.patches.youtube.misc.quality.fingerprints.VideoQualitySetterFingerprint
|
||||
import app.revanced.patches.youtube.misc.quality.fingerprints.VideoUserQualityChangeFingerprint
|
||||
import app.revanced.patches.youtube.misc.videoid.fingerprint.VideoIdFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Dependencies(
|
||||
dependencies = [IntegrationsPatch::class]
|
||||
)
|
||||
@Name("default-video-quality")
|
||||
@Description("Adds the ability to select preferred video quality.")
|
||||
@DefaultVideoQualityCompatibility
|
||||
@Version("0.0.1")
|
||||
class DefaultVideoQualityPatch : BytecodePatch(
|
||||
listOf(
|
||||
VideoQualitySetterFingerprint,
|
||||
VideoIdFingerprint
|
||||
)
|
||||
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val offset = 4
|
||||
val setterMethod = VideoQualitySetterFingerprint.result!!
|
||||
|
||||
VideoUserQualityChangeFingerprint.resolve(data, setterMethod.classDef)
|
||||
val userQualityMethod = VideoUserQualityChangeFingerprint.result!!
|
||||
|
||||
VideoQualityReferenceFingerprint.resolve(data, setterMethod.classDef)
|
||||
val qualityFieldReference =
|
||||
VideoQualityReferenceFingerprint.result!!.method.let { method ->
|
||||
(method.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
|
||||
}
|
||||
|
||||
val qIndexMethodName =
|
||||
data.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name
|
||||
|
||||
setterMethod.mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
iget-object v0, p0, ${setterMethod.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type}
|
||||
const-string v1, "$qIndexMethodName"
|
||||
invoke-static {p1, p2, v0, v1}, Lapp/revanced/integrations/patches/VideoQualityPatch;->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
|
||||
move-result p2
|
||||
""",
|
||||
)
|
||||
|
||||
val newVideoMethod = VideoIdFingerprint.result!!
|
||||
val newVideoIndex = newVideoMethod.patternScanResult!!.endIndex + offset
|
||||
newVideoMethod.mutableMethod.addInstructions(
|
||||
newVideoIndex, """
|
||||
const/4 v6, 0x1
|
||||
invoke-static {v6}, Lapp/revanced/integrations/utils/ReVancedUtils;->setNewVideo(Z)V
|
||||
"""
|
||||
)
|
||||
|
||||
userQualityMethod.mutableMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static {p3}, Lapp/revanced/integrations/patches/VideoQualityPatch;->userChangedQuality(I)V"
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
package app.revanced.patches.youtube.misc.quality.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.quality.annotations.DefaultVideoQualityCompatibility
|
||||
import app.revanced.patches.youtube.misc.quality.fingerprints.VideoQualityReferenceFingerprint
|
||||
import app.revanced.patches.youtube.misc.quality.fingerprints.VideoQualitySetterFingerprint
|
||||
import app.revanced.patches.youtube.misc.quality.fingerprints.VideoUserQualityChangeFingerprint
|
||||
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, VideoIdPatch::class])
|
||||
@Name("remember-video-quality")
|
||||
@Description("Adds the ability to remember the video quality you chose in the video quality flyout.")
|
||||
@DefaultVideoQualityCompatibility
|
||||
@Version("0.0.1")
|
||||
class RememberVideoQualityPatch : BytecodePatch(
|
||||
listOf(
|
||||
VideoQualitySetterFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val setterMethod = VideoQualitySetterFingerprint.result!!
|
||||
|
||||
VideoUserQualityChangeFingerprint.resolve(data, setterMethod.classDef)
|
||||
val userQualityMethod = VideoUserQualityChangeFingerprint.result!!
|
||||
|
||||
VideoQualityReferenceFingerprint.resolve(data, setterMethod.classDef)
|
||||
val qualityFieldReference =
|
||||
VideoQualityReferenceFingerprint.result!!.method.let { method ->
|
||||
(method.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
|
||||
}
|
||||
|
||||
VideoIdPatch.injectCall("Lapp/revanced/integrations/patches/VideoQualityPatch;->newVideoStarted(Ljava/lang/String;)V")
|
||||
|
||||
val qIndexMethodName =
|
||||
data.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name
|
||||
|
||||
setterMethod.mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
iget-object v0, p0, ${setterMethod.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type}
|
||||
const-string v1, "$qIndexMethodName"
|
||||
invoke-static {p1, p2, v0, v1}, Lapp/revanced/integrations/patches/VideoQualityPatch;->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
|
||||
move-result p2
|
||||
""",
|
||||
)
|
||||
|
||||
userQualityMethod.mutableMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static {p3}, Lapp/revanced/integrations/patches/VideoQualityPatch;->userChangedQuality(I)V"
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.settings.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf()
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class SettingsCompatibility
|
||||
@@ -0,0 +1,26 @@
|
||||
package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
|
||||
// TODO: This is more of a class fingerprint than a method fingerprint.
|
||||
// Convert to a class fingerprint whenever possible.
|
||||
@Name("license-activity-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lcom/google/android/libraries/social/licenses/LicenseActivity;", "onCreate"
|
||||
)
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@Version("0.0.1")
|
||||
object LicenseActivityFingerprint : MethodFingerprint(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{ methodDef ->
|
||||
methodDef.definingClass.endsWith("LicenseActivity;") && methodDef.name == "onCreate"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
|
||||
// TODO: This is more of a class fingerprint than a method fingerprint.
|
||||
// Convert to a class fingerprint whenever possible.
|
||||
@Name("revanced-settings-activity-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lapp/revanced/integrations/settingsmenu/ReVancedSettingActivity;", "initializeSettings"
|
||||
)
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@Version("0.0.1")
|
||||
object ReVancedSettingsActivityFingerprint : MethodFingerprint(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{ methodDef ->
|
||||
methodDef.definingClass.endsWith("ReVancedSettingActivity;") && methodDef.name == "initializeSettings"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
|
||||
@Name("theme-setter-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lfyq;", "a"
|
||||
)
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@Version("0.0.1")
|
||||
object ThemeSetterFingerprint : MethodFingerprint(
|
||||
"L",
|
||||
null,
|
||||
null,
|
||||
listOf(Opcode.RETURN_OBJECT),
|
||||
null,
|
||||
{ methodDef ->
|
||||
methodDef.implementation?.instructions?.any {
|
||||
it.opcode.ordinal == Opcode.CONST.ordinal && (it as WideLiteralInstruction).wideLiteral == SettingsPatch.appearanceStringId
|
||||
} == true
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,91 @@
|
||||
package app.revanced.patches.youtube.misc.settings.bytecode.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.smali.toInstruction
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ReVancedSettingsActivityFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
|
||||
|
||||
@Patch
|
||||
@DependsOn(
|
||||
[
|
||||
IntegrationsPatch::class,
|
||||
SettingsResourcePatch::class,
|
||||
ResourceIdMappingProviderResourcePatch::class
|
||||
]
|
||||
)
|
||||
@Name("settings")
|
||||
@Description("Adds settings for ReVanced to YouTube.")
|
||||
@SettingsCompatibility
|
||||
@Version("0.0.1")
|
||||
class SettingsPatch : BytecodePatch(
|
||||
listOf(LicenseActivityFingerprint, ReVancedSettingsActivityFingerprint, ThemeSetterFingerprint)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val licenseActivityResult = LicenseActivityFingerprint.result!!
|
||||
val settingsResult = ReVancedSettingsActivityFingerprint.result!!
|
||||
val themeSetterResult = ThemeSetterFingerprint.result!!
|
||||
|
||||
val licenseActivityClass = licenseActivityResult.mutableClass
|
||||
val settingsClass = settingsResult.mutableClass
|
||||
|
||||
val onCreate = licenseActivityResult.mutableMethod
|
||||
val setThemeMethodName = "setTheme"
|
||||
val initializeSettings = settingsResult.mutableMethod
|
||||
|
||||
val setThemeInstruction =
|
||||
"invoke-static {v0}, Lapp/revanced/integrations/utils/ThemeHelper;->setTheme(Ljava/lang/Object;)V".toInstruction(
|
||||
themeSetterResult.mutableMethod
|
||||
)
|
||||
|
||||
// add instructions to set the theme of the settings activity
|
||||
themeSetterResult.mutableMethod.implementation!!.let {
|
||||
it.addInstruction(
|
||||
themeSetterResult.patternScanResult!!.startIndex,
|
||||
setThemeInstruction
|
||||
)
|
||||
|
||||
it.addInstruction(
|
||||
it.instructions.size - 1, // add before return
|
||||
setThemeInstruction
|
||||
)
|
||||
}
|
||||
|
||||
// add the setTheme call to the onCreate method to not affect the offsets.
|
||||
onCreate.addInstructions(
|
||||
1,
|
||||
"""
|
||||
invoke-static { p0 }, ${settingsClass.type}->${initializeSettings.name}(${licenseActivityClass.type})V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
|
||||
// add the initializeSettings call to the onCreate method.
|
||||
onCreate.addInstruction(
|
||||
0,
|
||||
"invoke-static { p0 }, ${settingsClass.type}->$setThemeMethodName(${licenseActivityClass.type})V"
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
val appearanceStringId = ResourceIdMappingProviderResourcePatch.resourceMappings.find {
|
||||
it.type == "string" && it.name == "app_theme_appearance_dark"
|
||||
}!!.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package app.revanced.patches.youtube.misc.settings.resource.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
|
||||
import app.revanced.util.resources.ResourceUtils
|
||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||
import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Name("settings-resource-patch")
|
||||
@SettingsCompatibility
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@Version("0.0.1")
|
||||
class SettingsResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
/*
|
||||
* Copy strings
|
||||
*/
|
||||
|
||||
data.copyXmlNode("settings/host", "values/strings.xml", "resources")
|
||||
|
||||
/*
|
||||
* Copy arrays
|
||||
*/
|
||||
|
||||
data.copyXmlNode("settings/host", "values/arrays.xml", "resources")
|
||||
|
||||
/*
|
||||
* Copy preference fragments
|
||||
*/
|
||||
|
||||
data.copyXmlNode("settings/host", "xml/settings_fragment.xml", "PreferenceScreen")
|
||||
|
||||
/*
|
||||
* Copy layout resources
|
||||
*/
|
||||
arrayOf(
|
||||
ResourceUtils.ResourceGroup(
|
||||
"layout",
|
||||
"xsettings_toolbar.xml",
|
||||
"xsettings_with_toolbar.xml",
|
||||
"xsettings_with_toolbar_layout.xml"
|
||||
),
|
||||
ResourceUtils.ResourceGroup(
|
||||
"xml",
|
||||
"revanced_prefs.xml"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
data.copyResources("settings", resourceGroup)
|
||||
}
|
||||
|
||||
data.xmlEditor["AndroidManifest.xml"].use {
|
||||
val manifestNode = it
|
||||
.file
|
||||
.getElementsByTagName("manifest")
|
||||
.item(0) as Element
|
||||
|
||||
val element = it.file.createElement("uses-permission")
|
||||
element.setAttribute("android:name", "android.permission.SCHEDULE_EXACT_ALARM")
|
||||
manifestNode.appendChild(element)
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.videobuffer.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf("17.25.34", "17.29.34")
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class CustomVideoBufferCompatibility
|
||||
@@ -0,0 +1,32 @@
|
||||
package app.revanced.patches.youtube.misc.videobuffer.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
@Name("maxbuffer-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;", "r"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@CustomVideoBufferCompatibility
|
||||
@Version("0.0.1")
|
||||
object MaxBufferFingerprint : MethodFingerprint(
|
||||
"I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(),
|
||||
listOf(Opcode.SGET_OBJECT, Opcode.IGET, Opcode.IF_EQZ, Opcode.RETURN),
|
||||
null,
|
||||
customFingerprint = { methodDef ->
|
||||
methodDef.definingClass.equals("Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;")
|
||||
&& methodDef.implementation!!.instructions.any {
|
||||
((it as? NarrowLiteralInstruction)?.narrowLiteral == 120000)
|
||||
&& methodDef.name.equals("r")
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package app.revanced.patches.youtube.misc.videobuffer.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
@Name("playbackbuffer-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;", "p"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@CustomVideoBufferCompatibility
|
||||
@Version("0.0.1")
|
||||
object PlaybackBufferFingerprint : MethodFingerprint(
|
||||
"I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(),
|
||||
listOf(Opcode.IF_LEZ, Opcode.RETURN),
|
||||
null,
|
||||
customFingerprint = { methodDef ->
|
||||
methodDef.definingClass.equals("Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;")
|
||||
&& methodDef.implementation!!.instructions.any {
|
||||
((it as? NarrowLiteralInstruction)?.narrowLiteral == 1600)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package app.revanced.patches.youtube.misc.videobuffer.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
@Name("playbackbuffer-fingerprint")
|
||||
@MatchingMethod(
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;", "t"
|
||||
)
|
||||
@DirectPatternScanMethod
|
||||
@CustomVideoBufferCompatibility
|
||||
@Version("0.0.1")
|
||||
object ReBufferFingerprint : MethodFingerprint(
|
||||
"I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(),
|
||||
listOf(Opcode.IF_LEZ, Opcode.RETURN),
|
||||
null,
|
||||
customFingerprint = { methodDef ->
|
||||
methodDef.definingClass.equals("Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;")
|
||||
&& methodDef.implementation!!.instructions.any {
|
||||
((it as? NarrowLiteralInstruction)?.narrowLiteral == 5000)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,73 @@
|
||||
package app.revanced.patches.youtube.misc.videobuffer.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility
|
||||
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.MaxBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.PlaybackBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.ReBufferFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Name("custom-video-buffer")
|
||||
@Description("Lets you change the buffers of videos.")
|
||||
@CustomVideoBufferCompatibility
|
||||
@Version("0.0.1")
|
||||
class CustomVideoBufferPatch : BytecodePatch(
|
||||
listOf(
|
||||
MaxBufferFingerprint, PlaybackBufferFingerprint, ReBufferFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
execMaxBuffer()
|
||||
execPlaybackBuffer(data)
|
||||
execReBuffer(data)
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private fun execMaxBuffer() {
|
||||
val result = MaxBufferFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
val index = result.patternScanResult!!.endIndex - 1
|
||||
val register = (method.implementation!!.instructions.get(index) as OneRegisterInstruction).registerA
|
||||
method.addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getMaxBuffer()I
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun execPlaybackBuffer(data: BytecodeData) {
|
||||
val result = PlaybackBufferFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
val index = result.patternScanResult!!.startIndex
|
||||
val register = (method.implementation!!.instructions.get(index) as OneRegisterInstruction).registerA
|
||||
method.addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getPlaybackBuffer()I
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun execReBuffer(data: BytecodeData) {
|
||||
val result = ReBufferFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
val index = result.patternScanResult!!.startIndex
|
||||
val register = (method.implementation!!.instructions.get(index) as OneRegisterInstruction).registerA
|
||||
method.addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getReBuffer()I
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Dependencies
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
@@ -20,7 +20,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@Description("Hook to detect when the video id changes")
|
||||
@VideoIdCompatibility
|
||||
@Version("0.0.1")
|
||||
@Dependencies([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
class VideoIdPatch : BytecodePatch(
|
||||
listOf(
|
||||
VideoIdFingerprint
|
||||
@@ -35,15 +35,18 @@ class VideoIdPatch : BytecodePatch(
|
||||
|
||||
injectCall("Lapp/revanced/integrations/videoplayer/VideoInformation;->setCurrentVideoId(Ljava/lang/String;)V")
|
||||
|
||||
offset++ // offset so setCurrentVideoId is called before any injected call
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private lateinit var result: MethodFingerprintResult
|
||||
private var videoIdRegister: Int = 0
|
||||
private lateinit var insertMethod: MutableMethod
|
||||
private var offset = 2
|
||||
|
||||
private var videoIdRegister: Int = 0
|
||||
private lateinit var result: MethodFingerprintResult
|
||||
private lateinit var insertMethod: MutableMethod
|
||||
|
||||
/**
|
||||
* Adds an invoke-static instruction, called with the new id when the video changes
|
||||
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
|
||||
@@ -52,10 +55,9 @@ class VideoIdPatch : BytecodePatch(
|
||||
methodDescriptor: String
|
||||
) {
|
||||
insertMethod.addInstructions(
|
||||
result.patternScanResult!!.endIndex + offset, // after the move-result-object
|
||||
result.patternScanResult!!.endIndex + offset, // move-result-object offset
|
||||
"invoke-static {v$videoIdRegister}, $methodDescriptor"
|
||||
)
|
||||
offset++ // so additional instructions get added later
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
74
src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt
Normal file
74
src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt
Normal file
@@ -0,0 +1,74 @@
|
||||
package app.revanced.util.resources
|
||||
|
||||
import app.revanced.patcher.data.impl.DomFileEditor
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import java.nio.file.Files
|
||||
|
||||
internal object ResourceUtils {
|
||||
/**
|
||||
* Copy resources from the current class loader to the resource directory.
|
||||
* @param sourceResourceDirectory The source resource directory name.
|
||||
* @param resources The resources to copy.
|
||||
*/
|
||||
internal fun ResourceData.copyResources(sourceResourceDirectory: String, vararg resources: ResourceGroup) {
|
||||
val classLoader = ResourceUtils.javaClass.classLoader
|
||||
val targetResourceDirectory = this["res"]
|
||||
|
||||
for (resourceGroup in resources) {
|
||||
resourceGroup.resources.forEach { resource ->
|
||||
val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource"
|
||||
Files.copy(
|
||||
classLoader.getResourceAsStream("$sourceResourceDirectory/$resourceFile")!!,
|
||||
targetResourceDirectory.resolve(resourceFile).toPath()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource names mapped to their corresponding resource data.
|
||||
* @param resourceDirectoryName The name of the directory of the resource.
|
||||
* @param resources A list of resource names.
|
||||
*/
|
||||
internal class ResourceGroup(val resourceDirectoryName: String, vararg val resources: String)
|
||||
|
||||
/**
|
||||
* Copy resources from the current class loader to the resource directory.
|
||||
* @param resourceDirectory The directory of the resource.
|
||||
* @param targetResource The target resource.
|
||||
* @param elementTag The element to copy.
|
||||
*/
|
||||
internal fun ResourceData.copyXmlNode(resourceDirectory: String, targetResource: String, elementTag: String) {
|
||||
val stringsResourceInputStream = ResourceUtils.javaClass.classLoader.getResourceAsStream("$resourceDirectory/$targetResource")!!
|
||||
|
||||
// Copy nodes from the resources node to the real resource node
|
||||
elementTag.copyXmlNode(
|
||||
this.xmlEditor[stringsResourceInputStream],
|
||||
this.xmlEditor["res/$targetResource"]
|
||||
).close()
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the specified node of the source [DomFileEditor] to the target [DomFileEditor].
|
||||
* @param source the source [DomFileEditor].
|
||||
* @param target the target [DomFileEditor]-
|
||||
* @return AutoCloseable that closes the target [DomFileEditor]s.
|
||||
*/
|
||||
internal fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoCloseable {
|
||||
val hostNodes = source.file.getElementsByTagName(this).item(0).childNodes
|
||||
|
||||
val destinationResourceFile = target.file
|
||||
val destinationNode = destinationResourceFile.getElementsByTagName(this).item(0)
|
||||
|
||||
for (index in 0 until hostNodes.length) {
|
||||
val node = hostNodes.item(index).cloneNode(true)
|
||||
destinationResourceFile.adoptNode(node)
|
||||
destinationNode.appendChild(node)
|
||||
}
|
||||
|
||||
return AutoCloseable {
|
||||
source.close()
|
||||
target.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/main/resources/settings/host/values/arrays.xml
Normal file
14
src/main/resources/settings/host/values/arrays.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<resources>
|
||||
<string-array name="revanced_button_location_entries">
|
||||
<item>@string/revanced_button_location_entry_none</item>
|
||||
<item>@string/revanced_button_location_entry_player</item>
|
||||
<item>@string/revanced_button_location_entry_buttoncontainer</item>
|
||||
<item>@string/revanced_button_location_entry_both</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_button_location_entry_values">
|
||||
<item>NONE</item>
|
||||
<item>PLAYER</item>
|
||||
<item>BUTTON_CONTAINER</item>
|
||||
<item>BOTH</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
227
src/main/resources/settings/host/values/strings.xml
Normal file
227
src/main/resources/settings/host/values/strings.xml
Normal file
@@ -0,0 +1,227 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="revanced_auto_repeat_button_summary_off">"Doesn't show auto-repeat button in the player overlay. Use the toggle below to control auto-repeat"</string>
|
||||
<string name="revanced_auto_repeat_button_summary_on">Auto-repeat button is shown in the player overlay</string>
|
||||
<string name="revanced_auto_repeat_button_title">Auto-repeat button</string>
|
||||
<string name="revanced_auto_repeat_summary_off">Always Auto-repeat is off</string>
|
||||
<string name="revanced_auto_repeat_summary_on">Always Auto-repeat is on</string>
|
||||
<string name="revanced_auto_repeat_title">Always Auto-repeat</string>
|
||||
<string name="revanced_branding_watermark_summary_off">Video watermark is hidden</string>
|
||||
<string name="revanced_branding_watermark_summary_on">Video watermark is shown</string>
|
||||
<string name="revanced_branding_watermark_title">Video watermark</string>
|
||||
<string name="revanced_buffer_title">Buffer settings</string>
|
||||
<string name="revanced_cast_button_summary_off">Cast button is hidden</string>
|
||||
<string name="revanced_cast_button_summary_on">Cast button is shown</string>
|
||||
<string name="revanced_cast_button_title">Cast button</string>
|
||||
<string name="revanced_autoplay_button_summary_off">Autoplay button is hidden</string>
|
||||
<string name="revanced_autoplay_button_summary_on">Autoplay button is shown</string>
|
||||
<string name="revanced_autoplay_button_title">Autoplay button</string>
|
||||
<string name="revanced_codec_override_title">Codec override</string>
|
||||
<string name="revanced_debug_summary_off">Extra debug logging is disabled</string>
|
||||
<string name="revanced_debug_summary_on">Extra Debug logging is enabled</string>
|
||||
<string name="revanced_debug_title">Debug mode</string>
|
||||
<string name="revanced_discord_summary">Tap to join ReVanced on Discord</string>
|
||||
<string name="revanced_discord_title">Discord server</string>
|
||||
<string name="revanced_hdr_full_brightness_summary_on">Video brightness will follow your device\'s brightness on HDR landscape videos</string>
|
||||
<string name="revanced_hdr_full_brightness_summary_off">Video brightness is set to max on HDR landscape videos</string>
|
||||
<string name="revanced_hdr_full_brightness_title">Override HDR Video Brightness</string>
|
||||
<string name="revanced_info_cards_summary_off">Info cards are hidden</string>
|
||||
<string name="revanced_info_cards_summary_on">Info cards are shown</string>
|
||||
<string name="revanced_info_cards_title">Info cards</string>
|
||||
<string name="revanced_layout_settings_title">Layout settings</string>
|
||||
<string name="revanced_maximum_buffer_summary">"The maximum duration of media that the player will attempt to buffer (in milliseconds)
|
||||
|
||||
Default: 120000"</string>
|
||||
<string name="revanced_maximum_buffer_title">Maximum buffer</string>
|
||||
<string name="revanced_misc_title">Miscellaneous</string>
|
||||
<string name="revanced_playback_start_summary">"The duration of media that must be buffered for playback to start or resume following a user action such as seeking (in milliseconds)
|
||||
|
||||
Default: 2500"</string>
|
||||
<string name="revanced_playback_start_title">Playback start</string>
|
||||
<string name="revanced_preferred_video_speed_summary">Select preferred video speed</string>
|
||||
<string name="revanced_preferred_video_speed_title">Preferred video speed</string>
|
||||
<string name="revanced_rebuffer_summary">"The duration of media that must be buffered for playback to resume after a rebuffer (in milliseconds). A rebuffer is defined to be caused by buffer depletion rather than a user action
|
||||
|
||||
Default: 5000"</string>
|
||||
<string name="revanced_rebuffer_title">Rebuffer</string>
|
||||
<string name="revanced_suggestion_summary_off">End screens are hidden</string>
|
||||
<string name="revanced_suggestion_summary_on">End screens are shown</string>
|
||||
<string name="revanced_suggestion_title">End screens</string>
|
||||
<string name="revanced_support_summary">Support links</string>
|
||||
<string name="revanced_support_title">Support</string>
|
||||
<string name="revanced_video_settings_title">Video settings</string>
|
||||
<string name="revanced_vp9_summary">Tap to force usage of the VP9 codec</string>
|
||||
<string name="revanced_vp9_summary_off">VP9 codec not forced</string>
|
||||
<string name="revanced_vp9_summary_on">VP9 codec is enabled by default for supported devices, disable if you encounter stuttering/slowness in videos</string>
|
||||
<string name="revanced_vp9_title">VP9 codec</string>
|
||||
<string name="revanced_new_actionbar_title">Wide search bar</string>
|
||||
<string name="revanced_new_actionbar_summary_off">Search bar style is defined by the app</string>
|
||||
<string name="revanced_new_actionbar_summary_on">Forcing wide search bar</string>
|
||||
<string name="revanced_shorts_button_title">Show shorts button</string>
|
||||
<string name="revanced_shorts_button_summary_off">Shorts button is hidden</string>
|
||||
<string name="revanced_shorts_button_summary_on">Shorts button is shown</string>
|
||||
<string name="revanced_fullscreen_panels_title">Fullscreen panels</string>
|
||||
<string name="revanced_fullscreen_panels_summary_off">Fullscreen panels are hidden</string>
|
||||
<string name="revanced_fullscreen_panels_summary_on">Fullscreen panels are shown</string>
|
||||
<string name="revanced_zoom_to_fit_vertical_title">Dynamic player</string>
|
||||
<string name="revanced_zoom_to_fit_vertical_summary_off">Dynamic player is defined automatically</string>
|
||||
<string name="revanced_zoom_to_fit_vertical_summary_on">Dynamic player is forced on square and vertical videos</string>
|
||||
<string name="revanced_auto_captions_summary_off">Captions aren\'t enabled automatically at 0% volume </string>
|
||||
<string name="revanced_auto_captions_summary_on">Captions are enabled automatically at 0% volume</string>
|
||||
<string name="revanced_auto_captions_title">Auto captions</string>
|
||||
<string name="revanced_swipe_brightness_summary_off">Swipe controls for brightness are disabled</string>
|
||||
<string name="revanced_swipe_brightness_summary_on">Swipe controls for brightness are enabled</string>
|
||||
<string name="revanced_swipe_brightness_title">Swipe controls for Brightness</string>
|
||||
<string name="revanced_swipe_screen_summary">Swipe controls for Brightness and Volume</string>
|
||||
<string name="revanced_swipe_title">Swipe controls</string>
|
||||
<string name="revanced_swipe_volume_summary_off">Swipe controls for volume are disabled</string>
|
||||
<string name="revanced_swipe_volume_summary_on">Swipe controls for volume are enabled</string>
|
||||
<string name="revanced_swipe_volume_title">Swipe controls for Volume</string>
|
||||
<string name="revanced_swipe_pts_title">Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_pts_summary_off">Swipe controls are always active</string>
|
||||
<string name="revanced_swipe_pts_summary_on">Swipe controls require a long-press before activating</string>
|
||||
<string name="revanced_swipe_pts_haptic_title">Vibrate on Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_pts_haptic_summary_on">You\'ll get haptic feedback when activating Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_pts_haptic_summary_off">You won\'t get haptic feedback when activating Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_overlay_timeout_title">Overlay Timeout</string>
|
||||
<string name="revanced_swipe_overlay_timeout_summary">How long the overlay is shown after changes (ms)</string>
|
||||
<string name="revanced_swipe_overlay_text_size_title">Overlay Text Size</string>
|
||||
<string name="revanced_swipe_overlay_text_size_summary">Text size on the overlay</string>
|
||||
<string name="revanced_swipe_overlay_bg_alpha_title">Overlay Background Transparency</string>
|
||||
<string name="revanced_swipe_overlay_bg_alpha_summary">Transparency value of the overlay background (0–255)</string>
|
||||
<string name="revanced_swipe_magnitude_threshold_title">Swipe Magnitude Threshold</string>
|
||||
<string name="revanced_swipe_magnitude_threshold_summary">Minimum magnitude before a swipe is detected</string>
|
||||
<string name="revanced_swipe_tablet_title">Tablet style</string>
|
||||
<string name="revanced_swipe_tablet_summary_on">Tablet style is turned on. For example suggested videos are only partially working</string>
|
||||
<string name="revanced_swipe_tablet_summary_off">Tablet style is turned off</string>
|
||||
<string name="revanced_website_summary">Tap to open our website</string>
|
||||
<string name="revanced_website_title">ReVanced website</string>
|
||||
<string name="revanced_home_ads_summary_off">Home ADS are hidden</string>
|
||||
<string name="revanced_home_ads_summary_on">Home ADS are shown</string>
|
||||
<string name="revanced_home_ads_title">Home ADS</string>
|
||||
<string name="revanced_video_ads_title">Video ADS</string>
|
||||
<string name="revanced_video_ads_summary_off">Video ADS are hidden</string>
|
||||
<string name="revanced_video_ads_summary_on">Video ADS are shown</string>
|
||||
<string name="revanced_reel_summary_off">Stories are hidden</string>
|
||||
<string name="revanced_reel_summary_on">Stories are shown</string>
|
||||
<string name="revanced_reel_title">YouTube stories</string>
|
||||
<string name="revanced_ad_settings_title">AD settings</string>
|
||||
<string name="revanced_tablet_miniplayer_summary_off">Tablet miniplayer is not being used</string>
|
||||
<string name="revanced_tablet_miniplayer_summary_on">Tablet miniplayer is being used</string>
|
||||
<string name="revanced_tablet_miniplayer_title">Tablet miniplayer</string>
|
||||
|
||||
<string name="litho_comments">Comments removal</string>
|
||||
<string name="litho_comments_off">Comments removal is turned off (new comments / phones only)</string>
|
||||
<string name="litho_comments_on">Comments removal is turned on (new comments / phones only)</string>
|
||||
<string name="litho_community_posts">Community post removal</string>
|
||||
<string name="litho_community_posts_off">Community post removal is turned off</string>
|
||||
<string name="litho_community_posts_on">Community post removal is turned on</string>
|
||||
<string name="litho_compact_banner">Compact banner removal</string>
|
||||
<string name="litho_compact_banner_off">Compact banner removal is turned off</string>
|
||||
<string name="litho_compact_banner_on">Compact banner removal is turned on</string>
|
||||
<string name="litho_compact_movie">Compact movie removal</string>
|
||||
<string name="litho_compact_movie_off">Compact movie removal is turned off</string>
|
||||
<string name="litho_compact_movie_on">Compact movie removal is turned on</string>
|
||||
<string name="litho_general_ad_removal">General layout ad removal</string>
|
||||
<string name="litho_general_ad_removal_off">General layout ad removal is turned off</string>
|
||||
<string name="litho_general_ad_removal_on">General layout ad removal is turned on</string>
|
||||
<string name="litho_horizontal_movie_shelf">Movie shelf removal</string>
|
||||
<string name="litho_horizontal_movie_shelf_off">Movie shelf removal is turned off</string>
|
||||
<string name="litho_horizontal_movie_shelf_on">Movie shelf removal is turned on</string>
|
||||
<string name="litho_in_feed_survey">Survey removal</string>
|
||||
<string name="litho_in_feed_survey_off">Feed survey removal is turned off</string>
|
||||
<string name="litho_in_feed_survey_on">Feed survey removal is turned on</string>
|
||||
<string name="litho_merchandise">Merchandise removal</string>
|
||||
<string name="litho_merchandise_off">Merchandise removal is turned off</string>
|
||||
<string name="litho_merchandise_on">Merchandise removal is turned on</string>
|
||||
<string name="litho_movie_upsell">Movie upsell removal</string>
|
||||
<string name="litho_movie_upsell_off">Movie upsell removal is turned off</string>
|
||||
<string name="litho_movie_upsell_on">Movie upsell removal is turned on</string>
|
||||
<string name="litho_emergency_box">Emergency box removal</string>
|
||||
<string name="litho_emergency_box_on">Emergency box removal is turned on</string>
|
||||
<string name="litho_emergency_box_off">Emergency box removal is turned off</string>
|
||||
<string name="litho_info_panel">Info panel removal</string>
|
||||
<string name="litho_info_panel_on">Info panel removal is turned on</string>
|
||||
<string name="litho_info_panel_off">Info panel removal is turned off</string>
|
||||
<string name="litho_medical_panel">Medical panel removal</string>
|
||||
<string name="litho_medical_panel_on">Medical panel removal is turned on</string>
|
||||
<string name="litho_medical_panel_off">Medical panel removal is turned off</string>
|
||||
<string name="litho_paid_content">Paid content removal</string>
|
||||
<string name="litho_paid_content_on">Paid content removal is turned on</string>
|
||||
<string name="litho_paid_content_off">Paid content removal is turned off</string>
|
||||
<string name="litho_suggested">Suggested for you removal</string>
|
||||
<string name="litho_suggested_on">Suggested for you removal is turned on</string>
|
||||
<string name="litho_suggested_off">Suggested for you removal is turned off</string>
|
||||
<string name="litho_hide_suggestions">General Suggestions removal</string>
|
||||
<string name="litho_hide_suggestions_on">General Suggestions removal is turned on</string>
|
||||
<string name="litho_hide_suggestions_off">General Suggestions removal is turned off</string>
|
||||
<string name="litho_latest_posts">Latest posts removal</string>
|
||||
<string name="litho_latest_posts_on">Latest posts removal is turned on</string>
|
||||
<string name="litho_latest_posts_off">Latest posts removal is turned off</string>
|
||||
<string name="litho_channel_guidelines">Channel guidelines removal</string>
|
||||
<string name="litho_channel_guidelines_on">Channel guidelines removal is turned on</string>
|
||||
<string name="litho_channel_guidelines_off">Channel guidelines removal is turned off</string>
|
||||
|
||||
<string name="microg_notification_settings">Notification settings</string>
|
||||
<string name="microg_notification_settings_summary">"1. Google device registration and Cloud Messaging need to be enabled for notifications.
|
||||
2. ReVanced needs to be shown as registered under Cloud Messaging.
|
||||
3. Current State in Cloud Messaging must be Connected."</string>
|
||||
<string name="microg_settings">MicroG settings</string>
|
||||
<string name="revanced_settings">ReVanced settings</string>
|
||||
|
||||
<string name="revanced_seekbar_tapping">Seekbar Tapping</string>
|
||||
<string name="revanced_seekbar_tapping_off">Seekbar Tapping (video progress bar) is disabled</string>
|
||||
<string name="revanced_seekbar_tapping_on">Seekbar Tapping (video progress bar) is enabled</string>
|
||||
|
||||
<string name="revanced_minimized_playback">Background playback</string>
|
||||
<string name="revanced_minimized_playback_off">Background playback is disabled</string>
|
||||
<string name="revanced_minimized_playback_on">Background playback is enabled</string>
|
||||
|
||||
<string name="pref_subtitles_scale_normal">Normal</string>
|
||||
|
||||
<string name="litho_shorts_shelf">Shorts Shelf</string>
|
||||
<string name="litho_shorts_shelf_off">Shorts Shelf removal is turned off</string>
|
||||
<string name="litho_shorts_shelf_on">Shorts Shelf removal is turned on</string>
|
||||
|
||||
<string name="revanced_create_button_summary_off">Create Button is hidden</string>
|
||||
<string name="revanced_create_button_summary_on">Create Button is shown</string>
|
||||
<string name="revanced_create_button_title">Create Button</string>
|
||||
|
||||
<string name="litho_community_guidelines">Community Guidelines</string>
|
||||
<string name="litho_community_guidelines_off">Community Guidelines removal is turned off</string>
|
||||
<string name="litho_community_guidelines_on">Community Guidelines removal is turned on</string>
|
||||
|
||||
<string name="revanced_copy_video_url_summary_off">Copy Link Button is hidden from the player overlay</string>
|
||||
<string name="revanced_copy_video_url_summary_on">Copy Link Button is shown in the player overlay</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_off">Copy Link Button With Timestamp is hidden from the player overlay</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_on">Copy Link Button With Timestamp is shown in the player overlay</string>
|
||||
<string name="revanced_copy_video_url_timestamp_title">Copy Link Button With Timestamp</string>
|
||||
<string name="revanced_copy_video_url_title">Copy Link Button</string>
|
||||
|
||||
<string name="revanced_old_style_quality_settings_title">Quality Settings style</string>
|
||||
<string name="revanced_old_style_quality_settings_summary_off">Using default style video quality settings</string>
|
||||
<string name="revanced_old_style_quality_settings_summary_on">Using old style video quality settings</string>
|
||||
|
||||
<string name="revanced_videoadwhitelisting_title">Video ad whitelisting</string>
|
||||
<string name="revanced_videoadwhitelisting_summary_off">Video ad whitelisting is turned off</string>
|
||||
<string name="revanced_videoadwhitelisting_summary_on">Video ad whitelisting is turned on. Use the ADS button under the player to whitelist a channel</string>
|
||||
<string name="revanced_whitelisting_ads">ADS</string>
|
||||
<string name="revanced_whitelisting_sponsorblock">SponsorBlock</string>
|
||||
<string name="revanced_whitelisting_added" formatted="false">Channel %s was added to the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_removed" formatted="false">Channel %s was removed from the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_add_failed" formatted="false">Failed to add channel %s to the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_remove_failed" formatted="false">Failed to remove channel %s from the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_fetch_failed" formatted="false">Failed to retrieve channel details, received code %d</string>
|
||||
<string name="revanced_button_location_entry_none">Hidden</string>
|
||||
<string name="revanced_button_location_entry_player">In player</string>
|
||||
<string name="revanced_button_location_entry_buttoncontainer">Under player</string>
|
||||
<string name="revanced_button_location_entry_both">Both</string>
|
||||
<string name="revanced_ryd_settings_title">Return YouTube Dislike settings</string>
|
||||
<string name="revanced_ryd_settings_summary">Uses the RYD API</string>
|
||||
<string name="sb_settings">SponsorBlock settings</string>
|
||||
<string name="sb_summary">Uses the sponsor.ajay.app API</string>
|
||||
<string name="revanced_ryd_title">Enable RYD</string>
|
||||
<string name="revanced_ryd_summary">Switch this on to see the dislike counts again</string>
|
||||
<string name="revanced_ryd_attribution_title">Return YouTube Dislike Integration</string>
|
||||
<string name="revanced_ryd_attribution_summary">This integration uses the RYD API from https://returnyoutubedislike.com. Tap to learn more</string>
|
||||
</resources>
|
||||
12
src/main/resources/settings/host/xml/settings_fragment.xml
Normal file
12
src/main/resources/settings/host/xml/settings_fragment.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<Preference android:title="@string/revanced_ryd_settings_title" android:summary="@string/revanced_ryd_settings_summary">
|
||||
<intent android:targetPackage="com.google.android.youtube" android:data="ryd_settings" android:targetClass="com.google.android.libraries.social.licenses.LicenseActivity"/>
|
||||
</Preference>
|
||||
<Preference android:title="@string/sb_settings" android:summary="@string/sb_summary">
|
||||
<intent android:targetPackage="com.google.android.youtube" android:data="sponsorblock_settings" android:targetClass="com.google.android.libraries.social.licenses.LicenseActivity"/>
|
||||
</Preference>
|
||||
<Preference android:title="@string/revanced_settings">
|
||||
<intent android:targetPackage="com.google.android.youtube" android:data="revanced_settings" android:targetClass="com.google.android.libraries.social.licenses.LicenseActivity"/>
|
||||
</Preference>
|
||||
</PreferenceScreen>
|
||||
4
src/main/resources/settings/layout/xsettings_toolbar.xml
Normal file
4
src/main/resources/settings/layout/xsettings_toolbar.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="@color/yt_white1" android:layout_width="match_parent" android:layout_height="wrap_content" android:elevation="4dp">
|
||||
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="?attr/ytBrandBackgroundSolid" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationIcon="@drawable/quantum_ic_arrow_back_white_24" app:title="ReVanced settings"/>
|
||||
</FrameLayout>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge>
|
||||
<include layout="@layout/xsettings_with_toolbar_layout"/>
|
||||
</merge>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="match_parent" android:transitionGroup="true">
|
||||
<include layout="@layout/xsettings_toolbar"/>
|
||||
<FrameLayout android:id="@+id/xsettings_fragments" android:layout_width="match_parent" android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
180
src/main/resources/settings/xml/revanced_prefs.xml
Normal file
180
src/main/resources/settings/xml/revanced_prefs.xml
Normal file
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yt="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceCategory
|
||||
android:layout_height="match_parent"
|
||||
android:title="@string/revanced_settings" />
|
||||
<PreferenceScreen android:title="@string/revanced_codec_override_title" android:key="revanced_override_codec">
|
||||
<SwitchPreference android:title="@string/revanced_vp9_title" android:key="revanced_override_codec_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_vp9_summary_on" android:summaryOff="@string/revanced_vp9_summary_off" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_video_settings_title" android:key="video_settings">
|
||||
<SwitchPreference android:title="@string/revanced_old_style_quality_settings_title" android:key="revanced_use_old_style_quality_settings" android:defaultValue="true" android:summaryOn="@string/revanced_old_style_quality_settings_summary_on" android:summaryOff="@string/revanced_old_style_quality_settings_summary_off" />
|
||||
<ListPreference android:title="@string/revanced_preferred_video_speed_title" android:key="revanced_pref_video_speed" android:summary="@string/revanced_preferred_video_speed_summary" />
|
||||
<!--<SwitchPreference android:title="Auto captions" android:key="revanced_pref_auto_captions" android:defaultValue="false" android:summaryOn="Auto captions are turned on" android:summaryOff="Auto captions are turned off" />-->
|
||||
</PreferenceScreen>
|
||||
<!--<PreferenceScreen android:title="@string/revanced_videoadwhitelisting_title" android:key="video_ad_settings">
|
||||
<SwitchPreference android:title="@string/revanced_videoadwhitelisting_title" android:key="revanced_whitelist_ads_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_videoadwhitelisting_summary_on" android:summaryOff="@string/revanced_videoadwhitelisting_summary_off" />
|
||||
</PreferenceScreen>-->
|
||||
<PreferenceScreen
|
||||
android:key="ad_settings"
|
||||
android:title="@string/revanced_ad_settings_title">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="revanced_home_ads_enabled"
|
||||
android:summaryOff="@string/revanced_home_ads_summary_off"
|
||||
android:summaryOn="@string/revanced_home_ads_summary_on"
|
||||
android:title="@string/revanced_home_ads_title" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="revanced_video_ads_enabled"
|
||||
android:summaryOff="@string/revanced_video_ads_summary_off"
|
||||
android:summaryOn="@string/revanced_video_ads_summary_on"
|
||||
android:title="@string/revanced_video_ads_title" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_ad_removal"
|
||||
android:summaryOff="@string/litho_general_ad_removal_off"
|
||||
android:summaryOn="@string/litho_general_ad_removal_on"
|
||||
android:title="@string/litho_general_ad_removal" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_merchandise"
|
||||
android:summaryOff="@string/litho_merchandise_off"
|
||||
android:summaryOn="@string/litho_merchandise_on"
|
||||
android:title="@string/litho_merchandise" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_community_posts_removal"
|
||||
android:summaryOff="@string/litho_community_posts_off"
|
||||
android:summaryOn="@string/litho_community_posts_on"
|
||||
android:title="@string/litho_community_posts" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_compact_banner_removal"
|
||||
android:summaryOff="@string/litho_compact_banner_off"
|
||||
android:summaryOn="@string/litho_compact_banner_on"
|
||||
android:title="@string/litho_compact_banner" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="revanced_adremover_comments_removal"
|
||||
android:summaryOff="@string/litho_comments_off"
|
||||
android:summaryOn="@string/litho_comments_on"
|
||||
android:title="@string/litho_comments" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_movie"
|
||||
android:summaryOff="@string/litho_compact_movie_off"
|
||||
android:summaryOn="@string/litho_compact_movie_on"
|
||||
android:title="@string/litho_compact_movie" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_feed_survey"
|
||||
android:summaryOff="@string/litho_in_feed_survey_off"
|
||||
android:summaryOn="@string/litho_in_feed_survey_on"
|
||||
android:title="@string/litho_in_feed_survey" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_shorts_shelf"
|
||||
android:summaryOff="@string/litho_shorts_shelf_off"
|
||||
android:summaryOn="@string/litho_shorts_shelf_on"
|
||||
android:title="@string/litho_shorts_shelf" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_community_guideline"
|
||||
android:summaryOff="@string/litho_community_guidelines_off"
|
||||
android:summaryOn="@string/litho_community_guidelines_on"
|
||||
android:title="@string/litho_community_guidelines" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_emergency_box_removal"
|
||||
android:summaryOff="@string/litho_emergency_box_off"
|
||||
android:summaryOn="@string/litho_emergency_box_on"
|
||||
android:title="@string/litho_emergency_box" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_info_panel"
|
||||
android:summaryOff="@string/litho_info_panel_off"
|
||||
android:summaryOn="@string/litho_info_panel_on"
|
||||
android:title="@string/litho_info_panel" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_medical_panel"
|
||||
android:summaryOff="@string/litho_medical_panel_off"
|
||||
android:summaryOn="@string/litho_medical_panel_on"
|
||||
android:title="@string/litho_medical_panel" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_paid_content"
|
||||
android:summaryOff="@string/litho_paid_content_off"
|
||||
android:summaryOn="@string/litho_paid_content_on"
|
||||
android:title="@string/litho_paid_content" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_suggested"
|
||||
android:summaryOff="@string/litho_suggested_off"
|
||||
android:summaryOn="@string/litho_suggested_on"
|
||||
android:title="@string/litho_suggested" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_hide_suggestions"
|
||||
android:summaryOff="@string/litho_hide_suggestions_off"
|
||||
android:summaryOn="@string/litho_hide_suggestions_on"
|
||||
android:title="@string/litho_hide_suggestions" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_hide_latest_posts"
|
||||
android:summaryOff="@string/litho_latest_posts_off"
|
||||
android:summaryOn="@string/litho_latest_posts_on"
|
||||
android:title="@string/litho_latest_posts" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_hide_channel_guidelines"
|
||||
android:summaryOff="@string/litho_channel_guidelines_off"
|
||||
android:summaryOn="@string/litho_channel_guidelines_on"
|
||||
android:title="@string/litho_channel_guidelines" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_layout_settings_title" android:key="layout_settings">
|
||||
<SwitchPreference android:title="@string/revanced_reel_title" android:key="revanced_reel_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_reel_summary_on" android:summaryOff="@string/revanced_reel_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_suggestion_title" android:key="revanced_info_cards_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_suggestion_summary_on" android:summaryOff="@string/revanced_suggestion_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_branding_watermark_title" android:key="revanced_branding_watermark_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_branding_watermark_summary_on" android:summaryOff="@string/revanced_branding_watermark_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_cast_button_title" android:key="revanced_cast_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_cast_button_summary_on" android:summaryOff="@string/revanced_cast_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_autoplay_button_title" android:key="revanced_autoplay_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_autoplay_button_summary_on" android:summaryOff="@string/revanced_autoplay_button_summary_off" />
|
||||
<!--<SwitchPreference android:title="@string/revanced_tablet_miniplayer_title" android:key="revanced_tablet_miniplayer" android:defaultValue="false" android:summaryOn="@string/revanced_tablet_miniplayer_summary_on" android:summaryOff="@string/revanced_tablet_miniplayer_summary_off" />-->
|
||||
<SwitchPreference android:title="@string/revanced_create_button_title" android:key="revanced_create_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_create_button_summary_on" android:summaryOff="@string/revanced_create_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_new_actionbar_title" android:key="revanced_new_actionbar" android:defaultValue="false" android:summaryOn="@string/revanced_new_actionbar_summary_on" android:summaryOff="@string/revanced_new_actionbar_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_shorts_button_title" android:key="revanced_shorts_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_shorts_button_summary_on" android:summaryOff="@string/revanced_shorts_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_fullscreen_panels_title" android:key="revanced_fullscreen_panels_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_fullscreen_panels_summary_on" android:summaryOff="@string/revanced_fullscreen_panels_summary_off" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_misc_title" android:key="misc_screen">
|
||||
<SwitchPreference android:title="@string/revanced_auto_repeat_title" android:key="revanced_pref_auto_repeat" android:defaultValue="false" android:summaryOn="@string/revanced_auto_repeat_summary_on" android:summaryOff="@string/revanced_auto_repeat_summary_off" />
|
||||
<!--<ListPreference android:entries="@array/revanced_button_location_entries" android:title="@string/revanced_copy_video_url_timestamp_title" android:key="revanced_pref_copy_video_url_timestamp_button_list" android:entryValues="@array/revanced_button_location_entry_values" />
|
||||
<ListPreference android:entries="@array/revanced_button_location_entries" android:title="@string/revanced_copy_video_url_title" android:key="revanced_pref_copy_video_url_button_list" android:entryValues="@array/revanced_button_location_entry_values" />-->
|
||||
<SwitchPreference android:title="@string/revanced_hdr_full_brightness_title" android:key="revanced_pref_hdr_autobrightness" android:defaultValue="false" android:summaryOn="@string/revanced_hdr_full_brightness_summary_on" android:summaryOff="@string/revanced_hdr_full_brightness_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_seekbar_tapping" android:key="revanced_enable_tap_seeking" android:defaultValue="true" android:summaryOn="@string/revanced_seekbar_tapping_on" android:summaryOff="@string/revanced_seekbar_tapping_off" />
|
||||
<SwitchPreference android:title="@string/revanced_minimized_playback" android:key="revanced_enable_minimized_playback" android:defaultValue="true" android:summaryOn="@string/revanced_minimized_playback_on" android:summaryOff="@string/revanced_minimized_playback_off" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_swipe_title" android:key="swipe_screen" android:summary="@string/revanced_swipe_screen_summary">
|
||||
<SwitchPreference android:title="@string/revanced_swipe_brightness_title" android:key="revanced_enable_swipe_brightness" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_brightness_summary_on" android:summaryOff="@string/revanced_swipe_brightness_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_swipe_volume_title" android:key="revanced_enable_swipe_volume" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_volume_summary_on" android:summaryOff="@string/revanced_swipe_volume_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_swipe_pts_title" android:key="revanced_enable_press_to_swipe" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_pts_summary_on" android:summaryOff="@string/revanced_swipe_pts_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_swipe_pts_haptic_title" android:key="revanced_enable_swipe_haptic_feedback" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_pts_haptic_summary_on" android:summaryOff="@string/revanced_swipe_pts_haptic_summary_off" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_overlay_timeout_title" android:key="revanced_swipe_overlay_timeout" android:summary="@string/revanced_swipe_overlay_timeout_summary" android:defaultValue="500" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_overlay_text_size_title" android:key="revanced_swipe_overlay_text_size" android:summary="@string/revanced_swipe_overlay_text_size_summary" android:defaultValue="22" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_overlay_bg_alpha_title" android:key="revanced_swipe_overlay_background_alpha" android:summary="@string/revanced_swipe_overlay_bg_alpha_summary" android:defaultValue="127" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_magnitude_threshold_title" android:key="revanced_swipe_magnitude_threshold" android:summary="@string/revanced_swipe_magnitude_threshold_summary" android:defaultValue="30" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_buffer_title" android:key="buffer_screen">
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_maximum_buffer_title" android:key="revanced_pref_max_buffer_ms" android:summary="@string/revanced_maximum_buffer_summary" android:defaultValue="120000" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_playback_start_title" android:key="revanced_pref_buffer_for_playback_ms" android:summary="@string/revanced_playback_start_summary" android:defaultValue="2500" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_rebuffer_title" android:key="revanced_pref_buffer_for_playback_after_rebuffer_ms" android:summary="@string/revanced_rebuffer_summary" android:defaultValue="5000" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_support_title" android:key="support_screen" android:summary="@string/revanced_support_summary">
|
||||
<Preference android:title="@string/revanced_discord_title" android:summary="@string/revanced_discord_summary">
|
||||
<intent android:action="android.intent.action.VIEW" android:data="https://discord.gg/rF2YcEjcrT" />
|
||||
</Preference>
|
||||
<Preference android:title="@string/revanced_website_title" android:summary="@string/revanced_website_summary">
|
||||
<intent android:action="android.intent.action.VIEW" android:data="https://revanced.app" />
|
||||
</Preference>
|
||||
</PreferenceScreen>
|
||||
<SwitchPreference android:title="@string/revanced_debug_title" android:key="revanced_debug_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_debug_summary_on" android:summaryOff="@string/revanced_debug_summary_off" />
|
||||
</PreferenceScreen>
|
||||
@@ -57,7 +57,7 @@
|
||||
<string name="about">About</string>
|
||||
<string name="about_api">This app uses the API from SponsorBlock</string>
|
||||
<string name="about_api_sum">Tap to learn more, and see downloads for other platforms at: sponsor.ajay.app</string>
|
||||
<string name="about_madeby">Integration made by JakubWeg</string>
|
||||
<string name="about_madeby">Integration made by JakubWeg, recoded by oSumAtrIX</string>
|
||||
<string name="tap_skip">Tap to skip</string>
|
||||
|
||||
<string name="submit_failed_unknown_error" formatted="false">Unable to submit segments: Status: %d %s</string>
|
||||
@@ -105,9 +105,6 @@
|
||||
<string name="sb_guidelines_popup_already_read">Already read</string>
|
||||
<string name="sb_guidelines_popup_open">Show me</string>
|
||||
|
||||
<string name="sb_settings">SponsorBlock settings</string>
|
||||
<string name="sb_summary">Uses the sponsor.ajay.app API</string>
|
||||
|
||||
<string name="general_time_without_sb">Show time without segments</string>
|
||||
<string name="general_time_without_sb_sum">This time appears in brackets next to the current time. This shows the total video duration minus any segments.</string>
|
||||
<string name="general_whitelisting">Channel whitelisting</string>
|
||||
|
||||
Reference in New Issue
Block a user