diff --git a/.github/ISSUE_TEMPLATE/bug-issue.yml b/.github/ISSUE_TEMPLATE/bug-issue.yml
deleted file mode 100644
index 6b98f0483..000000000
--- a/.github/ISSUE_TEMPLATE/bug-issue.yml
+++ /dev/null
@@ -1,73 +0,0 @@
-name: 🐞 Bug report
-description: Report a very clearly broken issue.
-title: 'bug: '
-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. Capture crash logs by running `logcat | grep AndroidRuntime`.
- 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
- - type: checkboxes
- id: acknowledgements
- attributes:
- label: Acknowledgements
- description: Your issue will be closed if you haven't done these steps.
- options:
- - label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
- required: true
- - label: I have written a short but informative title.
- required: true
- - label: I filled out all of the requested information in this issue properly.
- required: true
diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
new file mode 100644
index 000000000..910adefc7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -0,0 +1,49 @@
+name: 🐞 Bug report
+description: Report a bug or an issue.
+title: 'bug: '
+labels: ['Bug report']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ # ReVanced Patches bug report
+
+ Please check for existing bug reports
+ [here](https://github.com/ReVanced/revanced-patches/labels/Bug%20report)
+ before creating a new one.
+
+ - type: textarea
+ attributes:
+ label: Bug description
+ description: |
+ - Describe your bug in detail
+ - Add steps to reproduce the bug if possible (Step 1. ... Step 2. ...)
+ - Add images and videos if possible
+ - List used patches if applicable
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Error logs
+ description: Exceptions can be captured by running `logcat | grep AndroidRuntime` in a shell.
+ render: shell
+ - type: textarea
+ attributes:
+ label: Solution
+ description: If applicable, add a possible solution to the bug.
+ - type: textarea
+ attributes:
+ label: Additional context
+ description: Add additional context here.
+ - type: checkboxes
+ id: acknowledgements
+ attributes:
+ label: Acknowledgements
+ description: Your issue will be closed if you don't follow the checklist below.
+ options:
+ - label: This request is not a duplicate of an existing issue.
+ required: true
+ - label: I have chosen an appropriate title.
+ required: true
+ - label: All requested information has been provided properly.
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 9f537ff85..6fb647b70 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,8 +1,5 @@
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!
\ No newline at end of file
+ about: Have something unspecific to ReVanced Patches in mind? Search for or start a new discussion!
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
new file mode 100644
index 000000000..63f7ad2da
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -0,0 +1,44 @@
+name: ⭐ Feature request
+description: Create a detailed request for a new feature.
+title: 'feat: '
+labels: ['Feature request']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ # ReVanced Patches feature request
+
+ Please check for existing feature requests
+ [here](https://github.com/ReVanced/revanced-patches/labels/Feature%20request)
+ before creating a new one.
+ - type: textarea
+ attributes:
+ label: Feature description
+ description: |
+ - Describe your feature in detail
+ - Add images, videos, links, examples, references, etc. if possible
+ - Add the target application name in case you request a new patch
+ - type: textarea
+ attributes:
+ label: Motivation
+ description: |
+ A strong motivation is necessary for a feature request to be considered.
+
+ - Why should this feature be implemented?
+ - What is the explicit use case?
+ - What are the benefits?
+ - What makes this feature important?
+ validations:
+ required: true
+ - type: checkboxes
+ id: acknowledgements
+ attributes:
+ label: Acknowledgements
+ description: Your issue will be closed if you don't follow the checklist below.
+ options:
+ - label: This request is not a duplicate of an existing issue.
+ required: true
+ - label: I have chosen an appropriate title.
+ required: true
+ - label: All requested information has been provided properly.
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/patch-request.yml b/.github/ISSUE_TEMPLATE/patch-request.yml
deleted file mode 100644
index 35084c206..000000000
--- a/.github/ISSUE_TEMPLATE/patch-request.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-name: ⭐ Patch Request
-description: Create a detailed patch request.
-title: 'feat: '
-labels: [patch-request]
-body:
- - type: textarea
- attributes:
- label: Application
- description: Which application is this patch for?
- validations:
- required: true
- - type: textarea
- attributes:
- label: Issue
- description: What is the issue this patch should solve?
- validations:
- required: true
- - type: textarea
- attributes:
- label: Patch
- description: "Describe the patch you'd like to see in detail."
- validations:
- required: true
- - type: textarea
- attributes:
- label: Motivation
- description: Why should your patch request be considered? What makes it valuable to the community?
- validations:
- required: true
- - type: checkboxes
- id: acknowledgements
- attributes:
- label: Acknowledgements
- description: Your issue will be closed if you haven't done these steps.
- options:
- - label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
- required: true
- - label: I have written a short but informative title.
- required: true
- - label: I filled out all of the requested information in this issue properly.
- required: true
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index 8b208066e..da51ad113 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -1,4 +1,4 @@
-name: PR to main
+name: Open a PR to main
on:
push:
@@ -7,7 +7,7 @@ on:
workflow_dispatch:
env:
- MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main`
+ MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main`
jobs:
pull-request:
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Open pull request
uses: repo-sync/pull-request@v2
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0b122f635..c3be77c5e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
# Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef164c8c5..64b12f7f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,319 @@
+# [2.191.0-dev.33](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.32...v2.191.0-dev.33) (2023-10-04)
+
+
+### Bug Fixes
+
+* **TikTok - Hide ads:** Constrain to last working version ([56e45a6](https://github.com/ReVanced/revanced-patches/commit/56e45a60a405b5382e1ef6f7bcd5de570c7c52ef))
+
+# [2.191.0-dev.32](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.31...v2.191.0-dev.32) (2023-10-03)
+
+
+### Bug Fixes
+
+* **Sync for Reddit:** Do not throw an error when not necessary ([ef644e4](https://github.com/ReVanced/revanced-patches/commit/ef644e48018a90429108779b7419299c4f43e4ff))
+
+
+### Features
+
+* **Sync for Reddit - Client spoof:** Restore upload functionality ([9344c8a](https://github.com/ReVanced/revanced-patches/commit/9344c8a067127b0fb4ee8599c5dcfcb206b4ee07))
+* Use properties file for `Client spoof` patches ([e5d548c](https://github.com/ReVanced/revanced-patches/commit/e5d548c6427fb54968f26d706ff16274e72f700a))
+
+# [2.191.0-dev.31](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.30...v2.191.0-dev.31) (2023-10-02)
+
+
+### Bug Fixes
+
+* **YouTube - SponsorBlock:** Adjust import/export UI text ([#3063](https://github.com/ReVanced/revanced-patches/issues/3063)) ([4e5513e](https://github.com/ReVanced/revanced-patches/commit/4e5513e973f5de7c9f6330dfe7a0744e91f305b4))
+
+# [2.191.0-dev.30](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.29...v2.191.0-dev.30) (2023-10-02)
+
+
+### Bug Fixes
+
+* Add hooks to existing hook set ([5655067](https://github.com/ReVanced/revanced-patches/commit/5655067f28d010f3a7a6d91b09ac984eee162031))
+* **Google Recorder - Remove device restrictions:** Clarify limitation ([094f57b](https://github.com/ReVanced/revanced-patches/commit/094f57b601d746079c43fd5c8834e3e6be07f946))
+
+
+### Features
+
+* **YouTube - Hide layout components:** Hide search result shelf header ([f4eda8c](https://github.com/ReVanced/revanced-patches/commit/f4eda8c8d111cc856d5878a32ddca3f7c2e0df31))
+
+# [2.191.0-dev.29](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.28...v2.191.0-dev.29) (2023-10-01)
+
+
+### Features
+
+* **TikTok - Hide ads:** Constrain to last working version ([516e8a1](https://github.com/ReVanced/revanced-patches/commit/516e8a14c0e113f9f4c0dda9be223cf3e929eb3a))
+
+# [2.191.0-dev.28](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.27...v2.191.0-dev.28) (2023-10-01)
+
+
+### Bug Fixes
+
+* **YouTube - Hide "Load more" button:** Use correct names ([569c3cd](https://github.com/ReVanced/revanced-patches/commit/569c3cde9875b807c9116322ca324f69b5fa0218))
+* **YouTube - Hide shorts components:** Fix hiding navigation bar ([2de51e6](https://github.com/ReVanced/revanced-patches/commit/2de51e65f05be8a6364dfdfe9cd36e8fed5737f6))
+
+# [2.191.0-dev.27](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.26...v2.191.0-dev.27) (2023-10-01)
+
+
+### Features
+
+* **Tumblr:** Add `Disable in-app update` patch ([#3058](https://github.com/ReVanced/revanced-patches/issues/3058)) ([5e8076b](https://github.com/ReVanced/revanced-patches/commit/5e8076b330cabe57130233adacdf84b56f010217))
+
+# [2.191.0-dev.26](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.25...v2.191.0-dev.26) (2023-10-01)
+
+
+### Bug Fixes
+
+* Use correct instruction ([246cf2c](https://github.com/ReVanced/revanced-patches/commit/246cf2cc92624e43bc7405cb32be9b560bb648c5))
+
+# [2.191.0-dev.25](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.24...v2.191.0-dev.25) (2023-10-01)
+
+
+### Features
+
+* **YouTube - Hide layout components:** Hide "Join" button ([1b71f89](https://github.com/ReVanced/revanced-patches/commit/1b71f893bb9fd8511833b8895031c8d8122a6efb))
+* **YouTube - Hide layout components:** Hide "Notify me" button ([3027c15](https://github.com/ReVanced/revanced-patches/commit/3027c1575717588f43f4b95be6ba97dac2b94069))
+* **YouTube - Hide layout components:** Hide timed reactions ([d0a775d](https://github.com/ReVanced/revanced-patches/commit/d0a775d685b1e0564804d564d1cbcbb8d0a04b03))
+
+# [2.191.0-dev.24](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.23...v2.191.0-dev.24) (2023-09-30)
+
+
+### Features
+
+* **Duolingo:** Remove `Unlock Duolingo Super` patch ([b4b9746](https://github.com/ReVanced/revanced-patches/commit/b4b9746361b5435b9d9429ad065e53364c51904a))
+
+# [2.191.0-dev.23](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.22...v2.191.0-dev.23) (2023-09-30)
+
+
+### Features
+
+* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([481bf58](https://github.com/ReVanced/revanced-patches/commit/481bf583afbf954bef1c4e5349a62ea1c623115a))
+
+# [2.191.0-dev.22](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.21...v2.191.0-dev.22) (2023-09-28)
+
+
+### Bug Fixes
+
+* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([b33ed75](https://github.com/ReVanced/revanced-patches/commit/b33ed757370653b8eb0002b0977eedfbc73dbe5e))
+
+# [2.191.0-dev.21](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.20...v2.191.0-dev.21) (2023-09-28)
+
+
+### Bug Fixes
+
+* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([3761073](https://github.com/ReVanced/revanced-patches/commit/37610732da87549c22a430bb62d10793dfa2e696))
+
+# [2.191.0-dev.20](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.19...v2.191.0-dev.20) (2023-09-28)
+
+
+### Bug Fixes
+
+* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([f6f226b](https://github.com/ReVanced/revanced-patches/commit/f6f226ba281823cb5d2d468c32f6e48551971726))
+
+# [2.191.0-dev.19](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.18...v2.191.0-dev.19) (2023-09-28)
+
+
+### Features
+
+* **YouTube:** Add `Bypass URL redirects` patch ([125cac5](https://github.com/ReVanced/revanced-patches/commit/125cac5928c9b71d35253f1fd7651f4a30e15529))
+
+# [2.191.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.17...v2.191.0-dev.18) (2023-09-28)
+
+
+### Features
+
+* **YouTube - Premium heading:** Allow using default heading ([#3029](https://github.com/ReVanced/revanced-patches/issues/3029)) ([d5ab35a](https://github.com/ReVanced/revanced-patches/commit/d5ab35a444523baa0586fcb9513d6ae4f2518946))
+
+# [2.191.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.16...v2.191.0-dev.17) (2023-09-27)
+
+
+### Features
+
+* **YouTube:** Bump compatibility to `18.37.36` ([#3028](https://github.com/ReVanced/revanced-patches/issues/3028)) ([eda28e5](https://github.com/ReVanced/revanced-patches/commit/eda28e507e7fb5171eeb15a5a0532929ee611211))
+
+# [2.191.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.15...v2.191.0-dev.16) (2023-09-27)
+
+
+### Bug Fixes
+
+* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#3039](https://github.com/ReVanced/revanced-patches/issues/3039)) ([cb38637](https://github.com/ReVanced/revanced-patches/commit/cb38637e6be968d54561a1e0466b9259dbf0b4ee))
+
+# [2.191.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.14...v2.191.0-dev.15) (2023-09-26)
+
+
+### Bug Fixes
+
+* **YouTube - Client spoof:** adjust settings text ([#3035](https://github.com/ReVanced/revanced-patches/issues/3035)) ([59a2e96](https://github.com/ReVanced/revanced-patches/commit/59a2e9617fc4f898e87cefeb3d2c6996b925fa90))
+
+# [2.191.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.13...v2.191.0-dev.14) (2023-09-26)
+
+
+### Bug Fixes
+
+* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([1a79300](https://github.com/ReVanced/revanced-patches/commit/1a793007c919753a8c31ab2382d86c0546eefe20))
+
+# [2.191.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.12...v2.191.0-dev.13) (2023-09-25)
+
+
+### Bug Fixes
+
+* **YouTube - Client spoof:** Removed unused code ([#3030](https://github.com/ReVanced/revanced-patches/issues/3030)) ([15e27bf](https://github.com/ReVanced/revanced-patches/commit/15e27bf93e6366ba8a59091409c4271c8230edb6))
+
+# [2.191.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.11...v2.191.0-dev.12) (2023-09-25)
+
+
+### Bug Fixes
+
+* **YouTube - Client spoof:** Display seekbar thumbnails in high quality ([5e8a2d3](https://github.com/ReVanced/revanced-patches/commit/5e8a2d3fe77a4a08ea32e7dc22f2c8e4048b7a6b))
+
+# [2.191.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.10...v2.191.0-dev.11) (2023-09-25)
+
+
+### Features
+
+* Add notice for thumbnails for age restricted or paid videos ([f7cf70b](https://github.com/ReVanced/revanced-patches/commit/f7cf70b5d3f415411fa767931a33e84df9df6c16))
+
+# [2.191.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.9...v2.191.0-dev.10) (2023-09-25)
+
+
+### Bug Fixes
+
+* **YouTube - Client spoof:** Restore seekbar thumbnails ([bf4a115](https://github.com/ReVanced/revanced-patches/commit/bf4a1159ff745f8f91e11f30db4651d85769227b))
+
+# [2.191.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.8...v2.191.0-dev.9) (2023-09-25)
+
+
+### Features
+
+* **Strava:** Add `Disable subscription suggestions` patch ([#2997](https://github.com/ReVanced/revanced-patches/issues/2997)) ([af02175](https://github.com/ReVanced/revanced-patches/commit/af0217594d9c7526f550fc7e6f09f8a9232e72cf))
+
+# [2.191.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.7...v2.191.0-dev.8) (2023-09-24)
+
+
+### Bug Fixes
+
+* **Relay - Spoof client:** Restore OAuth login ([96e01f7](https://github.com/ReVanced/revanced-patches/commit/96e01f7a7b87f468776fbde48e114a3f51630a46))
+* **Slide - Spoof client:** Use correct patch name ([f355dbf](https://github.com/ReVanced/revanced-patches/commit/f355dbf1d2af3075c6a3f13d8bf5f8dca22e6005))
+
+# [2.191.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.6...v2.191.0-dev.7) (2023-09-24)
+
+
+### Bug Fixes
+
+* **Duolingo - Unlock Super:** Get correct instruction offset ([#3023](https://github.com/ReVanced/revanced-patches/issues/3023)) ([5146de8](https://github.com/ReVanced/revanced-patches/commit/5146de872acb17d7c21019ac7ed531f27361038f))
+
+# [2.191.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.5...v2.191.0-dev.6) (2023-09-23)
+
+
+### Bug Fixes
+
+* **YouTube - Client spoof:** Do not record feed videos to history by default ([#3017](https://github.com/ReVanced/revanced-patches/issues/3017)) ([5ccbf1b](https://github.com/ReVanced/revanced-patches/commit/5ccbf1bf8ed92cde61689a2b1e3a3c1e915959a7))
+
+
+### Features
+
+* **Tumblr:** Add `Disable Tumblr Live` patch ([#2987](https://github.com/ReVanced/revanced-patches/issues/2987)) ([bf1f9dc](https://github.com/ReVanced/revanced-patches/commit/bf1f9dc799705679d17973e689165ab1bff327cd))
+* **YouTube - Spoof app version:** add version 18.20.39 ([#3001](https://github.com/ReVanced/revanced-patches/issues/3001)) ([f14c5e7](https://github.com/ReVanced/revanced-patches/commit/f14c5e79792f62fb060dd0eebbd3dd7157a08a98))
+
+# [2.191.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.5...v2.191.0-dev.6) (2023-09-23)
+
+
+### Features
+
+* **Tumblr:** Add `Disable Tumblr Live` patch ([#2987](https://github.com/ReVanced/revanced-patches/issues/2987)) ([bf1f9dc](https://github.com/ReVanced/revanced-patches/commit/bf1f9dc799705679d17973e689165ab1bff327cd))
+* **YouTube - Spoof app version:** add version 18.20.39 ([#3001](https://github.com/ReVanced/revanced-patches/issues/3001)) ([f14c5e7](https://github.com/ReVanced/revanced-patches/commit/f14c5e79792f62fb060dd0eebbd3dd7157a08a98))
+
+# [2.191.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.5...v2.191.0-dev.6) (2023-09-21)
+
+
+### Features
+
+* **Tumblr:** Add `Disable Tumblr Live` patch ([#2987](https://github.com/ReVanced/revanced-patches/issues/2987)) ([bf1f9dc](https://github.com/ReVanced/revanced-patches/commit/bf1f9dc799705679d17973e689165ab1bff327cd))
+* **YouTube - Spoof app version:** add version 18.20.39 ([#3001](https://github.com/ReVanced/revanced-patches/issues/3001)) ([f14c5e7](https://github.com/ReVanced/revanced-patches/commit/f14c5e79792f62fb060dd0eebbd3dd7157a08a98))
+
+# [2.191.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.5...v2.191.0-dev.6) (2023-09-20)
+
+
+### Features
+
+* **Tumblr:** Add `Disable Tumblr Live` patch ([#2987](https://github.com/ReVanced/revanced-patches/issues/2987)) ([bf1f9dc](https://github.com/ReVanced/revanced-patches/commit/bf1f9dc799705679d17973e689165ab1bff327cd))
+* **YouTube - Spoof app version:** add version 18.20.39 ([#3001](https://github.com/ReVanced/revanced-patches/issues/3001)) ([f14c5e7](https://github.com/ReVanced/revanced-patches/commit/f14c5e79792f62fb060dd0eebbd3dd7157a08a98))
+
+# [2.191.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.5...v2.191.0-dev.6) (2023-09-20)
+
+
+### Features
+
+* **Tumblr:** Add `Disable Tumblr Live` patch ([#2987](https://github.com/ReVanced/revanced-patches/issues/2987)) ([bf1f9dc](https://github.com/ReVanced/revanced-patches/commit/bf1f9dc799705679d17973e689165ab1bff327cd))
+
+# [2.191.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.5...v2.191.0-dev.6) (2023-09-20)
+
+# [2.191.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.4...v2.191.0-dev.5) (2023-09-19)
+
+
+### Bug Fixes
+
+* **YouTube:** Restore functionality of `Old video quality menu` and `Custom speeds` on tablets ([#2999](https://github.com/ReVanced/revanced-patches/issues/2999)) ([238bed1](https://github.com/ReVanced/revanced-patches/commit/238bed12519ec61a53b1ee72da467830ef252154))
+
+# [2.191.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.3...v2.191.0-dev.4) (2023-09-14)
+
+
+### Features
+
+* **Twitch - Block embedded ads:** Switch from `ttv.lol` to `luminous.dev` ([0fe115e](https://github.com/ReVanced/revanced-patches/commit/0fe115e8f98ccdc86d318090fc92fe77cece1dd8))
+
+# [2.191.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.2...v2.191.0-dev.3) (2023-09-14)
+
+
+### Features
+
+* **TU Dortmund:** Add `Show on lockscreen` patch ([#2947](https://github.com/ReVanced/revanced-patches/issues/2947)) ([9a18326](https://github.com/ReVanced/revanced-patches/commit/9a18326aeb68d7518594d0eab326ca845b9bdbdd))
+* **Tumblr:** Add `Disable blog notification reminder` patch ([29f19b9](https://github.com/ReVanced/revanced-patches/commit/29f19b9378c7e167137f38fa4517ae19382ca4f6))
+* **Tumblr:** Add `Disable gift message popup` patch ([a4d6b4e](https://github.com/ReVanced/revanced-patches/commit/a4d6b4e5ce6065d932f3895b4996e7dc1e5f7c67))
+
+# [2.191.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.1...v2.191.0-dev.2) (2023-09-11)
+
+
+### Bug Fixes
+
+* Use consistent toggle description ([#2983](https://github.com/ReVanced/revanced-patches/issues/2983)) ([ceaa512](https://github.com/ReVanced/revanced-patches/commit/ceaa512f317fdd95dca37e425b389494a9b2e226))
+
+# [2.191.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.190.1-dev.4...v2.191.0-dev.1) (2023-09-11)
+
+
+### Features
+
+* **Tumblr:** Add `Disable dashboard ads` patch ([#2979](https://github.com/ReVanced/revanced-patches/issues/2979)) ([07c267a](https://github.com/ReVanced/revanced-patches/commit/07c267ad20afa1415d2dba31f0830d2dd5a34654))
+
+## [2.190.1-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.190.1-dev.3...v2.190.1-dev.4) (2023-09-07)
+
+
+### Bug Fixes
+
+* **YouTube - Custom filter:** Use new lines between components instead of commas ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([ecb2e32](https://github.com/ReVanced/revanced-patches/commit/ecb2e32b1e296590d150bdd3f8bea2665b19a84d))
+
+## [2.190.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.190.1-dev.2...v2.190.1-dev.3) (2023-09-07)
+
+
+### Bug Fixes
+
+* **Infinity for Reddit - Spoof client:** Constrain patch to last working versions ([#2944](https://github.com/ReVanced/revanced-patches/issues/2944)) ([ee975de](https://github.com/ReVanced/revanced-patches/commit/ee975dea846c77af0efe608e647075f4055af320))
+
+## [2.190.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.190.1-dev.1...v2.190.1-dev.2) (2023-09-07)
+
+
+### Bug Fixes
+
+* **YouTube - Hide layout components:** Always hide redundant 'player audio track' button ([#2951](https://github.com/ReVanced/revanced-patches/issues/2951)) ([ca632bd](https://github.com/ReVanced/revanced-patches/commit/ca632bd2cc74f0ce5ccb948e902445de3ab893cf))
+
+## [2.190.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.190.0...v2.190.1-dev.1) (2023-09-03)
+
+
+### Bug Fixes
+
+* **Twitch - Audio ads:** Support missing version `16.1.0` ([#2928](https://github.com/ReVanced/revanced-patches/issues/2928)) ([688d8fa](https://github.com/ReVanced/revanced-patches/commit/688d8fa7e86862e03d8336af5f6cb207c4b72593))
+
# [2.190.0](https://github.com/ReVanced/revanced-patches/compare/v2.189.0...v2.190.0) (2023-09-03)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..ae02f2a8f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Continuing the legacy of Vanced
+
+
+# 📙 ReVanced Patches contribution guidelines
+
+This document describes how to contribute to ReVanced Patches.
+
+## 📖 Resources to help you get started
+
+* The [documentation](https://github.com/ReVanced/revanced-patches/tree/docs/docs) provides the fundamentals of patches
+and everything necessary to create your own patch from scratch
+* [Our backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on
+* [Issues](https://github.com/ReVanced/revanced-patches/issues) are where we keep track of bugs and feature requests
+
+## 🙏 Submitting a feature request
+
+Features can be requested by opening an issue using the
+[Feature request issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Feature+request&projects=&template=feature-request.yml&title=feat%3A+).
+
+> **Note**
+> Requests can be accepted or rejected at the discretion of maintainers of ReVanced Patches.
+> Good motivation has to be provided for a request to be accepted.
+
+## 🐞 Submitting a bug report
+
+If you encounter a bug while using ReVanced Patches, open an issue using the
+[Bug report issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Bug+report&projects=&template=bug-report.yml&title=bug%3A+).
+
+## 🧑⚖️ Guidelines for requesting or contributing patches
+
+To maintain a high-quality and ethical collection of patches, the following guidelines for requesting
+or contributing patches are effective as of September 14, 2023. Any patches present prior to this date
+are unaffected by this change.
+
+> **Note**
+> We generally adhere to the guidelines outlined below. However, we may make exceptions
+> in specific cases based on our discretion. Pull requests for patches that deviate from the guidelines
+> will be evaluated individually. While a patch may not align with our general guidelines,
+> we will consider its acceptance on a case-by-case basis, taking into account its impact on user experience
+> and ethical considerations. We reserve the right to make exceptions for patches that provide significant value.
+
+✅ Examples for acceptable patches include:
+
+* Customizations: Feel free to contribute patches that allow users to personalize their experience
+* Ad-Blocking: Patches aimed at enhancing user privacy and blocking intrusive advertisements are appreciated
+* Feature additions: Patches that add new features or change behaviour to the app are welcome
+
+❌ Examples for unacceptable patches include:
+
+* Payment circumvention: We do not accept patches that exist solely to bypass payment for the app or any of its features
+* Malicious patches: Patches that are malicious in nature are not allowed
+
+
+## 📝 How to contribute
+
+1. Before contributing, it is recommended to open an issue to discuss your change
+with the maintainers of ReVanced Patches. This will help you determine whether your change is acceptable
+and whether it is worth your time to implement it
+2. Development happens on the `dev` branch. Fork the repository and create your branch from `dev`
+3. Commit your changes. In case you are contributing a new patch, make sure to follow the conventions for patches
+described in the [documentation](https://github.com/ReVanced/revanced-patches/tree/docs/docs)
+4. Submit a pull request to the `dev` branch of the repository and reference issues
+that your pull request closes in the description of your pull request
+5. Our team will review your pull request and provide feedback. Once your pull request is approved,
+it will be merged into the `dev` branch and will be included in the next release of ReVanced Patches
+
+❤️ Thank you for considering contributing to ReVanced Patches,
+ReVanced
diff --git a/README.md b/README.md
index 79fde2b82..6336b2c21 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,91 @@
-## 🧩 ReVanced Patches
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Continuing the legacy of Vanced
+
-Patches for ReVanced.
+
+# 🧩 ReVanced Patches
+
+
+
+
+This repository contains a collection of ReVanced Patches.
+
+## ❓ About
+
+Patches are small modifications to Android apps that allow you to change the behaviour of or add new features,
+block ads, customize the appearance, and much more.
+
+## 💪 Features
+
+Some of the features the patches provide are:
+
+* 🚫 **Block ads**: Say goodbye to ads
+* ⭐ **Customize your app**: Personalize the appearance of apps with various layouts and themes
+* 🪄 **Add new features**: Extend the functionality of apps with lots of new features
+* ⚙️ **Miscellaneous and general purpose**: Rename packages, enable debugging, disable screen capture restrictions,
+export activities, etc.
+* ✨ **And much more!**
+
+For a full list of all available patches, visit [revanced.app/patches](https://revanced.app/patches).
+
+## 🚀 How to get started
+
+You can use [ReVanced CLI](https://github.com/ReVanced/revanced-cli) or [ReVanced Manager](https://github.com/ReVanced/revanced-manager) to use ReVanced Patches.
+
+## 📚 Everything else
+
+### 📙 Contributing
+
+Thank you for considering contributing to ReVanced Patches. You can find the contribution guidelines [here](CONTRIBUTING.md).
+
+### 📃 Documentation
+
+The documentation provides the fundamentals of patches and everything necessary to create your own patch from scratch.
+You can find it [here](https://github.com/ReVanced/revanced-patches/tree/docs/docs).
+
+### 🛠️ Building
+
+In order to build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
+
+## 📜 Licence
+
+ReVanced Patches is licensed under the GPLv3 licence. Please see the [licence file](LICENSE) for more information.
+[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced patches as long as you track changes/dates in source files.
+Any modifications to ReVanced Patches must also be made available under the GPL along with build & install instructions.
diff --git a/assets/revanced-headline/revanced-headline-vertical-dark.svg b/assets/revanced-headline/revanced-headline-vertical-dark.svg
new file mode 100644
index 000000000..a59bfb50b
--- /dev/null
+++ b/assets/revanced-headline/revanced-headline-vertical-dark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/revanced-headline/revanced-headline-vertical-light.svg b/assets/revanced-headline/revanced-headline-vertical-light.svg
new file mode 100644
index 000000000..3c5eeccc7
--- /dev/null
+++ b/assets/revanced-headline/revanced-headline-vertical-light.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/revanced-logo/revanced-logo-round.svg b/assets/revanced-logo/revanced-logo-round.svg
new file mode 100644
index 000000000..901e1914b
--- /dev/null
+++ b/assets/revanced-logo/revanced-logo-round.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index dc49306d7..ef4cbf566 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,6 @@
plugins {
kotlin("jvm") version "1.8.20"
+ alias(libs.plugins.ksp)
}
group = "app.revanced"
@@ -25,16 +26,17 @@ repositories {
}
dependencies {
- implementation("app.revanced:revanced-patcher:14.2.1")
- implementation("com.android.tools.smali:smali:3.0.3")
- // Required because build fails without it.
- // TODO: Find a way to remove this dependency.
- implementation("com.google.guava:guava:32.1.2-jre")
+ implementation(libs.revanced.patcher)
+ implementation(libs.smali)
+ implementation(libs.revanced.patch.annotation.processor)
+ // TODO: Required because build fails without it. Find a way to remove this dependency.
+ implementation(libs.guava)
// Used in JsonGenerator.
- implementation("com.google.code.gson:gson:2.10.1")
- // A dependency to the Android library unfortunately fails the build,
- // which is why this is required for the patch change-oauth-client-id.
+ implementation(libs.gson)
+ // A dependency to the Android library unfortunately fails the build, which is why this is required.
compileOnly(project("dummy"))
+
+ ksp(libs.revanced.patch.annotation.processor)
}
kotlin {
@@ -50,7 +52,7 @@ tasks {
val androidHome = System.getenv("ANDROID_HOME") ?: throw GradleException("ANDROID_HOME not found")
val d8 = "${androidHome}/build-tools/33.0.1/d8"
val input = configurations.archives.get().allArtifacts.files.files.first().absolutePath
- val work = File("${buildDir}/libs")
+ val work = layout.buildDirectory.dir("libs").get().asFile
exec {
workingDir = work
@@ -63,6 +65,7 @@ tasks {
}
}
}
+
register("generateMeta") {
description = "Generate metadata for this bundle"
dependsOn(build)
@@ -70,6 +73,7 @@ tasks {
classpath = sourceSets["main"].runtimeClasspath
mainClass.set("app.revanced.meta.PatchesFileGenerator")
}
+
// Dummy task to fix the Gradle semantic-release plugin.
// Remove this if you forked it to support building only.
// Tracking issue: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
diff --git a/gradle.properties b/gradle.properties
index c836a2ec8..542cff4ec 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
-version = 2.190.0
+version = 2.191.0-dev.33
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 000000000..87ecc96b9
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,17 @@
+[versions]
+revanced-patcher = "16.0.0"
+revanced-patch-annotation-processor = "16.0.0"
+ksp = "1.9.0-1.0.11"
+smali = "3.0.3"
+guava = "32.1.2-jre"
+gson = "2.10.1"
+
+[libraries]
+revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
+revanced-patch-annotation-processor = { module = "app.revanced:revanced-patch-annotation-processor", version.ref = "revanced-patch-annotation-processor" }
+smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }
+guava = { module = "com.google.guava:guava", version.ref = "guava" }
+gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
+
+[plugins]
+ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
diff --git a/patches.json b/patches.json
index 59d9a07a9..de8b00dbe 100644
--- a/patches.json
+++ b/patches.json
@@ -1 +1 @@
-[{"name":"Alternative thumbnails","description":"Adds options to replace video thumbnails with still image captures of the video.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Always autorepeat","description":"Always repeats the playing video again.","excluded":false,"options":[],"dependencies":["Integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Auto claim channel points","description":"Automatically claim Channel Points.","excluded":false,"options":[],"dependencies":["Settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}]},{"name":"Background play","description":"Enables playing music in the background.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Block audio ads","description":"Blocks audio ads in streams and VODs.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1"]}]},{"name":"Block embedded ads","description":"Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker.","excluded":false,"options":[],"dependencies":["Block video ads","Integrations","Settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}]},{"name":"Block video ads","description":"Blocks video ads in streams and VODs.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}]},{"name":"Bypass certificate checks","description":"Bypasses certificate checks which prevent YouTube Music from working on Android Auto.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Change package name","description":"Changes the package name. Appends \".revanced\" to the package name by default.","excluded":true,"options":[{"key":"packageName","title":"Package name","description":"The name of the package to rename the app to.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"Client spoof","description":"Spoofs the client to allow playback.","excluded":false,"options":[],"dependencies":["Spoof signature verification"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Codecs unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Comments","description":"Hides components related to comments.","excluded":false,"options":[],"dependencies":["Settings","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Compact header","description":"Hides the music category bar at the top of the homepage.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Copy video url","description":"Adds buttons in player to copy video links.","excluded":false,"options":[],"dependencies":["CopyVideoUrlResourcePatch","Player controls bytecode patch","Video information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Custom branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","excluded":true,"options":[{"key":"appName","title":"Application Name","description":"The name of the application it will show on your home screen.","required":true,"choices":null},{"key":"iconPath","title":"App Icon Path","description":"A path containing mipmap resource folders with icons.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Custom player overlay opacity","description":"Change the opacity of the player background, when player controls are visible.","excluded":false,"options":[],"dependencies":["CustomPlayerOverlayOpacityResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Debug mode","description":"Enables Twitch\u0027s internal debugging mode.","excluded":true,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"Disable Shorts on startup","description":"Disables playing YouTube Shorts when launching YouTube.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Disable Sync for Lemmy bottom sheet","description":"Disables the bottom sheet at the startup that asks you to signup to \"Sync for Lemmy\".","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":["v23.06.30-13:39"]},{"name":"com.laurencedawson.reddit_sync.pro","versions":[]},{"name":"com.laurencedawson.reddit_sync.dev","versions":[]}]},{"name":"Disable ads","description":"Disables ads in HexEditor.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.myprog.hexedit","versions":[]}]},{"name":"Disable ads","description":"This patch has no description.","excluded":false,"options":[],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]}]},{"name":"Disable ads","description":"This patch has no description.","excluded":false,"options":[],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"o.o.joey","versions":[]}]},{"name":"Disable auto captions","description":"Disable forced captions from being automatically enabled.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Disable login requirement","description":"Do not force login.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Disable mandatory login","description":"This patch has no description.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.adobe.lrmobile","versions":[]}]},{"name":"Disable player popup panels","description":"Disables panels from appearing automatically when going into fullscreen (playlist or live chat).","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Disable screenshot popup","description":"Disables the popup that shows up when taking a screenshot.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"Disable switching emoji to sticker in message input field","description":"Disables switching from emoji to sticker search mode in message input field","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"Disable typing indicator","description":"Disables the indicator while typing a message","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"Disable zoom haptics","description":"Disables haptics when zooming.","excluded":false,"options":[],"dependencies":["Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Downloads","description":"Removes download restrictions and changes the default path to download to.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Dynamic color","description":"Replaces the default Twitter Blue with the users Material You palette.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"Enable android debugging","description":"Enables Android debugging capabilities. This can slow down the app.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"Enable debugging","description":"Adds debugging options.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Enable on demand","description":"Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.lite","versions":[]}]},{"name":"Enable tablet layout","description":"Spoofs the device form factor to a tablet which enables the tablet layout.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Exclusive audio playback","description":"Enables the option to play audio without video.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Export all activities","description":"Makes all app activities exportable.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"External downloads","description":"Adds support to download and save YouTube videos using an external app.","excluded":false,"options":[],"dependencies":["ExternalDownloadsResourcePatch","Player controls bytecode patch","Video information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Feed filter","description":"Filters tiktok videos: removing ads, removing livestreams.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Fix google login","description":"Allows logging in with a Google account.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"HDR auto brightness","description":"Makes the brightness of HDR videos follow the system default.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide Shorts components","description":"Hides components from YouTube Shorts.","excluded":false,"options":[],"dependencies":["Integrations","LithoFilterPatch","HideShortsComponentsResourcePatch","ResourceMappingPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide ads","description":"Removes general ads.","excluded":false,"options":[],"dependencies":["Hide get premium","HideAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide ads","description":"Removes ads from the Reddit.","excluded":false,"options":[],"dependencies":["Hide subreddit banner","Hide comment ads"],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"Hide ads","description":"Hides ads.","excluded":false,"options":[],"dependencies":["Json hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"Hide ads","description":"Removes general ads.","excluded":false,"options":[],"dependencies":["VerticalScrollPatch"],"compatiblePackages":[{"name":"com.vanced.android.youtube","versions":[]}]},{"name":"Hide ads","description":"Removes ads from TikTok.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Hide ads","description":"Removes ads from Inshorts.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.nis.app","versions":[]}]},{"name":"Hide ads","description":"Hides ads.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"jp.pxv.android","versions":[]}]},{"name":"Hide album cards","description":"Hides the album cards below the artist description.","excluded":false,"options":[],"dependencies":["Integrations","AlbumCardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide autoplay button","description":"Hides the autoplay button in the video player.","excluded":false,"options":[],"dependencies":["Integrations","Settings","ResourceMappingPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide breaking news shelf","description":"Hides the breaking news shelf on the homepage tab.","excluded":false,"options":[],"dependencies":["Integrations","BreakingNewsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide captions button","description":"Hides the captions button on video player.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide cast button","description":"Hides the cast button in the video player.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Hide crowdfunding box","description":"Hides the crowdfunding box between the player and video description.","excluded":false,"options":[],"dependencies":["Integrations","CrowdfundingBoxResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide email address","description":"Hides the email address in the account switcher.","excluded":false,"options":[],"dependencies":["Integrations","HideEmailAddressResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide endscreen cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","excluded":false,"options":[],"dependencies":["Integrations","HideEndscreenCardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide filter bar","description":"Hides the filter bar in video feeds.","excluded":false,"options":[],"dependencies":["HideFilterBarResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide floating microphone button","description":"Hides the floating microphone button which appears in search.","excluded":false,"options":[],"dependencies":["HideFloatingMicrophoneButtonResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide get premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Hide inbox ads","description":"Hides ads in inbox.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"Hide info cards","description":"Hides info cards in videos.","excluded":false,"options":[],"dependencies":["Integrations","HideInfocardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide layout components","description":"Hides general layout components.","excluded":false,"options":[],"dependencies":["LithoFilterPatch","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.32.39"]}]},{"name":"Hide load more button","description":"Hides the button under videos that loads similar videos.","excluded":false,"options":[],"dependencies":["HideLoadMoreButtonResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide player buttons","description":"Adds the option to hide video player previous and next buttons.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide premium navbar","description":"Removes the premium tab from the navbar.","excluded":false,"options":[],"dependencies":["ResourceMappingPatch"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"Hide recommended users","description":"Hides recommended users.","excluded":false,"options":[],"dependencies":["Json hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"Hide seekbar","description":"Hides the seekbar.","excluded":false,"options":[],"dependencies":["Integrations","Settings","SeekbarColorBytecodePatch","SeekbarPreferencesPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide timeline ads","description":"Removes ads from the timeline.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":["275.0.0.27.98"]}]},{"name":"Hide timestamp","description":"Hides timestamp in video player.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide video action buttons","description":"Adds the options to hide action buttons under a video.","excluded":false,"options":[],"dependencies":["ResourceMappingPatch","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Hide watermark","description":"Hides creator\u0027s watermarks on videos.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Minimized playback","description":"Enables minimized and background playback.","excluded":false,"options":[],"dependencies":["Integrations","Player type hook","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Minimized playback music","description":"Enables minimized playback on Kids music.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Music video ads","description":"Removes ads in the music player.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Navigation buttons","description":"Adds options to hide or change navigation buttons.","excluded":false,"options":[],"dependencies":["Integrations","Settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Old video quality menu","description":"Shows the old video quality with the advanced video quality options instead of the new one.","excluded":false,"options":[],"dependencies":["Integrations","OldVideoQualityMenuResourcePatch","LithoFilterPatch","BottomSheetHookPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Open links externally","description":"Open links outside of the app directly in your browser.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Override certificate pinning","description":"Overrides certificate pinning, allowing to inspect traffic via a proxy.","excluded":true,"options":[],"dependencies":["Enable android debugging"],"compatiblePackages":[]},{"name":"Permanent repeat","description":"Permanently remember your repeating preference even if the playlist ends or another track is played.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Permanent shuffle","description":"Permanently remember your shuffle preference even if the playlist ends or another track is played.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Playback speed","description":"Adds custom playback speeds and ability to remember the playback speed you chose in the video playback speed flyout.","excluded":false,"options":[],"dependencies":["Custom playback speed","Remember playback speed"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Playback speed","description":"Enables the playback speed option for all videos.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Player flyout menu","description":"Hides player flyout menu items.","excluded":false,"options":[],"dependencies":["LithoFilterPatch","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Predictive back gesture","description":"Enables the predictive back gesture introduced on Android 13.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"Premium heading","description":"Shows premium branding on the home screen.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Premium icon reddit","description":"Unlocks premium Reddit app icons.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"Pro unlock","description":"Unlocks pro-only functions.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.backdrops.wallpapers","versions":["4.52"]}]},{"name":"Promo code unlock","description":"Disables the validation of promo code. Any code will work to unlock all features.","excluded":false,"options":[],"dependencies":["Spoof cert patch"],"compatiblePackages":[{"name":"de.dwd.warnapp","versions":[]}]},{"name":"Remember video quality","description":"Adds the ability to remember the video quality you chose in the video quality flyout.","excluded":false,"options":[],"dependencies":["Integrations","Video information","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Remove ads","description":"Removes all ads from the app.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.binarymode.android.irplus","versions":[]}]},{"name":"Remove badge tab","description":"Removes the badge tab from the activity tab.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.sony.songpal.mdr","versions":[]}]},{"name":"Remove bootloader detection","description":"Removes the check for an unlocked bootloader.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":[]}]},{"name":"Remove broadcasts restriction","description":"Enables starting/stopping NetGuard via broadcasts.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"eu.faircode.netguard","versions":[]}]},{"name":"Remove debugging detection","description":"Removes the USB and wireless debugging checks.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.scb.phone","versions":[]}]},{"name":"Remove device restrictions","description":"Removes restrictions from using the app on any device.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.recorder","versions":[]}]},{"name":"Remove file size limit","description":"Allows opening files larger than 2 MB in the text editor.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"pl.solidexplorer2","versions":[]}]},{"name":"Remove notification badge","description":"Removes the red notification badge from the activity tab.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.sony.songpal.mdr","versions":[]}]},{"name":"Remove player controls background","description":"Removes the background from the video player controls.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Remove root detection","description":"Removes the check for root permissions and unlocked bootloader.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"Remove root detection","description":"Removes the check for root permissions.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":[]}]},{"name":"Remove screen capture restriction","description":"Removes the restriction of capturing audio from apps that normally wouldn\u0027t allow it.","excluded":true,"options":[],"dependencies":["RemoveCaptureRestrictionResourcePatch"],"compatiblePackages":[]},{"name":"Remove screenshot restriction","description":"Removes the restriction of taking screenshots in apps that normally wouldn\u0027t allow it.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"Remove upgrade button","description":"Removes the upgrade tab from the pivot bar.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Return YouTube Dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","excluded":false,"options":[],"dependencies":["Integrations","Video id hook","ReturnYouTubeDislikeResourcePatch","Player type hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.32.39"]}]},{"name":"Sanitize sharing links","description":"Removes (tracking) query parameters from the URLs when sharing links.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"Seekbar tapping","description":"Enables tap-to-seek on the seekbar of the video player.","excluded":false,"options":[],"dependencies":["Integrations","EnableSeekbarTappingResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Settings","description":"Adds settings menu to Twitch.","excluded":false,"options":[],"dependencies":["Integrations","SettingsResourcePatch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"Settings","description":"Adds ReVanced settings to TikTok.","excluded":false,"options":[],"dependencies":["Integrations"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Show deleted messages","description":"Shows deleted chat messages behind a clickable spoiler.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}]},{"name":"Show seekbar","description":"Shows progress bar for all video.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"Sim spoof","description":"Spoofs the information which is retrieved from the sim-card.","excluded":true,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"SponsorBlock","description":"Integrates SponsorBlock which allows skipping video segments such as sponsored content.","excluded":false,"options":[],"dependencies":["Integrations","Video id hook","Video information","Player type hook","Player controls bytecode patch","SponsorBlockResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Spoof app version","description":"Tricks YouTube into thinking you are running an older version of the app. One of the side effects also includes restoring the old UI.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"http://baconreader.com/auth\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.onelouder.baconreader","versions":[]},{"name":"com.onelouder.baconreader.premium","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"dbrady://relay\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"free.reddit.news","versions":[]},{"name":"reddit.news","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"redditisfun://auth\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.andrewshu.android.reddit","versions":[]},{"name":"com.andrewshu.android.redditdonation","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"infinity://localhost\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"ml.docilealligator.infinityforreddit","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"http://rubenmayayo.com\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.rubenmayayo.reddit","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"http://redditsync/auth\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]},{"name":"com.laurencedawson.reddit_sync.pro","versions":[]},{"name":"com.laurencedawson.reddit_sync.dev","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"https://127.0.0.1:65023/authorize_callback\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"o.o.joey","versions":[]},{"name":"o.o.joey.pro","versions":[]},{"name":"o.o.joey.dev","versions":[]}]},{"name":"Spoof client","description":"Spoofs the client in order to allow logging in. The OAuth application type has to be \"Installed app\" and the redirect URI has to be set to \"http://www.ccrama.me\".","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"me.ccrama.redditslide","versions":[]}]},{"name":"Spoof device ID","description":"Spoofs device ID to mitigate manual bans by developers.","excluded":false,"options":[],"dependencies":["SignatureDetectionPatch"],"compatiblePackages":[{"name":"com.microblink.photomath","versions":[]}]},{"name":"Spoof signature","description":"Spoofs the signature of the app.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"Spoof wifi connection","description":"Spoofs an existing Wi-Fi connection.","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"Spotify theme","description":"Applies a custom theme.","excluded":false,"options":[{"key":"backgroundColor","title":"Background color","description":"The background color. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentColor","title":"Accent color","description":"The accent color (\u0027spotify green\u0027 by default). Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentPressedColor","title":"Pressed accent for the dark theme","description":"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"Swipe controls","description":"Adds volume and brightness swipe controls.","excluded":false,"options":[],"dependencies":["Integrations","Player type hook","SwipeControlsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Tablet mini player","description":"Enables the tablet mini player layout.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Theme","description":"Applies a custom theme.","excluded":false,"options":[{"key":"darkThemeBackgroundColor","title":"Background color for the dark theme","description":"The background color of the dark theme. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"lightThemeBackgroundColor","title":"Background color for the light theme","description":"The background color of the light theme. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":["Litho color hook","SeekbarColorBytecodePatch","ThemeResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"Unlock Duolingo Super","description":"Unlocks Duolingo Super features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.duolingo","versions":[]}]},{"name":"Unlock paid widgets","description":"Unlocks paid widgets of the app","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.dci.dev.androidtwelvewidgets","versions":[]}]},{"name":"Unlock plus","description":"This patch has no description.","excluded":false,"options":[],"dependencies":["SignatureDetectionPatch","EnableBookpointPatch"],"compatiblePackages":[{"name":"com.microblink.photomath","versions":[]}]},{"name":"Unlock premium","description":"Unlocks premium features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.adobe.lrmobile","versions":[]}]},{"name":"Unlock premium","description":"Unlocks premium features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"io.yuka.android","versions":[]}]},{"name":"Unlock pro","description":"Unlocks premium features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.candylink.openvpn","versions":[]}]},{"name":"Unlock pro","description":"Unlocks all pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.wakdev.apps.nfctools.se","versions":[]}]},{"name":"Unlock pro","description":"Unlocks pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"Unlock pro","description":"Unlocks all pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"Unlock pro","description":"Unlocks pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.vsco.cam","versions":[]}]},{"name":"Unlock pro","description":"Unlocks pro features.","excluded":false,"options":[],"dependencies":["SignatureVerificationPatch","LicenseValidationPatch"],"compatiblePackages":[{"name":"com.zombodroid.MemeGenerator","versions":["4.6364","4.6370","4.6375","4.6377"]}]},{"name":"Unlock pro","description":"Unlocks all professional features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":["3.4.9"]}]},{"name":"Unlock pro","description":"Unlocks pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.trakt.trakt","versions":["1.1.1"]}]},{"name":"Unlock pro","description":"Unlocks all pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"Unlock pro","description":"Unlocks all pro features.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"Unlock subscription features","description":"Unlocks \"Matched Runs\" and \"Segment Efforts\".","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.strava","versions":["320.12"]}]},{"name":"Unlock themes","description":"Unlocks all themes that are inaccessible until a certain level is reached.","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ticktick.task","versions":[]}]},{"name":"Vanced MicroG support","description":"Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.","excluded":false,"options":[],"dependencies":["MicroGResourcePatch","Hide cast button","Client spoof"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Vanced MicroG support","description":"Allows YouTube Music ReVanced to run without root and under a different package name.","excluded":false,"options":[],"dependencies":["MicroGResourcePatch"],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"Video ads","description":"Removes ads in the video player.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]},{"name":"Wide searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","excluded":false,"options":[],"dependencies":["Integrations","Settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39"]}]}]
\ No newline at end of file
+[{"name":"Unlock premium","description":null,"compatiblePackages":[{"name":"com.adobe.lrmobile","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable mandatory login","description":null,"compatiblePackages":[{"name":"com.adobe.lrmobile","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Removes general ads.","compatiblePackages":[{"name":"com.vanced.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable typing indicator","description":"Disables the indicator while typing a message.","compatiblePackages":[{"name":"com.facebook.orca","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable switching emoji to sticker","description":"Disables switching from emoji to sticker search mode in message input field.","compatiblePackages":[{"name":"com.facebook.orca","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide inbox ads","description":"Hides ads in inbox.","compatiblePackages":[{"name":"com.facebook.orca","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove file size limit","description":"Allows opening files larger than 2 MB in the text editor.","compatiblePackages":[{"name":"pl.solidexplorer2","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock themes","description":"Unlocks all themes that are inaccessible until a certain level is reached.","compatiblePackages":[{"name":"com.ticktick.task","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide premium navbar","description":"Removes the premium tab from the navbar.","compatiblePackages":[{"name":"com.spotify.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable on demand","description":"Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.","compatiblePackages":[{"name":"com.spotify.lite","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Custom theme","description":"Applies a custom theme.","compatiblePackages":[{"name":"com.spotify.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"backgroundColor","default":"@android:color/black","title":"Background color","description":"The background color. Can be a hex color or a resource reference.","required":false},{"key":"accentColor","default":"#ff1ed760","title":"Accent color","description":"The accent color (\u0027spotify green\u0027 by default). Can be a hex color or a resource reference.","required":false},{"key":"accentPressedColor","default":"#ff169c46","title":"Pressed accent for the dark theme","description":"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.","required":false}]},{"name":"Unlock premium","description":null,"compatiblePackages":[{"name":"io.yuka.android","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"com.candylink.openvpn","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Exclusive audio playback","description":"Enables the option to play audio without video.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Codecs unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Permanent repeat","description":"Permanently remember your repeating preference even if the playlist ends or another track is played.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Permanent shuffle","description":"Permanently remember your shuffle preference even if the playlist ends or another track is played.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Music video ads","description":"Removes ads in the music player.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Background play","description":"Enables playing music in the background.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Vanced MicroG support","description":"Allows YouTube Music to run without root and under a different package name.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bypass certificate checks","description":"Bypasses certificate checks which prevent YouTube Music from working on Android Auto.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide get premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Minimized playback music","description":"Enables minimized playback on Kids music.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Compact header","description":"Hides the music category bar at the top of the homepage.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Remove upgrade button","description":"Removes the upgrade tab from the pivot bar.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove root detection","description":"Removes the check for root permissions.","compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove bootloader detection","description":"Removes the check for an unlocked bootloader.","compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Pro unlock","description":null,"compatiblePackages":[{"name":"com.backdrops.wallpapers","versions":["4.52"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof device ID","description":"Spoofs device ID to mitigate manual bans by developers.","compatiblePackages":[{"name":"com.microblink.photomath","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock plus","description":null,"compatiblePackages":[{"name":"com.microblink.photomath","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable ads","description":null,"compatiblePackages":[{"name":"com.myprog.hexedit","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Auto claim channel points","description":"Automatically claim Channel Points.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Show deleted messages","description":"Shows deleted chat messages behind a clickable spoiler.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Debug mode","description":"Enables Twitch\u0027s internal debugging mode.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Block audio ads","description":"Blocks audio ads in streams and VODs.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Block video ads","description":"Blocks video ads in streams and VODs.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Block embedded ads","description":"Blocks embedded stream ads using services like Luminous or PurpleAdBlocker.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1","16.1.0"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Settings","description":"Adds settings menu to Twitch.","compatiblePackages":[{"name":"tv.twitch.android.app","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Promo code unlock","description":"Disables the validation of promo code. Any code will work to unlock all features.","compatiblePackages":[{"name":"de.dwd.warnapp","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Feed filter","description":"Filters tiktok videos: removing ads, removing livestreams.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Downloads","description":"Removes download restrictions and changes the default path to download to.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Playback speed","description":"Enables the playback speed option for all videos.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Show seekbar","description":"Shows progress bar for all video.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":null,"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["30.8.4"]},{"name":"com.zhiliaoapp.musically","versions":["30.8.4"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"SIM spoof","description":"Spoofs the information which is retrieved from the SIM card.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Disable login requirement","description":null,"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Fix Google login","description":"Allows logging in with a Google account.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Settings","description":"Adds ReVanced settings to TikTok.","compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":null},{"name":"com.zhiliaoapp.musically","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock paid widgets","description":"Unlocks paid widgets of the app","compatiblePackages":[{"name":"com.dci.dev.androidtwelvewidgets","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable subscription suggestions","description":null,"compatiblePackages":[{"name":"com.strava","versions":["320.12"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock subscription features","description":"Unlocks \"Routes\", \"Matched Runs\" and \"Segment Efforts\".","compatiblePackages":[{"name":"com.strava","versions":["320.12"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable dashboard ads","description":"Disables ads in the dashboard.","compatiblePackages":[{"name":"com.tumblr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable gift message popup","description":"Disables the popup suggesting to buy TumblrMart items for other people.","compatiblePackages":[{"name":"com.tumblr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable in-app update","description":"Disables the in-app update check and update prompt.","compatiblePackages":[{"name":"com.tumblr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable blog notification reminder","description":"Disables the reminder to enable notifications for blogs you visit.","compatiblePackages":[{"name":"com.tumblr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable Tumblr Live","description":"Disable the Tumblr Live tab button and dashboard carousel.","compatiblePackages":[{"name":"com.tumblr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove root detection","description":"Removes the check for root permissions and unlocked bootloader.","compatiblePackages":[{"name":"at.gv.bka.serviceportal","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove badge tab","description":"Removes the badge tab from the activity tab.","compatiblePackages":[{"name":"com.sony.songpal.mdr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove notification badge","description":"Removes the red notification badge from the activity tab.","compatiblePackages":[{"name":"com.sony.songpal.mdr","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove device restrictions","description":"Removes restrictions from using the app on any device. Requires mounting patched app over original.","compatiblePackages":[{"name":"com.google.android.apps.recorder","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"com.awedea.nyx","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":"Unlocks pro features.","compatiblePackages":[{"name":"com.vsco.cam","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof signature","description":"Spoofs the signature of the app.","compatiblePackages":[{"name":"at.gv.oe.app","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove root detection","description":"Removes the check for root permissions and unlocked bootloader.","compatiblePackages":[{"name":"at.gv.oe.app","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":["3.4.9"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":"Unlocks all pro features.","compatiblePackages":[{"name":"co.windyapp.android","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"com.zombodroid.MemeGenerator","versions":["4.6364","4.6370","4.6375","4.6377"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":null,"compatiblePackages":[{"name":"jp.pxv.android","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Show on lockscreen","description":"Shows student id and student ticket on lockscreen.","compatiblePackages":[{"name":"de.tudortmund.app","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":true,"options":[]},{"name":"Remove debugging detection","description":"Removes the USB and wireless debugging checks.","compatiblePackages":[{"name":"com.scb.phone","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"External downloads","description":"Adds support to download and save YouTube videos using an external app.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Copy video url","description":"Adds buttons in player to copy video links.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Seekbar tapping","description":"Enables tap-to-seek on the seekbar of the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Swipe controls","description":"Adds volume and brightness swipe controls.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Removes general ads.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide get premium","description":null,"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Video ads","description":"Removes ads in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Old video quality menu","description":"Shows the old video quality with the advanced video quality options instead of the new one.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Playback speed","description":"Adds custom playback speeds and ability to remember the playback speed you chose in the video playback speed flyout.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"HDR auto brightness","description":"Makes the brightness of HDR videos follow the system default.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remember video quality","description":"Adds the ability to remember the video quality you chose in the video quality flyout.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Always autorepeat","description":"Always repeats the playing video again.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Vanced MicroG support","description":"Allows YouTube to run without root and under a different package name with Vanced MicroG.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Minimized playback","description":"Enables minimized and background playback.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable zoom haptics","description":"Disables haptics when zooming.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable debugging","description":"Adds debugging options.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bypass URL redirects","description":"Bypass URL redirects and open the original URL directly.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Open links externally","description":"Open links outside of the app directly in your browser.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Client spoof","description":"Spoofs the client to allow playback.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide filter bar","description":"Hides the filter bar in video feeds.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide timestamp","description":"Hides timestamp in video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide \"Load more\" button","description":"Hides the button under videos that loads similar videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide layout components","description":"Hides general layout components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide breaking news shelf","description":"Hides the breaking news shelf on the homepage tab.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide endscreen cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide floating microphone button","description":"Hides the floating microphone button which appears in search.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide watermark","description":"Hides creator\u0027s watermarks on videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Comments","description":"Hides components related to comments.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide album cards","description":"Hides the album cards below the artist description.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide email address","description":"Hides the email address in the account switcher.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide seekbar","description":"Hides the seekbar.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide Shorts components","description":"Hides components from YouTube Shorts.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide crowdfunding box","description":"Hides the crowdfunding box between the player and video description.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide info cards","description":"Hides info cards in videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Player flyout menu","description":"Hides player flyout menu items.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide captions button","description":"Hides the captions button on video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide autoplay button","description":"Hides the autoplay button in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Navigation buttons","description":"Adds options to hide or change navigation buttons.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide video action buttons","description":"Adds the options to hide action buttons under a video.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide cast button","description":"Hides the cast button in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide player buttons","description":"Adds the option to hide video player previous and next buttons.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto captions","description":"Disable forced captions from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Wide searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable tablet layout","description":"Spoofs the device form factor to a tablet which enables the tablet layout.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable Shorts on startup","description":"Disables playing YouTube Shorts when launching YouTube.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Theme","description":"Applies a custom theme.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"darkThemeBackgroundColor","default":"@android:color/black","title":"Background color for the dark theme","description":"The background color of the dark theme. Can be a hex color or a resource reference.","required":false},{"key":"lightThemeBackgroundColor","default":"@android:color/white","title":"Background color for the light theme","description":"The background color of the light theme. Can be a hex color or a resource reference.","required":false}]},{"name":"Disable player popup panels","description":"Disables panels from appearing automatically when going into fullscreen (playlist or live chat).","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"SponsorBlock","description":"Integrates SponsorBlock which allows skipping video segments such as sponsored content.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Custom branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[{"key":"appName","default":"YouTube ReVanced","title":"Application Name","description":"The name of the application it will show on your home screen.","required":true},{"key":"iconPath","default":null,"title":"App Icon Path","description":"A path containing mipmap resource folders with icons.","required":false}]},{"name":"Premium heading","description":"Show or hide the premium heading.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"usePremiumHeading","default":true,"title":"Use premium heading","description":"Whether to use the premium heading.","required":true}]},{"name":"Return YouTube Dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.32.39"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Tablet mini player","description":"Enables the tablet mini player layout.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof app version","description":"Tricks YouTube into thinking you are running an older version of the app. One of the side effects also includes restoring the old UI.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Alternative thumbnails","description":"Adds options to replace video thumbnails with still image captures of the video.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Custom player overlay opacity","description":"Change the opacity of the player background, when player controls are visible.","compatiblePackages":[{"name":"com.google.android.youtube","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove player controls background","description":"Removes the background from the video player controls.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35","18.20.39","18.23.35","18.29.38","18.32.39","18.37.36"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Export all activities","description":"Makes all app activities exportable.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Remove screen capture restriction","description":"Removes the restriction of capturing audio from apps that normally wouldn\u0027t allow it.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":true,"options":[]},{"name":"Remove screenshot restriction","description":"Removes the restriction of taking screenshots in apps that normally wouldn\u0027t allow it.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":true,"options":[]},{"name":"Spoof Wi-Fi connection","description":"Spoofs an existing Wi-Fi connection.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":true,"options":[]},{"name":"Predictive back gesture","description":"Enables the predictive back gesture introduced on Android 13.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Override certificate pinning","description":"Overrides certificate pinning, allowing to inspect traffic via a proxy.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Change package name","description":"Appends \".revanced\" to the package name by default.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[{"key":"packageName","default":null,"title":"Package name","description":"The name of the package to rename the app to.","required":false}]},{"name":"Enable Android debugging","description":"Enables Android debugging capabilities. This can slow down the app.","compatiblePackages":null,"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Disable ads","description":null,"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable Sync for Lemmy bottom sheet","description":"Disables the bottom sheet at the startup that asks you to signup to \"Sync for Lemmy\".","compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":["v23.06.30-13:39"]},{"name":"com.laurencedawson.reddit_sync.pro","versions":null},{"name":"com.laurencedawson.reddit_sync.dev","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":null},{"name":"com.laurencedawson.reddit_sync.pro","versions":null},{"name":"com.laurencedawson.reddit_sync.dev","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"http://redditsync/auth\".","required":true}]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"com.rubenmayayo.reddit","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"http://rubenmayayo.com\".","required":true}]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"ml.docilealligator.infinityforreddit","versions":["5.4.0","5.4.1","5.4.2","6.0.1","6.0.2","6.0.4","6.0.6","6.1.1"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"infinity://localhost\".","required":true}]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"com.onelouder.baconreader","versions":null},{"name":"com.onelouder.baconreader.premium","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"http://baconreader.com/auth\".","required":true}]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"me.ccrama.redditslide","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"http://www.ccrama.me\".","required":true}]},{"name":"Disable ads","description":null,"compatiblePackages":[{"name":"o.o.joey","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"o.o.joey","versions":null},{"name":"o.o.joey.pro","versions":null},{"name":"o.o.joey.dev","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"https://127.0.0.1:65023/authorize_callback\".","required":true}]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"free.reddit.news","versions":null},{"name":"reddit.news","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"dbrady://relay\".","required":true}]},{"name":"Spoof client","description":"Restores functionality of the app by using custom client ID\u0027s.","compatiblePackages":[{"name":"com.andrewshu.android.reddit","versions":null},{"name":"com.andrewshu.android.redditdonation","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[{"key":"client-id","default":null,"title":"OAuth client ID","description":"The Reddit OAuth client ID. You can get your client ID from https://www.reddit.com/prefs/apps. The application type has to be \"Installed app\" and the redirect URI has to be set to \"redditisfun://auth\".","required":true}]},{"name":"Hide ads","description":null,"compatiblePackages":[{"name":"com.reddit.frontpage","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":true,"options":[]},{"name":"Sanitize sharing links","description":"Removes (tracking) query parameters from the URLs when sharing links.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable screenshot popup","description":"Disables the popup that shows up when taking a screenshot.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock premium Reddit icons","description":null,"compatiblePackages":[{"name":"com.reddit.frontpage","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Hides ads.","compatiblePackages":[{"name":"com.twitter.android","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide recommended users","description":null,"compatiblePackages":[{"name":"com.twitter.android","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Dynamic color","description":"Replaces the default Twitter Blue with the user\u0027s Material You palette.","compatiblePackages":[{"name":"com.twitter.android","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove broadcasts restriction","description":"Enables starting/stopping NetGuard via broadcasts.","compatiblePackages":[{"name":"eu.faircode.netguard","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"tv.trakt.trakt","versions":["1.1.1"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove ads","description":null,"compatiblePackages":[{"name":"net.binarymode.android.irplus","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide timeline ads","description":"Removes ads from the timeline.","compatiblePackages":[{"name":"com.instagram.android","versions":["275.0.0.27.98"]}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":null,"compatiblePackages":[{"name":"com.nis.app","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Unlock pro","description":null,"compatiblePackages":[{"name":"com.wakdev.apps.nfctools.se","versions":null}],"dependencies":["kotlin.reflect.jvm.internal.KClassImpl"],"use":true,"requiresIntegrations":false,"options":[]}]
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/extensions/Extensions.kt b/src/main/kotlin/app/revanced/extensions/Extensions.kt
index 226f4b143..0a00f5dd2 100644
--- a/src/main/kotlin/app/revanced/extensions/Extensions.kt
+++ b/src/main/kotlin/app/revanced/extensions/Extensions.kt
@@ -2,12 +2,11 @@ package app.revanced.extensions
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
@@ -20,7 +19,7 @@ import org.w3c.dom.Node
* @return The [PatchException].
*/
val MethodFingerprint.exception
- get() = PatchException("Failed to resolve $name")
+ get() = PatchException("Failed to resolve ${this.javaClass.simpleName}")
/**
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
@@ -77,22 +76,21 @@ fun Method.findIndexForIdResource(resourceName: String): Int {
*
* @return the first constant instruction with the value, or -1 if not found.
*/
-fun Method.indexOfFirstConstantInstructionValue(constantValue: Long): Int {
- return implementation?.let {
- it.instructions.indexOfFirst { instruction ->
- instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == constantValue
- }
- } ?: -1
-}
+fun Method.indexOfFirstConstantInstructionValue(constantValue: Long) = implementation?.let {
+ it.instructions.indexOfFirst { instruction ->
+ instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == constantValue
+ }
+} ?: -1
+
/**
* Check if the method contains a constant with the given value.
*
* @return if the method contains a constant with the given value.
*/
-fun Method.containsConstantInstructionValue(constantValue: Long): Boolean {
- return indexOfFirstConstantInstructionValue(constantValue) >= 0
-}
+fun Method.containsConstantInstructionValue(constantValue: Long) =
+ indexOfFirstConstantInstructionValue(constantValue) >= 0
+
/**
* Traverse the class hierarchy starting from the given root class.
diff --git a/src/main/kotlin/app/revanced/meta/JsonGenerator.kt b/src/main/kotlin/app/revanced/meta/JsonGenerator.kt
index 3be7793f8..dea128a76 100644
--- a/src/main/kotlin/app/revanced/meta/JsonGenerator.kt
+++ b/src/main/kotlin/app/revanced/meta/JsonGenerator.kt
@@ -1,67 +1,43 @@
package app.revanced.meta
-import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
-import app.revanced.patcher.extensions.PatchExtensions.dependencies
-import app.revanced.patcher.extensions.PatchExtensions.description
-import app.revanced.patcher.extensions.PatchExtensions.include
-import app.revanced.patcher.extensions.PatchExtensions.options
-import app.revanced.patcher.extensions.PatchExtensions.patchName
-import app.revanced.patcher.patch.PatchOption
+import app.revanced.patcher.PatchSet
+import app.revanced.patcher.patch.Patch
import com.google.gson.GsonBuilder
import java.io.File
internal class JsonGenerator : PatchesFileGenerator {
- override fun generate(bundle: PatchBundlePatches) {
- val patches = bundle.map {
- JsonPatch(
- it.patchName,
- it.description ?: "This patch has no description.",
- !it.include,
- it.options?.map { option ->
- JsonPatch.Option(
- option.key,
- option.title,
- option.description,
- option.required,
- option.let { listOption ->
- if (listOption is PatchOption.ListOption<*>) {
- listOption.options.toMutableList().toTypedArray()
- } else null
- }
- )
- }?.toTypedArray() ?: emptyArray(),
- it.dependencies?.map { dep ->
- dep.java.patchName
- }?.toTypedArray() ?: emptyArray(),
- it.compatiblePackages?.map { pkg ->
- JsonPatch.CompatiblePackage(pkg.name, pkg.versions)
- }?.toTypedArray() ?: emptyArray()
- )
- }
-
- val json = File("patches.json")
- json.writeText(GsonBuilder().serializeNulls().create().toJson(patches))
+ override fun generate(patches: PatchSet) = patches.map {
+ JsonPatch(
+ it.name!!,
+ it.description,
+ it.compatiblePackages,
+ it.dependencies?.map { dependency -> dependency::class.java.name }?.toSet(),
+ it.use,
+ it.requiresIntegrations,
+ it.options.values.map { option ->
+ JsonPatch.Option(option.key, option.value, option.title, option.description, option.required)
+ }
+ )
+ }.let {
+ File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it))
}
+ @Suppress("unused")
private class JsonPatch(
- val name: String,
- val description: String,
- val excluded: Boolean,
- val options: Array,
- val dependencies: Array,
- val compatiblePackages: Array,
+ val name: String? = null,
+ val description: String? = null,
+ val compatiblePackages: Set? = null,
+ val dependencies: Set? = null,
+ val use: Boolean = true,
+ val requiresIntegrations: Boolean = false,
+ val options: List
) {
- class CompatiblePackage(
- val name: String,
- val versions: Array,
- )
-
class Option(
val key: String,
- val title: String,
- val description: String,
+ val default: Any?,
+ val title: String?,
+ val description: String?,
val required: Boolean,
- val choices: Array<*>?,
)
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/meta/PatchesFileGenerator.kt b/src/main/kotlin/app/revanced/meta/PatchesFileGenerator.kt
index 23c1d100f..61d8e85da 100644
--- a/src/main/kotlin/app/revanced/meta/PatchesFileGenerator.kt
+++ b/src/main/kotlin/app/revanced/meta/PatchesFileGenerator.kt
@@ -1,13 +1,11 @@
package app.revanced.meta
import app.revanced.patcher.PatchBundleLoader
-import app.revanced.patcher.patch.PatchClass
+import app.revanced.patcher.PatchSet
import java.io.File
-internal typealias PatchBundlePatches = List
-
internal interface PatchesFileGenerator {
- fun generate(bundle: PatchBundlePatches)
+ fun generate(patches: PatchSet)
private companion object {
@JvmStatic
diff --git a/src/main/kotlin/app/revanced/patches/all/activity/exportall/patch/ExportAllActivitiesPatch.kt b/src/main/kotlin/app/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/all/activity/exportall/patch/ExportAllActivitiesPatch.kt
rename to src/main/kotlin/app/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch.kt
index 4d67cdeb2..e9a38f533 100644
--- a/src/main/kotlin/app/revanced/patches/all/activity/exportall/patch/ExportAllActivitiesPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch.kt
@@ -1,15 +1,17 @@
-package app.revanced.patches.all.activity.exportall.patch
+package app.revanced.patches.all.activity.exportall
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.Patch
-@Patch(false)
-@Name("Export all activities")
-@Description("Makes all app activities exportable.")
-class ExportAllActivitiesPatch : ResourcePatch {
+@Patch(
+ name = "Export all activities",
+ description = "Makes all app activities exportable.",
+ use = false
+)
+@Suppress("unused")
+object ExportAllActivitiesPatch : ResourcePatch() {
+ private const val EXPORTED_FLAG = "android:exported"
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
@@ -32,8 +34,4 @@ class ExportAllActivitiesPatch : ResourcePatch {
}
}
}
-
- private companion object {
- const val EXPORTED_FLAG = "android:exported"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/patch/SpoofWifiPatch.kt b/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/SpoofWifiPatch.kt
similarity index 89%
rename from src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/patch/SpoofWifiPatch.kt
rename to src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/SpoofWifiPatch.kt
index f6637c439..b304d3953 100644
--- a/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/patch/SpoofWifiPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/SpoofWifiPatch.kt
@@ -1,27 +1,44 @@
-package app.revanced.patches.all.connectivity.wifi.spoof.patch
+package app.revanced.patches.all.connectivity.wifi.spoof
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.util.patch.*
+import app.revanced.util.patch.AbstractTransformInstructionsPatch
+import app.revanced.util.patch.IMethodCall
+import app.revanced.util.patch.Instruction35cInfo
+import app.revanced.util.patch.filterMapInstruction35c
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
-import java.util.*
-@Patch(false)
-@Name("Spoof wifi connection")
-@Description("Spoofs an existing Wi-Fi connection.")
-@RequiresIntegrations
-class SpoofWifiPatch : AbstractTransformInstructionsPatch() {
+@Patch(
+ name = "Spoof Wi-Fi connection",
+ description = "Spoofs an existing Wi-Fi connection.",
+ use = false,
+ requiresIntegrations = true
+)
+@Suppress("unused")
+object SpoofWifiPatch : AbstractTransformInstructionsPatch() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch"
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch"
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "${INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX};"
+ override fun filterMap(
+ classDef: ClassDef,
+ method: Method,
+ instruction: Instruction,
+ instructionIndex: Int
+ ) = filterMapInstruction35c(
+ INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
+ classDef,
+ instruction,
+ instructionIndex
+ )
+
+ override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) {
+ val (methodType, instruction, instructionIndex) = entry
+ methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
}
+
// Information about method calls we want to replace
enum class MethodCall(
override val definedClassName: String,
@@ -186,21 +203,4 @@ class SpoofWifiPatch : AbstractTransformInstructionsPatch()
"V",
);
}
-
- override fun filterMap(
- classDef: ClassDef,
- method: Method,
- instruction: Instruction,
- instructionIndex: Int
- ) = filterMapInstruction35c(
- INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
- classDef,
- instruction,
- instructionIndex
- )
-
- override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) {
- val (methodType, instruction, instructionIndex) = entry
- methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/all/interaction/gestures/patch/PredictiveBackGesturePatch.kt b/src/main/kotlin/app/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/all/interaction/gestures/patch/PredictiveBackGesturePatch.kt
rename to src/main/kotlin/app/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch.kt
index 22763c67f..3f3a0b9d5 100644
--- a/src/main/kotlin/app/revanced/patches/all/interaction/gestures/patch/PredictiveBackGesturePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch.kt
@@ -1,15 +1,18 @@
-package app.revanced.patches.all.interaction.gestures.patch
+package app.revanced.patches.all.interaction.gestures
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.Patch
+
+@Patch(
+ name = "Predictive back gesture",
+ description = "Enables the predictive back gesture introduced on Android 13.",
+ use = false
+)
+@Suppress("unused")
+object PredictiveBackGesturePatch : ResourcePatch() {
+ private const val FLAG = "android:enableOnBackInvokedCallback"
-@Patch(false)
-@Name("Predictive back gesture")
-@Description("Enables the predictive back gesture introduced on Android 13.")
-class PredictiveBackGesturePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
@@ -20,12 +23,7 @@ class PredictiveBackGesturePatch : ResourcePatch {
document.createAttribute(FLAG)
.apply { value = "true" }
.let(attributes::setNamedItem)
-
}
}
}
-
- private companion object {
- const val FLAG = "android:enableOnBackInvokedCallback"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/all/misc/debugging/patch/EnableAndroidDebuggingPatch.kt b/src/main/kotlin/app/revanced/patches/all/misc/debugging/EnableAndroidDebuggingPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/all/misc/debugging/patch/EnableAndroidDebuggingPatch.kt
rename to src/main/kotlin/app/revanced/patches/all/misc/debugging/EnableAndroidDebuggingPatch.kt
index 441dc24a5..902205e61 100644
--- a/src/main/kotlin/app/revanced/patches/all/misc/debugging/patch/EnableAndroidDebuggingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/misc/debugging/EnableAndroidDebuggingPatch.kt
@@ -1,16 +1,17 @@
-package app.revanced.patches.all.misc.debugging.patch
+package app.revanced.patches.all.misc.debugging
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.*
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.Patch
import org.w3c.dom.Element
-@Patch(false)
-@Name("Enable android debugging")
-@Description("Enables Android debugging capabilities. This can slow down the app.")
-class EnableAndroidDebuggingPatch : ResourcePatch {
+@Patch(
+ name = "Enable Android debugging",
+ description = "Enables Android debugging capabilities. This can slow down the app.",
+ use = false
+)
+@Suppress("unused")
+object EnableAndroidDebuggingPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { dom ->
val applicationNode = dom
@@ -22,5 +23,4 @@ class EnableAndroidDebuggingPatch : ResourcePatch {
applicationNode.setAttribute("android:debuggable", "true")
}
}
-
}
diff --git a/src/main/kotlin/app/revanced/patches/all/misc/network/patch/OverrideCertificatePinningPatch.kt b/src/main/kotlin/app/revanced/patches/all/misc/network/OverrideCertificatePinningPatch.kt
similarity index 82%
rename from src/main/kotlin/app/revanced/patches/all/misc/network/patch/OverrideCertificatePinningPatch.kt
rename to src/main/kotlin/app/revanced/patches/all/misc/network/OverrideCertificatePinningPatch.kt
index 5d571dbef..d44033185 100644
--- a/src/main/kotlin/app/revanced/patches/all/misc/network/patch/OverrideCertificatePinningPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/misc/network/OverrideCertificatePinningPatch.kt
@@ -1,20 +1,20 @@
-package app.revanced.patches.all.misc.network.patch
+package app.revanced.patches.all.misc.network
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.all.misc.debugging.patch.EnableAndroidDebuggingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch
import org.w3c.dom.Element
import java.io.File
-@Patch(false)
-@Name("Override certificate pinning")
-@Description("Overrides certificate pinning, allowing to inspect traffic via a proxy.")
-@DependsOn([EnableAndroidDebuggingPatch::class])
-class OverrideCertificatePinningPatch : ResourcePatch {
+@Patch(
+ name = "Override certificate pinning",
+ description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
+ dependencies = [EnableAndroidDebuggingPatch::class],
+ use = false
+)
+@Suppress("unused")
+object OverrideCertificatePinningPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
val resXmlDirectory = context["res/xml"]
diff --git a/src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt b/src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt
similarity index 58%
rename from src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt
rename to src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt
index 8498ee694..5a0501ded 100644
--- a/src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt
@@ -1,16 +1,26 @@
-package app.revanced.patches.all.misc.packagename.patch
+package app.revanced.patches.all.misc.packagename
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.*
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.PatchException
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
import org.w3c.dom.Element
-@Patch(false)
-@Name("Change package name")
-@Description("Changes the package name. Appends \".revanced\" to the package name by default.")
-class ChangePackageNamePatch : ResourcePatch {
+@Patch(
+ name = "Change package name",
+ description = "Appends \".revanced\" to the package name by default.",
+ use = false
+)
+@Suppress("unused")
+object ChangePackageNamePatch : ResourcePatch() {
+ private var packageName by stringPatchOption(
+ key = "packageName",
+ default = null,
+ title = "Package name",
+ description = "The name of the package to rename the app to.",
+ )
+
override fun execute(context: ResourceContext) {
val packageNameToUse = packageName ?: getDefaultPackageName(context)
@@ -36,15 +46,4 @@ class ChangePackageNamePatch : ResourcePatch {
return manifest.getAttribute("package")
}
}
-
- companion object : OptionsContainer() {
- var packageName: String? by option(
- PatchOption.StringOption(
- key = "packageName",
- default = null,
- title = "Package name",
- description = "The name of the package to rename the app to.",
- )
- )
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/bytecode/patch/RemoveCaptureRestrictionPatch.kt b/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/RemoveCaptureRestrictionPatch.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/bytecode/patch/RemoveCaptureRestrictionPatch.kt
rename to src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/RemoveCaptureRestrictionPatch.kt
index 7e372798b..3b5bc3596 100644
--- a/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/bytecode/patch/RemoveCaptureRestrictionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/RemoveCaptureRestrictionPatch.kt
@@ -1,12 +1,7 @@
-package app.revanced.patches.all.screencapture.removerestriction.bytecode.patch
+package app.revanced.patches.all.screencapture.removerestriction
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.all.screencapture.removerestriction.resource.patch.RemoveCaptureRestrictionResourcePatch
import app.revanced.util.patch.AbstractTransformInstructionsPatch
import app.revanced.util.patch.IMethodCall
import app.revanced.util.patch.Instruction35cInfo
@@ -15,12 +10,18 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
-@Patch(false)
-@Name("Remove screen capture restriction")
-@Description("Removes the restriction of capturing audio from apps that normally wouldn't allow it.")
-@DependsOn([RemoveCaptureRestrictionResourcePatch::class])
-@RequiresIntegrations
-class RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch() {
+@Patch(
+ name = "Remove screen capture restriction",
+ description = "Removes the restriction of capturing audio from apps that normally wouldn't allow it.",
+ dependencies = [RemoveCaptureRestrictionResourcePatch::class],
+ use = false,
+ requiresIntegrations = true
+)
+@Suppress("unused")
+object RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
+ "Lapp/revanced/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
// Information about method calls we want to replace
enum class MethodCall(
override val definedClassName: String,
@@ -58,10 +59,4 @@ class RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch
diff --git a/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt b/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt
rename to src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.kt
index 05c49282b..ce0db09da 100644
--- a/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch.kt
@@ -1,9 +1,6 @@
-package app.revanced.patches.all.screenshot.removerestriction.patch
+package app.revanced.patches.all.screenshot.removerestriction
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.patch.AbstractTransformInstructionsPatch
import app.revanced.util.patch.IMethodCall
@@ -13,32 +10,17 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
-@Patch(false)
-@Name("Remove screenshot restriction")
-@Description("Removes the restriction of taking screenshots in apps that normally wouldn't allow it.")
-@RequiresIntegrations
-class RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch() {
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
+@Patch(
+ name = "Remove screenshot restriction",
+ description = "Removes the restriction of taking screenshots in apps that normally wouldn't allow it.",
+ use = false,
+ requiresIntegrations = true,
+)
+@Suppress("unused")
+object RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
- }
-
- // Information about method calls we want to replace
- enum class MethodCall(
- override val definedClassName: String,
- override val methodName: String,
- override val methodParams: Array,
- override val returnType: String
- ): IMethodCall {
- SetFlags(
- "Landroid/view/Window;",
- "setFlags",
- arrayOf("I", "I"),
- "V",
- );
- }
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
override fun filterMap(
classDef: ClassDef,
@@ -56,4 +38,19 @@ class RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch,
+ override val returnType: String
+ ): IMethodCall {
+ SetFlags(
+ "Landroid/view/Window;",
+ "setFlags",
+ arrayOf("I", "I"),
+ "V",
+ );
+ }
}
diff --git a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt
rename to src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt
index 2c5d8ed5c..a108b0f04 100644
--- a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt
@@ -1,23 +1,22 @@
-package app.revanced.patches.backdrops.misc.pro.patch
+package app.revanced.patches.backdrops.misc.pro
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.backdrops.misc.pro.annotations.ProUnlockCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.backdrops.misc.pro.fingerprints.ProUnlockFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@Name("Pro unlock")
-@Description("Unlocks pro-only functions.")
-@ProUnlockCompatibility
-class ProUnlockPatch : BytecodePatch(
- listOf(ProUnlockFingerprint)
+@Patch(
+ name = "Pro unlock",
+ compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers", ["4.52"])]
+)
+@Suppress("unused")
+object ProUnlockPatch : BytecodePatch(
+ setOf(ProUnlockFingerprint)
) {
override fun execute(context: BytecodeContext) {
ProUnlockFingerprint.result?.let { result ->
diff --git a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/annotations/ProUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/annotations/ProUnlockCompatibility.kt
deleted file mode 100644
index 0159508b5..000000000
--- a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/annotations/ProUnlockCompatibility.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package app.revanced.patches.backdrops.misc.pro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.backdrops.wallpapers", arrayOf("4.52"))])
-internal annotation class ProUnlockCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/candylinkvpn/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/candylinkvpn/UnlockProPatch.kt
similarity index 57%
rename from src/main/kotlin/app/revanced/patches/candylinkvpn/patch/UnlockProPatch.kt
rename to src/main/kotlin/app/revanced/patches/candylinkvpn/UnlockProPatch.kt
index c1eb4b7f6..810256533 100644
--- a/src/main/kotlin/app/revanced/patches/candylinkvpn/patch/UnlockProPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/candylinkvpn/UnlockProPatch.kt
@@ -1,21 +1,20 @@
-package app.revanced.patches.candylinkvpn.patch
+package app.revanced.patches.candylinkvpn
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.candylinkvpn.annotations.UnlockProCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.candylinkvpn.fingerprints.IsPremiumPurchasedFingerprint
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks premium features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(IsPremiumPurchasedFingerprint)
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("com.candylink.openvpn")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(
+ setOf(IsPremiumPurchasedFingerprint)
) {
override fun execute(context: BytecodeContext) {
IsPremiumPurchasedFingerprint.result?.mutableMethod?.addInstructions(
diff --git a/src/main/kotlin/app/revanced/patches/candylinkvpn/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/candylinkvpn/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index 36c0f653c..000000000
--- a/src/main/kotlin/app/revanced/patches/candylinkvpn/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.candylinkvpn.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.candylink.openvpn")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/fingerprints/UserSerializationMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/fingerprints/UserSerializationMethodFingerprint.kt
deleted file mode 100644
index 2d8bcdda1..000000000
--- a/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/fingerprints/UserSerializationMethodFingerprint.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package app.revanced.patches.duolingo.unlocksuper.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import com.android.tools.smali.dexlib2.AccessFlags
-import com.android.tools.smali.dexlib2.Opcode
-
-object UserSerializationMethodFingerprint : MethodFingerprint(
- returnType = "V",
- accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
- strings = listOf(
- "betaStatus",
- "coachOutfit",
- "globalAmbassadorStatus",
- ),
- opcodes = listOf(
- Opcode.MOVE_FROM16,
- Opcode.IPUT_BOOLEAN,
- ),
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/patch/UnlockDuolingoSuperPatch.kt b/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/patch/UnlockDuolingoSuperPatch.kt
deleted file mode 100644
index c02228f2b..000000000
--- a/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/patch/UnlockDuolingoSuperPatch.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package app.revanced.patches.duolingo.unlocksuper.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
-import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.duolingo.unlocksuper.fingerprints.IsUserSuperMethodFingerprint
-import app.revanced.patches.duolingo.unlocksuper.fingerprints.UserSerializationMethodFingerprint
-import com.android.tools.smali.dexlib2.Opcode
-import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22c
-import com.android.tools.smali.dexlib2.iface.reference.Reference
-
-@Patch
-@Name("Unlock Duolingo Super")
-@Description("Unlocks Duolingo Super features.")
-@Compatibility([Package("com.duolingo")])
-class UnlockDuolingoSuperPatch : BytecodePatch(
- listOf(UserSerializationMethodFingerprint, IsUserSuperMethodFingerprint)
-) {
-
- /* First find the reference to the isUserSuper field, then patch the instruction that assigns it to false.
- * This strategy is used because the method that sets the isUserSuper field is difficult to fingerprint reliably.
- */
- override fun execute(context: BytecodeContext) {
- // Find the reference to the isUserSuper field.
- val isUserSuperReference = IsUserSuperMethodFingerprint
- .result
- ?.mutableMethod
- ?.getInstructions()
- ?.filterIsInstance()
- ?.firstOrNull { it.opcode == Opcode.IGET_BOOLEAN }
- ?.reference
- ?: throw IsUserSuperMethodFingerprint.exception
-
- // Patch the instruction that assigns isUserSuper to true.
- UserSerializationMethodFingerprint
- .result
- ?.mutableMethod
- ?.apply {
- replaceInstructions(
- indexOfReference(isUserSuperReference) - 1,
- "const/4 v2, 0x1"
- )
- }
- ?: throw UserSerializationMethodFingerprint.exception
- }
-
- private companion object {
- private fun MutableMethod.indexOfReference(reference: Reference) = getInstructions()
- .filterIsInstance()
- .filter { it.opcode == Opcode.IPUT_BOOLEAN }.indexOfFirst { it.reference == reference }.let {
- if (it == -1) throw PatchException("Could not find index of instruction with supplied reference.")
- else it
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/patch/BootloaderDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/BootloaderDetectionPatch.kt
similarity index 59%
rename from src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/patch/BootloaderDetectionPatch.kt
rename to src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/BootloaderDetectionPatch.kt
index 6864d9635..180f26f7c 100644
--- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/patch/BootloaderDetectionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/BootloaderDetectionPatch.kt
@@ -1,23 +1,23 @@
-package app.revanced.patches.finanzonline.detection.bootloader.patch
+package app.revanced.patches.finanzonline.detection.bootloader
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.BootStateFingerprint
import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.CreateKeyFingerprint
-import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility
-@Patch
-@Name("Remove bootloader detection")
-@Description("Removes the check for an unlocked bootloader.")
-@DetectionCompatibility
-class BootloaderDetectionPatch : BytecodePatch(
- listOf(CreateKeyFingerprint, BootStateFingerprint)
+@Patch(
+ name = "Remove bootloader detection",
+ description = "Removes the check for an unlocked bootloader.",
+ compatiblePackages = [CompatiblePackage("at.gv.bmf.bmf2go")]
+)
+@Suppress("unused")
+object BootloaderDetectionPatch : BytecodePatch(
+ setOf(CreateKeyFingerprint, BootStateFingerprint)
) {
override fun execute(context: BytecodeContext) {
arrayOf(CreateKeyFingerprint, BootStateFingerprint).forEach { fingerprint ->
diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/RootDetectionPatch.kt
similarity index 56%
rename from src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt
rename to src/main/kotlin/app/revanced/patches/finanzonline/detection/root/RootDetectionPatch.kt
index 35ebdfe32..6de93017a 100644
--- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/RootDetectionPatch.kt
@@ -1,21 +1,21 @@
-package app.revanced.patches.finanzonline.detection.root.patch
+package app.revanced.patches.finanzonline.detection.root
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.finanzonline.detection.root.fingerprints.RootDetectionFingerprint
-import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility
-@Patch
-@Name("Remove root detection")
-@Description("Removes the check for root permissions.")
-@DetectionCompatibility
-class RootDetectionPatch : BytecodePatch(
- listOf(RootDetectionFingerprint)
+@Patch(
+ name = "Remove root detection",
+ description = "Removes the check for root permissions.",
+ compatiblePackages = [CompatiblePackage("at.gv.bmf.bmf2go")]
+)
+@Suppress("unused")
+object RootDetectionPatch : BytecodePatch(
+ setOf(RootDetectionFingerprint)
) {
override fun execute(context: BytecodeContext) {
RootDetectionFingerprint.result?.mutableMethod?.addInstructions(
diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/shared/annotations/DetectionCompatibility.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/shared/annotations/DetectionCompatibility.kt
deleted file mode 100644
index 8da838bae..000000000
--- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/shared/annotations/DetectionCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.finanzonline.detection.shared.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("at.gv.bmf.bmf2go")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DetectionCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/patch/RemoveDeviceRestrictions.kt b/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/patch/RemoveDeviceRestrictions.kt
rename to src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt
index f505efbac..22f69b85d 100644
--- a/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/patch/RemoveDeviceRestrictions.kt
+++ b/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt
@@ -1,25 +1,24 @@
-package app.revanced.patches.googlerecorder.restrictions.patch
+package app.revanced.patches.googlerecorder.restrictions
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.googlerecorder.restrictions.fingerprints.OnApplicationCreateFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@Name("Remove device restrictions")
-@Description("Removes restrictions from using the app on any device.")
-@Compatibility([Package("com.google.android.apps.recorder")])
-class RemoveDeviceRestrictions : BytecodePatch(
- listOf(OnApplicationCreateFingerprint)
+@Patch(
+ name = "Remove device restrictions",
+ description = "Removes restrictions from using the app on any device. Requires mounting patched app over original.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.recorder")]
+)
+@Suppress("unused")
+object RemoveDeviceRestrictions : BytecodePatch(
+ setOf(OnApplicationCreateFingerprint)
) {
override fun execute(context: BytecodeContext) {
OnApplicationCreateFingerprint.result?.let {
diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/DisableAdsPatch.kt
new file mode 100644
index 000000000..bd6ae8a35
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/hexeditor/ad/DisableAdsPatch.kt
@@ -0,0 +1,26 @@
+package app.revanced.patches.hexeditor.ad
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.hexeditor.ad.fingerprints.PrimaryAdsFingerprint
+
+@Patch(
+ name = "Disable ads",
+ compatiblePackages = [CompatiblePackage("com.myprog.hexedit")]
+)
+@Suppress("unused")
+object DisableAdsPatch : BytecodePatch(
+ setOf(PrimaryAdsFingerprint)
+) {
+ override fun execute(context: BytecodeContext) = PrimaryAdsFingerprint.result?.mutableMethod?.replaceInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw PrimaryAdsFingerprint.exception
+}
diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt
deleted file mode 100644
index 15fa03761..000000000
--- a/src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package app.revanced.patches.hexeditor.ad.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.myprog.hexedit")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class HexEditorAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt
deleted file mode 100644
index 84d4dbf95..000000000
--- a/src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package app.revanced.patches.hexeditor.ad.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.hexeditor.ad.annotations.HexEditorAdsCompatibility
-import app.revanced.patches.hexeditor.ad.fingerprints.PrimaryAdsFingerprint
-
-@Patch
-@Name("Disable ads")
-@Description("Disables ads in HexEditor.")
-@HexEditorAdsCompatibility
-class HexEditorAdsPatch : BytecodePatch(
- listOf(
- PrimaryAdsFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- val method = PrimaryAdsFingerprint.result!!.mutableMethod
-
- method.replaceInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/UnlockProPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt
rename to src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/UnlockProPatch.kt
index 13d8c8490..eba26e426 100644
--- a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/UnlockProPatch.kt
@@ -1,22 +1,19 @@
-package app.revanced.patches.iconpackstudio.misc.pro.patch
+package app.revanced.patches.iconpackstudio.misc.pro
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.iconpackstudio.misc.pro.annotations.UnlockProCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.iconpackstudio.misc.pro.fingerprints.CheckProFingerprint
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks all pro features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(
- CheckProFingerprint
- )
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("ginlemon.iconpackstudio")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(
+ setOf(CheckProFingerprint)
) {
override fun execute(context: BytecodeContext) {
val method = CheckProFingerprint.result!!.mutableMethod
diff --git a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index e7a54f1f9..000000000
--- a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.iconpackstudio.misc.pro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("ginlemon.iconpackstudio")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/idaustria/detection/root/RootDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/idaustria/detection/root/RootDetectionPatch.kt
new file mode 100644
index 000000000..35ab4a61a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/idaustria/detection/root/RootDetectionPatch.kt
@@ -0,0 +1,21 @@
+package app.revanced.patches.idaustria.detection.root
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.idaustria.detection.root.fingerprints.RootDetectionFingerprint
+
+@Patch(
+ name = "Remove root detection",
+ description = "Removes the check for root permissions and unlocked bootloader.",
+ compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
+)
+@Suppress("unused")
+object RootDetectionPatch : BytecodePatch(
+ setOf(RootDetectionFingerprint)
+) {
+ override fun execute(context: BytecodeContext) =
+ RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
+}
diff --git a/src/main/kotlin/app/revanced/patches/idaustria/detection/root/patch/RootDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/idaustria/detection/root/patch/RootDetectionPatch.kt
deleted file mode 100644
index f7edc70c2..000000000
--- a/src/main/kotlin/app/revanced/patches/idaustria/detection/root/patch/RootDetectionPatch.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package app.revanced.patches.idaustria.detection.root.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.idaustria.detection.root.fingerprints.RootDetectionFingerprint
-import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility
-
-@Patch
-@Name("Remove root detection")
-@Description("Removes the check for root permissions and unlocked bootloader.")
-@DetectionCompatibility
-class RootDetectionPatch : BytecodePatch(
- listOf(RootDetectionFingerprint)
-) {
- override fun execute(context: BytecodeContext) =
- RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
-}
diff --git a/src/main/kotlin/app/revanced/patches/idaustria/detection/shared/annotations/DetectionCompatibility.kt b/src/main/kotlin/app/revanced/patches/idaustria/detection/shared/annotations/DetectionCompatibility.kt
deleted file mode 100644
index dbc8d4619..000000000
--- a/src/main/kotlin/app/revanced/patches/idaustria/detection/shared/annotations/DetectionCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.idaustria.detection.shared.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("at.gv.oe.app")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DetectionCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/patch/SpoofSignaturePatch.kt b/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/SpoofSignaturePatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/idaustria/detection/signature/patch/SpoofSignaturePatch.kt
rename to src/main/kotlin/app/revanced/patches/idaustria/detection/signature/SpoofSignaturePatch.kt
index 295855048..ae427b744 100644
--- a/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/patch/SpoofSignaturePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/SpoofSignaturePatch.kt
@@ -1,23 +1,23 @@
-package app.revanced.patches.idaustria.detection.signature.patch
+package app.revanced.patches.idaustria.detection.signature
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.idaustria.detection.signature.fingerprints.SpoofSignatureFingerprint
-@Patch
-@Name("Spoof signature")
-@Description("Spoofs the signature of the app.")
-@DetectionCompatibility
-class SpoofSignaturePatch : BytecodePatch(
- listOf(SpoofSignatureFingerprint)
+@Patch(
+ name = "Spoof signature",
+ description = "Spoofs the signature of the app.",
+ compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
+)
+@Suppress("unused")
+object SpoofSignaturePatch : BytecodePatch(
+ setOf(SpoofSignatureFingerprint)
) {
- companion object {
- const val EXPECTED_SIGNATURE = "OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
+ private const val EXPECTED_SIGNATURE =
+ "OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
"067c149768320026e10b24799a1339e414605e448e3f264444a327b9ae292be2b62ad567dd1800dbed4a88f718a33dc6db6b" +
"f5178aa41aa0efff8a3409f5ca95dbfccd92c7b4298966df806ea7a0204a00f0e745f6d9f13bdf24f3df715d7b62c1600906" +
"15de1c8a956b9286764985a3b3c060963c435fb9481a5543aaf0671fc2dba6c5c2b17d1ef1d85137f14dc9bbdf3490288087" +
@@ -28,7 +28,6 @@ class SpoofSignaturePatch : BytecodePatch(
"0def55be2c1f6f9c72c92fb45d7e0a9ac571cb38f0a9a37bb33ea06f223fde8c7a92e8c47769e386f9799776e8f110c21df2" +
"77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" +
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
- }
override fun execute(context: BytecodeContext) {
SpoofSignatureFingerprint.result!!.mutableMethod.addInstructions(
diff --git a/src/main/kotlin/app/revanced/patches/inshorts/ad/patch/InshortsAdsPatch.kt b/src/main/kotlin/app/revanced/patches/inshorts/ad/InshortsAdsPatch.kt
similarity index 61%
rename from src/main/kotlin/app/revanced/patches/inshorts/ad/patch/InshortsAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/inshorts/ad/InshortsAdsPatch.kt
index 8b48bcd41..2ec7536e8 100644
--- a/src/main/kotlin/app/revanced/patches/inshorts/ad/patch/InshortsAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/inshorts/ad/InshortsAdsPatch.kt
@@ -1,21 +1,20 @@
-package app.revanced.patches.inshorts.ad.patch
+package app.revanced.patches.inshorts.ad
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.inshorts.ad.annotations.HideAdsCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.inshorts.ad.fingerprints.InshortsAdsFingerprint
-@Patch
-@Name("Hide ads")
-@Description("Removes ads from Inshorts.")
-@HideAdsCompatibility
-class HideAdsPatch : BytecodePatch(
- listOf(InshortsAdsFingerprint)
+@Patch(
+ name = "Hide ads",
+ compatiblePackages = [CompatiblePackage("com.nis.app")]
+)
+@Suppress("unused")
+object HideAdsPatch : BytecodePatch(
+ setOf(InshortsAdsFingerprint)
) {
override fun execute(context: BytecodeContext) {
InshortsAdsFingerprint.result?.let { result ->
diff --git a/src/main/kotlin/app/revanced/patches/inshorts/ad/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/inshorts/ad/annotations/HideAdsCompatibility.kt
deleted file mode 100644
index 372929a12..000000000
--- a/src/main/kotlin/app/revanced/patches/inshorts/ad/annotations/HideAdsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.inshorts.ad.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.nis.app")])
-
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt
similarity index 90%
rename from src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt
index a8b2cc699..feb4ee5d5 100644
--- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt
@@ -1,14 +1,14 @@
-package app.revanced.patches.instagram.patches.ads.timeline.patch
+package app.revanced.patches.instagram.patches.ads.timeline
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint
@@ -19,12 +19,14 @@ import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.Shop
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@Name("Hide timeline ads")
-@Description("Removes ads from the timeline.")
-@Compatibility([Package("com.instagram.android", arrayOf("275.0.0.27.98"))])
-class HideTimelineAdsPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Hide timeline ads",
+ description = "Removes ads from the timeline.",
+ compatiblePackages = [CompatiblePackage("com.instagram.android", ["275.0.0.27.98"])]
+)
+@Suppress("unused")
+object HideTimelineAdsPatch : BytecodePatch(
+ setOf(
ShowAdFingerprint,
MediaFingerprint,
PaidPartnershipAdFingerprint // Unlike the other ads this one is resolved from all classes.
diff --git a/src/main/kotlin/app/revanced/patches/irplus/ad/patch/IrplusAdsPatch.kt b/src/main/kotlin/app/revanced/patches/irplus/ad/RemoveAdsPatch.kt
similarity index 56%
rename from src/main/kotlin/app/revanced/patches/irplus/ad/patch/IrplusAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/irplus/ad/RemoveAdsPatch.kt
index a138d5fd9..d9750df4c 100644
--- a/src/main/kotlin/app/revanced/patches/irplus/ad/patch/IrplusAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/irplus/ad/RemoveAdsPatch.kt
@@ -1,21 +1,20 @@
-package app.revanced.patches.irplus.ad.patch
+package app.revanced.patches.irplus.ad
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.irplus.ad.annotations.IrplusAdsCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.irplus.ad.fingerprints.IrplusAdsFingerprint
-@Patch
-@Name("Remove ads")
-@Description("Removes all ads from the app.")
-@IrplusAdsCompatibility
-class IrplusAdsPatch : BytecodePatch(
- listOf(IrplusAdsFingerprint)
+@Patch(
+ name = "Remove ads",
+ compatiblePackages = [CompatiblePackage("net.binarymode.android.irplus")]
+)
+@Suppress("unused")
+object RemoveAdsPatch : BytecodePatch(
+ setOf(IrplusAdsFingerprint)
) {
override fun execute(context: BytecodeContext) {
val method = IrplusAdsFingerprint.result!!.mutableMethod
diff --git a/src/main/kotlin/app/revanced/patches/irplus/ad/annotations/IrplusAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/irplus/ad/annotations/IrplusAdsCompatibility.kt
deleted file mode 100644
index c7a4a56f1..000000000
--- a/src/main/kotlin/app/revanced/patches/irplus/ad/annotations/IrplusAdsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.irplus.ad.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("net.binarymode.android.irplus")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class IrplusAdsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/login/patch/DisableMandatoryLoginPatch.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/login/DisableMandatoryLoginPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/lightroom/misc/login/patch/DisableMandatoryLoginPatch.kt
rename to src/main/kotlin/app/revanced/patches/lightroom/misc/login/DisableMandatoryLoginPatch.kt
index b1317bb07..e2eb41f10 100644
--- a/src/main/kotlin/app/revanced/patches/lightroom/misc/login/patch/DisableMandatoryLoginPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/lightroom/misc/login/DisableMandatoryLoginPatch.kt
@@ -1,18 +1,21 @@
-package app.revanced.patches.lightroom.misc.login.patch
+package app.revanced.patches.lightroom.misc.login
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.lightroom.misc.login.annotations.DisableMandatoryLoginCompatibility
-import app.revanced.patches.lightroom.misc.login.fingerprint.IsLoggedInFingerprint
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.lightroom.misc.login.fingerprints.IsLoggedInFingerprint
-@Patch
-@Name("Disable mandatory login")
-@DisableMandatoryLoginCompatibility
-class DisableMandatoryLoginPatch : BytecodePatch(listOf(IsLoggedInFingerprint)) {
+@Patch(
+ name = "Disable mandatory login",
+ compatiblePackages = [CompatiblePackage("com.adobe.lrmobile")]
+)
+@Suppress("unused")
+object DisableMandatoryLoginPatch : BytecodePatch(
+ setOf(IsLoggedInFingerprint)
+) {
override fun execute(context: BytecodeContext) {
IsLoggedInFingerprint.result?.mutableMethod?.apply {
val index = implementation!!.instructions.lastIndex - 1
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/login/annotations/DisableMandatoryLoginCompatibility.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/login/annotations/DisableMandatoryLoginCompatibility.kt
deleted file mode 100644
index edc9e6896..000000000
--- a/src/main/kotlin/app/revanced/patches/lightroom/misc/login/annotations/DisableMandatoryLoginCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.lightroom.misc.login.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.adobe.lrmobile",)])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DisableMandatoryLoginCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/login/fingerprint/IsLoggedInFingerprint.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/login/fingerprints/IsLoggedInFingerprint.kt
similarity index 89%
rename from src/main/kotlin/app/revanced/patches/lightroom/misc/login/fingerprint/IsLoggedInFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/lightroom/misc/login/fingerprints/IsLoggedInFingerprint.kt
index 7e56d8d02..4bdeb448c 100644
--- a/src/main/kotlin/app/revanced/patches/lightroom/misc/login/fingerprint/IsLoggedInFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/lightroom/misc/login/fingerprints/IsLoggedInFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.lightroom.misc.login.fingerprint
+package app.revanced.patches.lightroom.misc.login.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt
new file mode 100644
index 000000000..f747dcbd4
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt
@@ -0,0 +1,24 @@
+package app.revanced.patches.lightroom.misc.premium
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.lightroom.misc.premium.fingerprints.HasPurchasedFingerprint
+
+@Patch(
+ name = "Unlock premium",
+ compatiblePackages = [CompatiblePackage("com.adobe.lrmobile")]
+)
+@Suppress("unused")
+object UnlockPremiumPatch : BytecodePatch(
+ setOf(HasPurchasedFingerprint)
+){
+ override fun execute(context: BytecodeContext) {
+ // Set hasPremium = true.
+ HasPurchasedFingerprint.result?.mutableMethod?.replaceInstruction(2, "const/4 v2, 0x1")
+ ?: throw HasPurchasedFingerprint.exception
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/annotations/UnlockPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/annotations/UnlockPremiumCompatibility.kt
deleted file mode 100644
index 1c03bff62..000000000
--- a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/annotations/UnlockPremiumCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.lightroom.misc.premium.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.adobe.lrmobile")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockPremiumCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/fingerprint/HasPurchasedFingerprint.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/fingerprints/HasPurchasedFingerprint.kt
similarity index 89%
rename from src/main/kotlin/app/revanced/patches/lightroom/misc/premium/fingerprint/HasPurchasedFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/lightroom/misc/premium/fingerprints/HasPurchasedFingerprint.kt
index 31bef2284..9d15d0cf8 100644
--- a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/fingerprint/HasPurchasedFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/fingerprints/HasPurchasedFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.lightroom.misc.premium.fingerprint
+package app.revanced.patches.lightroom.misc.premium.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/patch/UnlockPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/patch/UnlockPremiumPatch.kt
deleted file mode 100644
index f71cc2a95..000000000
--- a/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/patch/UnlockPremiumPatch.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package app.revanced.patches.lightroom.misc.premium.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.lightroom.misc.premium.annotations.UnlockPremiumCompatibility
-import app.revanced.patches.lightroom.misc.premium.fingerprint.HasPurchasedFingerprint
-
-@Patch
-@Name("Unlock premium")
-@Description("Unlocks premium features.")
-@UnlockPremiumCompatibility
-class UnlockPremiumPatch : BytecodePatch(listOf(HasPurchasedFingerprint)) {
- override fun execute(context: BytecodeContext) {
- // Set hasPremium = true.
- HasPurchasedFingerprint.result?.mutableMethod?.replaceInstruction(2, "const/4 v2, 0x1")
- ?: throw HasPurchasedFingerprint.exception
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/patch/LicenseValidationPatch.kt b/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/LicenseValidationPatch.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/memegenerator/detection/license/patch/LicenseValidationPatch.kt
rename to src/main/kotlin/app/revanced/patches/memegenerator/detection/license/LicenseValidationPatch.kt
index 337d3e171..8347de814 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/patch/LicenseValidationPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/LicenseValidationPatch.kt
@@ -1,15 +1,15 @@
-package app.revanced.patches.memegenerator.detection.license.patch
+package app.revanced.patches.memegenerator.detection.license
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.memegenerator.detection.license.fingerprint.LicenseValidationFingerprint
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.memegenerator.detection.license.fingerprints.LicenseValidationFingerprint
-@Description("Disables Firebase license validation.")
-class LicenseValidationPatch : BytecodePatch(
- listOf(LicenseValidationFingerprint)
+@Patch(description = "Disables Firebase license validation.")
+object LicenseValidationPatch : BytecodePatch(
+ setOf(LicenseValidationFingerprint)
) {
override fun execute(context: BytecodeContext) {
LicenseValidationFingerprint.result?.apply {
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt b/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprints/LicenseValidationFingerprint.kt
similarity index 98%
rename from src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprints/LicenseValidationFingerprint.kt
index d6454e705..0f133ba36 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprints/LicenseValidationFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.memegenerator.detection.license.fingerprint
+package app.revanced.patches.memegenerator.detection.license.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/patch/SignatureVerificationPatch.kt b/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/SignatureVerificationPatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/patch/SignatureVerificationPatch.kt
rename to src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/SignatureVerificationPatch.kt
index 47b056daf..3c00f93ef 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/patch/SignatureVerificationPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/SignatureVerificationPatch.kt
@@ -1,15 +1,15 @@
-package app.revanced.patches.memegenerator.detection.signature.patch
+package app.revanced.patches.memegenerator.detection.signature
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.memegenerator.detection.signature.fingerprint.VerifySignatureFingerprint
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.memegenerator.detection.signature.fingerprints.VerifySignatureFingerprint
-@Description("Disables detection of incorrect signature.")
-class SignatureVerificationPatch : BytecodePatch(
- listOf(VerifySignatureFingerprint)
+@Patch(description = "Disables detection of incorrect signature.")
+object SignatureVerificationPatch : BytecodePatch(
+ setOf(VerifySignatureFingerprint)
) {
override fun execute(context: BytecodeContext) {
VerifySignatureFingerprint.result?.apply {
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt b/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprints/VerifySignatureFingerprint.kt
similarity index 98%
rename from src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprints/VerifySignatureFingerprint.kt
index 10ea37f9b..4218055d1 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprints/VerifySignatureFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.memegenerator.detection.signature.fingerprint
+package app.revanced.patches.memegenerator.detection.signature.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/UnlockProVersionPatch.kt b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/UnlockProVersionPatch.kt
new file mode 100644
index 000000000..4b07f2428
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/UnlockProVersionPatch.kt
@@ -0,0 +1,44 @@
+package app.revanced.patches.memegenerator.misc.pro
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.memegenerator.detection.license.LicenseValidationPatch
+import app.revanced.patches.memegenerator.detection.signature.SignatureVerificationPatch
+import app.revanced.patches.memegenerator.misc.pro.fingerprints.IsFreeVersionFingerprint
+
+@Patch(
+ name = "Unlock pro",
+ dependencies = [
+ SignatureVerificationPatch::class,
+ LicenseValidationPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.zombodroid.MemeGenerator", [
+ "4.6364",
+ "4.6370",
+ "4.6375",
+ "4.6377"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object UnlockProVersionPatch : BytecodePatch(
+ setOf(IsFreeVersionFingerprint)
+) {
+ override fun execute(context: BytecodeContext) {
+ IsFreeVersionFingerprint.result?.apply {
+ mutableMethod.replaceInstructions(0,
+ """
+ sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
+ return-object p0
+ """
+ )
+ } ?: throw IsFreeVersionFingerprint.exception
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index b93215674..000000000
--- a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package app.revanced.patches.memegenerator.misc.pro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.zombodroid.MemeGenerator", arrayOf(
- "4.6364",
- "4.6370",
- "4.6375",
- "4.6377",
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprints/IsFreeVersionFingerprint.kt
similarity index 91%
rename from src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprints/IsFreeVersionFingerprint.kt
index d601f5b3c..cde47e1b0 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprints/IsFreeVersionFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.memegenerator.misc.pro.fingerprint
+package app.revanced.patches.memegenerator.misc.pro.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/patch/UnlockProVersionPatch.kt b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/patch/UnlockProVersionPatch.kt
deleted file mode 100644
index 601e78b24..000000000
--- a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/patch/UnlockProVersionPatch.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package app.revanced.patches.memegenerator.misc.pro.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.memegenerator.detection.license.patch.LicenseValidationPatch
-import app.revanced.patches.memegenerator.detection.signature.patch.SignatureVerificationPatch
-import app.revanced.patches.memegenerator.misc.pro.annotations.UnlockProCompatibility
-import app.revanced.patches.memegenerator.misc.pro.fingerprint.IsFreeVersionFingerprint
-
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks pro features.")
-@DependsOn([
- SignatureVerificationPatch::class,
- LicenseValidationPatch::class
-])
-@UnlockProCompatibility
-class UnlockProVersionPatch : BytecodePatch(
- listOf(
- IsFreeVersionFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- IsFreeVersionFingerprint.result?.apply {
- mutableMethod.replaceInstructions(0,
- """
- sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
- return-object p0
- """
- )
- } ?: throw IsFreeVersionFingerprint.exception
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/patch/HideInboxAdsPatch.kt b/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/patch/HideInboxAdsPatch.kt
index 6101f4e6f..a7ff651eb 100644
--- a/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/patch/HideInboxAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/patch/HideInboxAdsPatch.kt
@@ -1,19 +1,21 @@
package app.revanced.patches.messenger.ads.inbox.patch
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.ads.inbox.fingerprints.LoadInboxAdsFingerprint
-@Patch
-@Name("Hide inbox ads")
-@Description("Hides ads in inbox.")
-@Compatibility([Package("com.facebook.orca")])
-class HideInboxAdsPatch : BytecodePatch(
- listOf(LoadInboxAdsFingerprint)
+@Patch(
+ name = "Hide inbox ads",
+ description = "Hides ads in inbox.",
+ compatiblePackages = [CompatiblePackage("com.facebook.orca")]
+)
+@Suppress("unused")
+object HideInboxAdsPatch : BytecodePatch(
+ setOf(LoadInboxAdsFingerprint)
) {
override fun execute(context: BytecodeContext) {
LoadInboxAdsFingerprint.result?.mutableMethod?.apply {
diff --git a/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerInMessageInputField.kt b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerPatch.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerInMessageInputField.kt
rename to src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerPatch.kt
index dee26e289..0ae8faabe 100644
--- a/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerInMessageInputField.kt
+++ b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerPatch.kt
@@ -1,20 +1,24 @@
package app.revanced.patches.messenger.inputfield.patch
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.inputfield.fingerprints.SwitchMessangeInputEmojiButtonFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@Name("Disable switching emoji to sticker in message input field")
-@Description("Disables switching from emoji to sticker search mode in message input field")
-@Compatibility([Package("com.facebook.orca")])
-class DisableSwitchingEmojiToStickerInMessageInputField : BytecodePatch(listOf(SwitchMessangeInputEmojiButtonFingerprint)) {
+@Patch(
+ name = "Disable switching emoji to sticker",
+ description = "Disables switching from emoji to sticker search mode in message input field.",
+ compatiblePackages = [CompatiblePackage("com.facebook.orca")]
+)
+@Suppress("unused")
+object DisableSwitchingEmojiToStickerPatch : BytecodePatch(
+ setOf(SwitchMessangeInputEmojiButtonFingerprint)
+) {
override fun execute(context: BytecodeContext) {
SwitchMessangeInputEmojiButtonFingerprint.result?.let {
val setStringIndex = it.scanResult.patternScanResult!!.startIndex + 2
diff --git a/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicator.kt b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicatorPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicator.kt
rename to src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicatorPatch.kt
index cfd852dad..03334b4ba 100644
--- a/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicator.kt
+++ b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicatorPatch.kt
@@ -1,21 +1,22 @@
package app.revanced.patches.messenger.inputfield.patch
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.inputfield.fingerprints.SendTypingIndicatorFingerprint
-@Patch
-@Name("Disable typing indicator")
-@Description("Disables the indicator while typing a message")
-@Compatibility([Package("com.facebook.orca")])
-class DisableTypingIndicator : BytecodePatch(listOf(SendTypingIndicatorFingerprint)) {
+@Patch(
+ name = "Disable typing indicator",
+ description = "Disables the indicator while typing a message.",
+ compatiblePackages = [CompatiblePackage("com.facebook.orca")]
+)
+@Suppress("unused")
+object DisableTypingIndicatorPatch : BytecodePatch(
+ setOf(SendTypingIndicatorFingerprint)
+){
override fun execute(context: BytecodeContext) {
SendTypingIndicatorFingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void")
?: throw SendTypingIndicatorFingerprint.exception
diff --git a/src/main/kotlin/app/revanced/patches/moneymanager/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/moneymanager/UnlockProPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/moneymanager/patch/UnlockProPatch.kt
rename to src/main/kotlin/app/revanced/patches/moneymanager/UnlockProPatch.kt
index a6bbe51c5..0f5afa70c 100644
--- a/src/main/kotlin/app/revanced/patches/moneymanager/patch/UnlockProPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/moneymanager/UnlockProPatch.kt
@@ -1,21 +1,20 @@
-package app.revanced.patches.moneymanager.patch
+package app.revanced.patches.moneymanager
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.moneymanager.annotations.UnlockProCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks pro features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(UnlockProFingerprint)
-) {
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("com.ithebk.expensemanager")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(
+ setOf(UnlockProFingerprint)
+){
override fun execute(context: BytecodeContext) {
UnlockProFingerprint.result!!.mutableMethod.addInstructions(
0,
diff --git a/src/main/kotlin/app/revanced/patches/moneymanager/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/moneymanager/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index 7e4be16ac..000000000
--- a/src/main/kotlin/app/revanced/patches/moneymanager/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.moneymanager.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.ithebk.expensemanager")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt
index eca9604cd..2e1c11e05 100644
--- a/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt
@@ -1,22 +1,22 @@
-package app.revanced.patches.music.ad.video.patch
+package app.revanced.patches.music.ad.video
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
-import app.revanced.patches.music.annotations.MusicCompatibility
-@Patch
-@Name("Music video ads")
-@Description("Removes ads in the music player.")
-@MusicCompatibility
-class MusicVideoAdsPatch : BytecodePatch(
- listOf(ShowMusicVideoAdsConstructorFingerprint)
+@Patch(
+ name = "Music video ads",
+ description = "Removes ads in the music player.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object MusicVideoAdsPatch : BytecodePatch(
+ setOf(ShowMusicVideoAdsConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
diff --git a/src/main/kotlin/app/revanced/patches/music/annotations/MusicCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/annotations/MusicCompatibility.kt
deleted file mode 100644
index 5cd3b494c..000000000
--- a/src/main/kotlin/app/revanced/patches/music/annotations/MusicCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.apps.youtube.music")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class MusicCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt
index 3dd5d59e7..35fa977a2 100644
--- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt
@@ -1,24 +1,22 @@
-package app.revanced.patches.music.audio.codecs.patch
+package app.revanced.patches.music.audio.codecs
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.toInstruction
-import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint
import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprint
import com.android.tools.smali.dexlib2.Opcode
-@Patch
-@Name("Codecs unlock")
-@Description("Adds more audio codec options. The new audio codecs usually result in better audio quality.")
-@MusicCompatibility
-class CodecsUnlockPatch : BytecodePatch(
- listOf(
- CodecsLockFingerprint, AllCodecsReferenceFingerprint
- )
+@Patch(
+ name = "Codecs unlock",
+ description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object CodecsUnlockPatch : BytecodePatch(
+ setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint)
) {
override fun execute(context: BytecodeContext) {
val codecsLockResult = CodecsLockFingerprint.result!!
diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt
similarity index 58%
rename from src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt
index e5801e64d..8b211b007 100644
--- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt
@@ -1,21 +1,21 @@
-package app.revanced.patches.music.audio.exclusiveaudio.patch
+package app.revanced.patches.music.audio.exclusiveaudio
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AllowExclusiveAudioPlaybackFingerprint
-@Patch
-@Name("Exclusive audio playback")
-@Description("Enables the option to play audio without video.")
-@MusicCompatibility
-class ExclusiveAudioPatch : BytecodePatch(
- listOf(AllowExclusiveAudioPlaybackFingerprint)
+@Patch(
+ name = "Exclusive audio playback",
+ description = "Enables the option to play audio without video.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object ExclusiveAudioPatch : BytecodePatch(
+ setOf(AllowExclusiveAudioPlaybackFingerprint)
) {
override fun execute(context: BytecodeContext) {
AllowExclusiveAudioPlaybackFingerprint.result?.mutableMethod?.apply {
diff --git a/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/patch/PermanentRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt
similarity index 64%
rename from src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/patch/PermanentRepeatPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt
index bba4649c7..37565f977 100644
--- a/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/patch/PermanentRepeatPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt
@@ -1,23 +1,24 @@
-package app.revanced.patches.music.interaction.permanentrepeat.patch
+package app.revanced.patches.music.interaction.permanentrepeat
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.interaction.permanentrepeat.fingerprints.RepeatTrackFingerprint
-@Patch(false)
-@Name("Permanent repeat")
-@Description("Permanently remember your repeating preference even if the playlist ends or another track is played.")
-@MusicCompatibility
-class PermanentRepeatPatch : BytecodePatch(
- listOf(RepeatTrackFingerprint)
+@Patch(
+ name = "Permanent repeat",
+ description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
+ use = false
+)
+@Suppress("unused")
+object PermanentRepeatPatch : BytecodePatch(
+ setOf(RepeatTrackFingerprint)
) {
override fun execute(context: BytecodeContext) {
RepeatTrackFingerprint.result?.let {
diff --git a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt
new file mode 100644
index 000000000..15f688bc2
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt
@@ -0,0 +1,25 @@
+package app.revanced.patches.music.interaction.permanentshuffle
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.music.interaction.permanentshuffle.fingerprints.DisableShuffleFingerprint
+
+
+@Patch(
+ name = "Permanent shuffle",
+ description = "Permanently remember your shuffle preference " +
+ "even if the playlist ends or another track is played.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
+ use = false
+)
+@Suppress("unused")
+object PermanentShuffleTogglePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
+ override fun execute(context: BytecodeContext) {
+ DisableShuffleFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
+ ?: throw DisableShuffleFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/patch/PermanentShufflePatch.kt b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/patch/PermanentShufflePatch.kt
deleted file mode 100644
index 3bb5fde34..000000000
--- a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/patch/PermanentShufflePatch.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package app.revanced.patches.music.interaction.permanentshuffle.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
-import app.revanced.patches.music.interaction.permanentshuffle.fingerprints.DisableShuffleFingerprint
-
-@Patch(false)
-@Name("Permanent shuffle")
-@Description("Permanently remember your shuffle preference " +
- "even if the playlist ends or another track is played.")
-@MusicCompatibility
-class PermanentShuffleTogglePatch : BytecodePatch(
- listOf(DisableShuffleFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- DisableShuffleFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
- ?: throw DisableShuffleFingerprint.exception
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt
index bd2cec28a..ec67f2d68 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt
@@ -1,21 +1,22 @@
-package app.revanced.patches.music.layout.compactheader.patch
+package app.revanced.patches.music.layout.compactheader
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x
-@Patch(false)
-@Name("Compact header")
-@Description("Hides the music category bar at the top of the homepage.")
-@MusicCompatibility
-class CompactHeaderPatch : BytecodePatch(
- listOf(CompactHeaderConstructorFingerprint)
+@Patch(
+ name = "Compact header",
+ description = "Hides the music category bar at the top of the homepage.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
+ use = false
+)
+@Suppress("unused")
+object CompactHeaderPatch : BytecodePatch(
+ setOf(CompactHeaderConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
val result = CompactHeaderConstructorFingerprint.result!!
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt
new file mode 100644
index 000000000..f34ca7dec
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt
@@ -0,0 +1,26 @@
+package app.revanced.patches.music.layout.minimizedplayback
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
+
+
+@Patch(
+ name = "Minimized playback music",
+ description = "Enables minimized playback on Kids music.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object MinimizedPlaybackPatch : BytecodePatch(setOf(MinimizedPlaybackManagerFingerprint)) {
+ override fun execute(context: BytecodeContext) =
+ MinimizedPlaybackManagerFingerprint.result?.mutableMethod?.addInstruction(
+ 0,
+ """
+ return-void
+ """
+ ) ?: throw MinimizedPlaybackManagerFingerprint.exception
+}
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt
deleted file mode 100644
index a1f0197e2..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package app.revanced.patches.music.layout.minimizedplayback.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
-import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
-
-@Patch
-@Name("Minimized playback music")
-@Description("Enables minimized playback on Kids music.")
-@MusicCompatibility
-class MinimizedPlaybackPatch : BytecodePatch(
- listOf(MinimizedPlaybackManagerFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstruction(
- 0,
- """
- return-void
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt
index 5a9f09b9e..26680e1e3 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt
@@ -1,24 +1,22 @@
-package app.revanced.patches.music.layout.premium.patch
+package app.revanced.patches.music.layout.premium
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
-@Patch
-@Name("Hide get premium")
-@Description("Removes all \"Get Premium\" evidences from the avatar menu.")
-@MusicCompatibility
-class HideGetPremiumPatch : BytecodePatch(
- listOf(HideGetPremiumParentFingerprint)
-) {
+@Patch(
+ name = "Hide get premium",
+ description = "Removes all \"Get Premium\" evidences from the avatar menu.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object HideGetPremiumPatch : BytecodePatch(setOf(HideGetPremiumParentFingerprint)) {
override fun execute(context: BytecodeContext) {
val parentResult = HideGetPremiumParentFingerprint.result!!
HideGetPremiumFingerprint.resolve(context, parentResult.classDef)
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt
index 4a2f13c28..7cd39e17d 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt
@@ -1,13 +1,11 @@
-package app.revanced.patches.music.layout.upgradebutton.patch
+package app.revanced.patches.music.layout.upgradebutton
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.toInstructions
-import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t
@@ -15,12 +13,14 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
-@Patch
-@Name("Remove upgrade button")
-@Description("Removes the upgrade tab from the pivot bar.")
-@MusicCompatibility
-class RemoveUpgradeButtonPatch : BytecodePatch(
- listOf(PivotBarConstructorFingerprint)
+@Patch(
+ name = "Remove upgrade button",
+ description = "Removes the upgrade tab from the pivot bar.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object RemoveUpgradeButtonPatch : BytecodePatch(
+ setOf(PivotBarConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
val result = PivotBarConstructorFingerprint.result!!
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/androidauto/patch/BypassCertificateChecksPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/music/misc/androidauto/patch/BypassCertificateChecksPatch.kt
rename to src/main/kotlin/app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatch.kt
index aaf43598d..af54e3c2c 100644
--- a/src/main/kotlin/app/revanced/patches/music/misc/androidauto/patch/BypassCertificateChecksPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatch.kt
@@ -1,22 +1,21 @@
-package app.revanced.patches.music.misc.androidauto.patch
+package app.revanced.patches.music.misc.androidauto
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.misc.androidauto.fingerprints.CheckCertificateFingerprint
-@Patch
-@Name("Bypass certificate checks")
-@Description("Bypasses certificate checks which prevent YouTube Music from working on Android Auto.")
-@MusicCompatibility
-class BypassCertificateChecksPatch : BytecodePatch(
- listOf(CheckCertificateFingerprint)
-) {
+
+@Patch(
+ name = "Bypass certificate checks",
+ description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object BypassCertificateChecksPatch : BytecodePatch(setOf(CheckCertificateFingerprint)) {
override fun execute(context: BytecodeContext) {
CheckCertificateFingerprint.result?.apply {
mutableMethod.addInstructions(
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt
index e15d2b567..c1adb1e15 100644
--- a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt
@@ -1,26 +1,25 @@
-package app.revanced.patches.music.misc.microg.patch.bytecode
+package app.revanced.patches.music.misc.microg
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.misc.microg.fingerprints.*
-import app.revanced.patches.music.misc.microg.patch.resource.MicroGResourcePatch
import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants
import app.revanced.util.microg.MicroGBytecodeHelper
-@Patch
-@DependsOn([MicroGResourcePatch::class])
-@Name("Vanced MicroG support")
-@Description("Allows YouTube Music ReVanced to run without root and under a different package name.")
-@MusicCompatibility
-class MicroGBytecodePatch : BytecodePatch(
- listOf(
+
+@Patch(
+ name = "Vanced MicroG support",
+ description = "Allows YouTube Music to run without root and under a different package name.",
+ dependencies = [MicroGResourcePatch::class],
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object MicroGBytecodePatch : BytecodePatch(
+ setOf(
ServiceCheckFingerprint,
GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt
similarity index 78%
rename from src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MicroGResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt
index bbcfcf4a4..eb8daf5ae 100644
--- a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MicroGResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt
@@ -1,8 +1,8 @@
-package app.revanced.patches.music.misc.microg.patch.resource
+package app.revanced.patches.music.misc.microg
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_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
@@ -11,8 +11,12 @@ import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_S
import app.revanced.util.microg.MicroGManifestHelper
import app.revanced.util.microg.MicroGResourceHelper
-@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.")
-class MicroGResourcePatch : ResourcePatch {
+
+@Patch(
+ description = "Resource patch to allow YouTube Music ReVanced to run without root " +
+ "and under a different package name."
+)
+object MicroGResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
// update manifest
MicroGResourceHelper.patchManifest(
diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt
new file mode 100644
index 000000000..3af1deb02
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt
@@ -0,0 +1,26 @@
+package app.revanced.patches.music.premium.backgroundplay
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
+
+
+@Patch(
+ name = "Background play",
+ description = "Enables playing music in the background.",
+ compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
+)
+@Suppress("unused")
+object BackgroundPlayPatch : BytecodePatch(setOf(BackgroundPlaybackDisableFingerprint)) {
+ override fun execute(context: BytecodeContext) =
+ BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
+ 0, """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw BackgroundPlaybackDisableFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt
deleted file mode 100644
index 3c9fbc068..000000000
--- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package app.revanced.patches.music.premium.backgroundplay.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.annotations.MusicCompatibility
-import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
-
-@Patch
-@Name("Background play")
-@Description("Enables playing music in the background.")
-@MusicCompatibility
-class BackgroundPlayPatch : BytecodePatch(
- listOf(BackgroundPlaybackDisableFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- BackgroundPlaybackDisableFingerprint.result!!.mutableMethod.addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/UnlockProPatch.kt
new file mode 100644
index 000000000..c7a8e031c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/UnlockProPatch.kt
@@ -0,0 +1,25 @@
+package app.revanced.patches.myexpenses.misc.pro
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.myexpenses.misc.pro.fingerprints.IsEnabledFingerprint
+
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("org.totschnig.myexpenses", ["3.4.9"])]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(setOf(IsEnabledFingerprint)) {
+ override fun execute(context: BytecodeContext) = IsEnabledFingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw IsEnabledFingerprint.exception
+
+}
diff --git a/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index 8ab7f6adf..000000000
--- a/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.myexpenses.misc.pro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("org.totschnig.myexpenses", arrayOf("3.4.9"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/patch/UnlockProPatch.kt
deleted file mode 100644
index ad60a41d4..000000000
--- a/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/patch/UnlockProPatch.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package app.revanced.patches.myexpenses.misc.pro.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.myexpenses.misc.pro.annotations.UnlockProCompatibility
-import app.revanced.patches.myexpenses.misc.pro.fingerprints.IsEnabledFingerprint
-
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks all professional features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(
- IsEnabledFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- val method = IsEnabledFingerprint.result!!.mutableMethod
- method.addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/patch/RemoveBroadcastsRestrictionPatch.kt b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch.kt
similarity index 64%
rename from src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/patch/RemoveBroadcastsRestrictionPatch.kt
rename to src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch.kt
index 90f196a50..dc06778f2 100644
--- a/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/patch/RemoveBroadcastsRestrictionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch.kt
@@ -1,18 +1,20 @@
-package app.revanced.patches.netguard.broadcasts.removerestriction.resource.patch
+package app.revanced.patches.netguard.broadcasts.removerestriction
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.netguard.broadcasts.removerestriction.resource.annotations.RemoveBroadcastsRestrictionCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import org.w3c.dom.Element
-@Patch(false)
-@Name("Remove broadcasts restriction")
-@Description("Enables starting/stopping NetGuard via broadcasts.")
-@RemoveBroadcastsRestrictionCompatibility
-class RemoveBroadcastsRestrictionPatch : ResourcePatch {
+
+@Patch(
+ name = "Remove broadcasts restriction",
+ description = "Enables starting/stopping NetGuard via broadcasts.",
+ compatiblePackages = [CompatiblePackage("eu.faircode.netguard")],
+ use = false
+)
+@Suppress("unused")
+object RemoveBroadcastsRestrictionPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { dom ->
val applicationNode = dom
diff --git a/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/annotations/RemoveBroadcastsRestrictionCompatibility.kt b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/annotations/RemoveBroadcastsRestrictionCompatibility.kt
deleted file mode 100644
index 94bbbe9f5..000000000
--- a/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/annotations/RemoveBroadcastsRestrictionCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.netguard.broadcasts.removerestriction.resource.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("eu.faircode.netguard")])
-@Target(AnnotationTarget.CLASS)
-annotation class RemoveBroadcastsRestrictionCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt
new file mode 100644
index 000000000..3e8d17008
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt
@@ -0,0 +1,25 @@
+package app.revanced.patches.nfctoolsse.misc.pro
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.nfctoolsse.misc.pro.fingerprints.IsLicenseRegisteredFingerprint
+
+
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("com.wakdev.apps.nfctools.se")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(setOf(IsLicenseRegisteredFingerprint)) {
+ override fun execute(context: BytecodeContext) = IsLicenseRegisteredFingerprint.result?.mutableMethod
+ ?.addInstructions(
+ 0, """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw IsLicenseRegisteredFingerprint.exception
+}
diff --git a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index 0fdf6ac06..000000000
--- a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.nfctoolsse.misc.pro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.wakdev.apps.nfctools.se")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/patch/UnlockProPatch.kt
deleted file mode 100644
index ce45d1d37..000000000
--- a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/patch/UnlockProPatch.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package app.revanced.patches.nfctoolsse.misc.pro.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.nfctoolsse.misc.pro.annotations.UnlockProCompatibility
-import app.revanced.patches.nfctoolsse.misc.pro.fingerprints.IsLicenseRegisteredFingerprint
-
-
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks all pro features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(
- IsLicenseRegisteredFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- IsLicenseRegisteredFingerprint.result?.mutableMethod?.apply {
- addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- } ?: throw IsLicenseRegisteredFingerprint.exception
- }
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/UnlockProPatch.kt
new file mode 100644
index 000000000..8fcdf88ed
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/UnlockProPatch.kt
@@ -0,0 +1,24 @@
+package app.revanced.patches.nyx.misc.pro
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.nyx.misc.pro.fingerprints.CheckProFingerprint
+
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("com.awedea.nyx")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(setOf(CheckProFingerprint)) {
+ override fun execute(context: BytecodeContext) = CheckProFingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw CheckProFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index c8aef11cb..000000000
--- a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.nyx.misc.pro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.awedea.nyx")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt
deleted file mode 100644
index 130b53099..000000000
--- a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package app.revanced.patches.nyx.misc.pro.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.nyx.misc.pro.annotations.UnlockProCompatibility
-import app.revanced.patches.nyx.misc.pro.fingerprints.CheckProFingerprint
-
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks all pro features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(
- CheckProFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- val method = CheckProFingerprint.result!!.mutableMethod
- method.addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch.kt b/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch.kt
new file mode 100644
index 000000000..cd5d6196a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch.kt
@@ -0,0 +1,30 @@
+package app.revanced.patches.photomath.detection.deviceid
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.photomath.detection.deviceid.fingerprints.GetDeviceIdFingerprint
+import app.revanced.patches.photomath.detection.signature.SignatureDetectionPatch
+import kotlin.random.Random
+
+@Patch(
+ name = "Spoof device ID",
+ description = "Spoofs device ID to mitigate manual bans by developers.",
+ dependencies = [SignatureDetectionPatch::class],
+ compatiblePackages = [CompatiblePackage("com.microblink.photomath")]
+)
+@Suppress("unused")
+object SpoofDeviceIdPatch : BytecodePatch(
+ setOf(GetDeviceIdFingerprint)
+){
+ override fun execute(context: BytecodeContext) = GetDeviceIdFingerprint.result?.mutableMethod?.replaceInstructions(
+ 0,
+ """
+ const-string v0, "${Random.nextLong().toString(16)}"
+ return-object v0
+ """
+ ) ?: throw GetDeviceIdFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/patch/SpoofDeviceIdPatch.kt b/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/patch/SpoofDeviceIdPatch.kt
deleted file mode 100644
index a295c0bc7..000000000
--- a/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/patch/SpoofDeviceIdPatch.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package app.revanced.patches.photomath.detection.deviceid.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.photomath.detection.deviceid.fingerprints.GetDeviceIdFingerprint
-import app.revanced.patches.photomath.detection.signature.patch.SignatureDetectionPatch
-import kotlin.random.Random
-
-@Patch
-@DependsOn([SignatureDetectionPatch::class])
-@Name("Spoof device ID")
-@Description("Spoofs device ID to mitigate manual bans by developers.")
-@Compatibility([Package("com.microblink.photomath")])
-class SpoofDeviceIdPatch : BytecodePatch(
- listOf(GetDeviceIdFingerprint)
-) {
- override fun execute(context: BytecodeContext) = GetDeviceIdFingerprint.result?.mutableMethod?.replaceInstructions(
- 0,
- """
- const-string v0, "${Random.nextLong().toString(16)}"
- return-object v0
- """
- ) ?: throw GetDeviceIdFingerprint.exception
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/photomath/detection/signature/patch/SignatureDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt
similarity index 78%
rename from src/main/kotlin/app/revanced/patches/photomath/detection/signature/patch/SignatureDetectionPatch.kt
rename to src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt
index cab96846e..a322efac2 100644
--- a/src/main/kotlin/app/revanced/patches/photomath/detection/signature/patch/SignatureDetectionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt
@@ -1,19 +1,17 @@
-package app.revanced.patches.photomath.detection.signature.patch
+package app.revanced.patches.photomath.detection.signature
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.photomath.detection.signature.fingerprints.CheckSignatureFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Description("Disables detection of incorrect signature.")
-class SignatureDetectionPatch : BytecodePatch(
- listOf(
- CheckSignatureFingerprint
- )
+@Patch(description = "Disables detection of incorrect signature.")
+object SignatureDetectionPatch : BytecodePatch(
+ setOf(CheckSignatureFingerprint)
) {
override fun execute(context: BytecodeContext) {
CheckSignatureFingerprint.result?.apply {
diff --git a/src/main/kotlin/app/revanced/patches/photomath/misc/bookpoint/patch/EnableBookpointPatch.kt b/src/main/kotlin/app/revanced/patches/photomath/misc/bookpoint/EnableBookpointPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/photomath/misc/bookpoint/patch/EnableBookpointPatch.kt
rename to src/main/kotlin/app/revanced/patches/photomath/misc/bookpoint/EnableBookpointPatch.kt
index 0966f508a..0ce19ed10 100644
--- a/src/main/kotlin/app/revanced/patches/photomath/misc/bookpoint/patch/EnableBookpointPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/photomath/misc/bookpoint/EnableBookpointPatch.kt
@@ -1,14 +1,16 @@
-package app.revanced.patches.photomath.misc.bookpoint.patch
+package app.revanced.patches.photomath.misc.bookpoint
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.photomath.misc.bookpoint.fingerprints.IsBookpointEnabledFingerprint
-@Description("Enables textbook access")
-class EnableBookpointPatch : BytecodePatch(listOf(IsBookpointEnabledFingerprint)) {
+@Patch(description = "Enables textbook access")
+object EnableBookpointPatch : BytecodePatch(
+ setOf(IsBookpointEnabledFingerprint)
+) {
override fun execute(context: BytecodeContext) =
IsBookpointEnabledFingerprint.result?.mutableMethod?.replaceInstructions(
0,
diff --git a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/UnlockPlusPatch.kt b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/UnlockPlusPatch.kt
new file mode 100644
index 000000000..36970d422
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/UnlockPlusPatch.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.photomath.misc.unlockplus
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.photomath.detection.signature.SignatureDetectionPatch
+import app.revanced.patches.photomath.misc.bookpoint.EnableBookpointPatch
+import app.revanced.patches.photomath.misc.unlockplus.fingerprints.IsPlusUnlockedFingerprint
+
+@Patch(
+ name = "Unlock plus",
+ dependencies = [SignatureDetectionPatch::class, EnableBookpointPatch::class],
+ compatiblePackages = [CompatiblePackage("com.microblink.photomath")]
+)
+@Suppress("unused")
+object UnlockPlusPatch : BytecodePatch(
+ setOf(IsPlusUnlockedFingerprint)
+){
+ override fun execute(context: BytecodeContext) = IsPlusUnlockedFingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw IsPlusUnlockedFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/patch/UnlockPlusPatch.kt b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/patch/UnlockPlusPatch.kt
deleted file mode 100644
index 9b351aa41..000000000
--- a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/patch/UnlockPlusPatch.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package app.revanced.patches.photomath.misc.unlockplus.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.photomath.detection.signature.patch.SignatureDetectionPatch
-import app.revanced.patches.photomath.misc.bookpoint.patch.EnableBookpointPatch
-import app.revanced.patches.photomath.misc.unlockplus.fingerprints.IsPlusUnlockedFingerprint
-
-@Patch
-@Name("Unlock plus")
-@DependsOn([SignatureDetectionPatch::class, EnableBookpointPatch::class])
-@Compatibility([Package("com.microblink.photomath")])
-class UnlockPlusPatch : BytecodePatch(
- listOf(IsPlusUnlockedFingerprint)
-) {
- override fun execute(context: BytecodeContext) = IsPlusUnlockedFingerprint.result?.mutableMethod?.addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- ) ?: throw IsPlusUnlockedFingerprint.exception
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/pixiv/ads/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/pixiv/ads/HideAdsPatch.kt
new file mode 100644
index 000000000..f827e27c0
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/pixiv/ads/HideAdsPatch.kt
@@ -0,0 +1,28 @@
+package app.revanced.patches.pixiv.ads
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.pixiv.ads.fingerprints.IsNotPremiumFingerprint
+
+@Patch(
+ name = "Hide ads",
+ compatiblePackages = [CompatiblePackage("jp.pxv.android")]
+)
+@Suppress("unused")
+object HideAdsPatch : BytecodePatch(setOf(IsNotPremiumFingerprint)) {
+ // Always return false in the "isNotPremium" method which normally returns !this.accountManager.isPremium.
+ // However, this is not the method that controls the user's premium status.
+ // Instead, this method is used to determine whether ads should be shown.
+ override fun execute(context: BytecodeContext) =
+ IsNotPremiumFingerprint.result?.mutableClass?.virtualMethods?.first()?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x0
+ return v0
+ """
+ ) ?: throw IsNotPremiumFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/pixiv/ads/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/pixiv/ads/patch/HideAdsPatch.kt
deleted file mode 100644
index df9d3591f..000000000
--- a/src/main/kotlin/app/revanced/patches/pixiv/ads/patch/HideAdsPatch.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package app.revanced.patches.pixiv.ads.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.pixiv.ads.fingerprints.IsNotPremiumFingerprint
-
-@Patch
-@Name("Hide ads")
-@Description("Hides ads.")
-@Compatibility([Package("jp.pxv.android")])
-class HideAdsPatch : BytecodePatch(listOf(IsNotPremiumFingerprint)) {
- override fun execute(context: BytecodeContext) {
- // Always return false in the "isNotPremium" method which normally returns !this.accountManager.isPremium.
- // However, this is not the method that controls the user's premium status.
- // Instead, this method is used to determine whether ads should be shown.
- IsNotPremiumFingerprint.result?.mutableClass?.virtualMethods?.first()?.addInstructions(
- 0,
- """
- const/4 v0, 0x0
- return v0
- """
- ) ?: throw IsNotPremiumFingerprint.exception
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/banner/patch/HideBannerPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/banner/HideBannerPatch.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/reddit/ad/banner/patch/HideBannerPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/ad/banner/HideBannerPatch.kt
index e4fb8aa04..669d67b88 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/banner/patch/HideBannerPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/ad/banner/HideBannerPatch.kt
@@ -1,13 +1,13 @@
-package app.revanced.patches.reddit.ad.banner.patch
+package app.revanced.patches.reddit.ad.banner
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.Patch
+
+@Patch(description = "Hides banner ads from comments on subreddits.")
+object HideBannerPatch : ResourcePatch() {
+ private const val RESOURCE_FILE_PATH = "res/layout/merge_listheader_link_detail.xml"
-@Name("Hide subreddit banner")
-@Description("Hides banner ads from comments on subreddits.")
-class HideBannerPatch : ResourcePatch {
override fun execute(context: ResourceContext) {
context.xmlEditor[RESOURCE_FILE_PATH].use {
it.file.getElementsByTagName("merge").item(0).childNodes.apply {
@@ -29,9 +29,5 @@ class HideBannerPatch : ResourcePatch {
}
}
}
-
- private companion object {
- const val RESOURCE_FILE_PATH = "res/layout/merge_listheader_link_detail.xml"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/comments/HideCommentAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/comments/HideCommentAdsPatch.kt
new file mode 100644
index 000000000..cdfda6b46
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/ad/comments/HideCommentAdsPatch.kt
@@ -0,0 +1,22 @@
+package app.revanced.patches.reddit.ad.comments
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.ad.comments.fingerprints.HideCommentAdsFingerprint
+
+@Patch(description = "Removes ads in the comments.",)
+object HideCommentAdsPatch : BytecodePatch(
+ setOf(HideCommentAdsFingerprint)
+) {
+ // Returns a blank object instead of the comment ad.
+ override fun execute(context: BytecodeContext) = HideCommentAdsFingerprint.result?.mutableMethod?.addInstructions(
+ 0, """
+ new-instance v0, Ljava/lang/Object;
+ invoke-direct {v0}, Ljava/lang/Object;->()V
+ return-object v0
+ """
+ ) ?: throw HideCommentAdsFingerprint.exception
+}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/comments/patch/HideCommentAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/comments/patch/HideCommentAdsPatch.kt
deleted file mode 100644
index 372903e99..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/comments/patch/HideCommentAdsPatch.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package app.revanced.patches.reddit.ad.comments.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.reddit.ad.comments.fingerprints.HideCommentAdsFingerprint
-
-@Name("Hide comment ads")
-@Description("Removes all comment ads.")
-class HideCommentAdsPatch : BytecodePatch(
- listOf(HideCommentAdsFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- val method = HideCommentAdsFingerprint.result!!.mutableMethod
- // Returns a blank object instead of the comment ad.
- method.addInstructions(
- 0,
- """
- new-instance v0, Ljava/lang/Object;
- invoke-direct {v0}, Ljava/lang/Object;->()V
- return-object v0
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/HideAdsPatch.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/HideAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/ad/general/HideAdsPatch.kt
index 4ad465838..23a1c69ee 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/ad/general/HideAdsPatch.kt
@@ -1,17 +1,13 @@
-package app.revanced.patches.reddit.ad.general.patch
+package app.revanced.patches.reddit.ad.general
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
-import app.revanced.patches.reddit.ad.banner.patch.HideBannerPatch
-import app.revanced.patches.reddit.ad.comments.patch.HideCommentAdsPatch
-import app.revanced.patches.reddit.ad.general.annotations.HideAdsCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.ad.banner.HideBannerPatch
+import app.revanced.patches.reddit.ad.comments.HideCommentAdsPatch
import app.revanced.patches.reddit.ad.general.fingerprints.AdPostFingerprint
import app.revanced.patches.reddit.ad.general.fingerprints.NewAdPostFingerprint
import com.android.tools.smali.dexlib2.Opcode
@@ -20,15 +16,19 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-@Patch
-@Name("Hide ads")
-@Description("Removes ads from the Reddit.")
-@DependsOn([HideBannerPatch::class, HideCommentAdsPatch::class])
-@HideAdsCompatibility
-@RequiresIntegrations
-class HideAdsPatch : BytecodePatch(
- listOf(AdPostFingerprint, NewAdPostFingerprint)
-) {
+
+@Patch(
+ name = "Hide ads",
+ dependencies = [HideBannerPatch::class, HideCommentAdsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.reddit.frontpage")],
+ requiresIntegrations = true,
+)
+@Suppress("unused")
+object HideAdsPatch : BytecodePatch(setOf(AdPostFingerprint, NewAdPostFingerprint)) {
+ private const val FILTER_METHOD_DESCRIPTOR =
+ "Lapp/revanced/reddit/patches/FilterPromotedLinksPatch;" +
+ "->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;"
+
override fun execute(context: BytecodeContext) {
// region Filter promoted ads (does not work in popular or latest feed)
@@ -77,10 +77,4 @@ class HideAdsPatch : BytecodePatch(
// endregion
}
-
- private companion object {
- private const val FILTER_METHOD_DESCRIPTOR =
- "Lapp/revanced/reddit/patches/FilterPromotedLinksPatch;" +
- "->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/HideAdsCompatibility.kt
deleted file mode 100644
index cc9230c57..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/HideAdsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.reddit.ad.general.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.reddit.frontpage")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractSpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractSpoofClientPatch.kt
index 3121dcb13..1f7ead84e 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractSpoofClientPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractSpoofClientPatch.kt
@@ -6,43 +6,85 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.OptionsContainer
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.PatchOption
+import app.revanced.patcher.patch.options.PatchOptionException
+import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
import java.io.File
+import java.util.*
abstract class AbstractSpoofClientPatch(
private val redirectUri: String,
- private val options: SpoofClientOptionsContainer,
private val clientIdFingerprints: List,
private val userAgentFingerprints: List? = null,
-) : BytecodePatch(buildList {
+ private val miscellaneousFingerprints: List? = null
+) : BytecodePatch(buildSet {
addAll(clientIdFingerprints)
userAgentFingerprints?.let(::addAll)
+ miscellaneousFingerprints?.let(::addAll)
}) {
+ var clientId by stringPatchOption(
+ "client-id",
+ null,
+ "OAuth client ID",
+ "The Reddit OAuth client ID. " +
+ "You can get your client ID from https://www.reddit.com/prefs/apps. " +
+ "The application type has to be \"Installed app\" " +
+ "and the redirect URI has to be set to \"$redirectUri\".",
+ true
+ )
+
override fun execute(context: BytecodeContext) {
- if (options.clientId == null) {
- // Ensure device runs Android.
- try {
- Class.forName("android.os.Environment")
- } catch (e: ClassNotFoundException) {
- throw PatchException("No client ID provided")
+ val requiredOptions = options.values.filter { it.required }
+
+ val isAndroidButRequiredOptionsUnset = try {
+ Class.forName("android.os.Environment")
+
+ requiredOptions.any { it.value == null }
+ } catch (_: ClassNotFoundException) {
+ false
+ }
+
+ if (isAndroidButRequiredOptionsUnset) {
+ val properties = Properties()
+
+ val propertiesFile = File(
+ Environment.getExternalStorageDirectory(),
+ "revanced_client_spoof_${redirectUri.hashCode()}.properties"
+ )
+ if (propertiesFile.exists()) {
+ properties.load(propertiesFile.inputStream())
+
+ // Set options from properties file.
+ properties.forEach { (name, value) ->
+ try {
+ options[name.toString()] = value.toString().trim()
+ } catch (_: PatchOptionException.PatchOptionNotFoundException) {
+ // Ignore unknown options.
+ }
+ }
+ } else {
+ options.keys.forEach { properties.setProperty(it, "") }
+
+ properties.store(
+ propertiesFile.outputStream(),
+ "Options for the ReVanced \"Client Spoof\" patch. Required options: " +
+ requiredOptions.joinToString { it.key }
+ )
}
- File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also {
- if (it.exists()) return@also
+ requiredOptions.filter { it.value == null }.let { requiredUnsetOptions ->
+ if (requiredUnsetOptions.isEmpty()) return@let
val error = """
- In order to use this patch, you need to provide a client ID.
- You can do that by creating a file at ${it.absolutePath} with the client ID as its content.
- Alternatively, you can provide the client ID using patch options.
-
- You can get your client ID from https://www.reddit.com/prefs/apps.
- The application type has to be "Installed app" and the redirect URI has to be set to "$redirectUri".
+ In order to use this patch, you need to provide the following options:
+ ${requiredUnsetOptions.joinToString("\n") { "${it.key}: ${it.description}" }}
+
+ A properties file has been created at ${propertiesFile.absolutePath}.
+ Please fill in the required options before using this patch.
""".trimIndent()
throw PatchException(error)
- }.let { options.clientId = it.readText().trim() }
+ }
}
fun List?.executePatch(
@@ -51,10 +93,12 @@ abstract class AbstractSpoofClientPatch(
clientIdFingerprints.executePatch { patchClientId(context) }
userAgentFingerprints.executePatch { patchUserAgent(context) }
+ miscellaneousFingerprints.executePatch { patchMiscellaneous(context) }
}
/**
- * Patch the client ID. The fingerprints are guaranteed to be in the same order as in [clientIdFingerprints].
+ * Patch the client ID.
+ * The fingerprints are guaranteed to be in the same order as in [clientIdFingerprints].
*
* @param context The current [BytecodeContext].
*
@@ -62,23 +106,20 @@ abstract class AbstractSpoofClientPatch(
abstract fun List.patchClientId(context: BytecodeContext)
/**
- * Patch the user agent. The fingerprints are guaranteed to be in the same order as in [userAgentFingerprints].
+ * Patch the user agent.
+ * The fingerprints are guaranteed to be in the same order as in [userAgentFingerprints].
*
* @param context The current [BytecodeContext].
*/
// Not every client needs to patch the user agent.
open fun List.patchUserAgent(context: BytecodeContext) {}
- companion object Options {
- open class SpoofClientOptionsContainer : OptionsContainer() {
- var clientId by option(
- PatchOption.StringOption(
- "client-id",
- null,
- "OAuth client ID",
- "The Reddit OAuth client ID."
- )
- )
- }
- }
+ /**
+ * Patch miscellaneous things such as protection measures.
+ * The fingerprints are guaranteed to be in the same order as in [miscellaneousFingerprints].
+ *
+ * @param context The current [BytecodeContext].
+ */
+ // Not every client needs to patch miscellaneous things.
+ open fun List.patchMiscellaneous(context: BytecodeContext) {}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientAnnotation.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientAnnotation.kt
deleted file mode 100644
index 9aede0fe1..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientAnnotation.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.reddit.customclients
-
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.Patch
-
-@Target(AnnotationTarget.CLASS)
-@Patch
-@Name("Spoof client")
-annotation class SpoofClientAnnotation
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/patch/SpoofClientPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt
index 18f2a9539..e85019073 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/patch/SpoofClientPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt
@@ -1,33 +1,29 @@
-package app.revanced.patches.reddit.customclients.baconreader.api.patch
+package app.revanced.patches.reddit.customclients.baconreader.api
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
import app.revanced.patches.reddit.customclients.baconreader.api.fingerprints.GetAuthorizationUrlFingerprint
import app.revanced.patches.reddit.customclients.baconreader.api.fingerprints.RequestTokenFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"http://baconreader.com/auth\".")
-@Compatibility(
- [
- Package("com.onelouder.baconreader"),
- Package("com.onelouder.baconreader.premium")
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ compatiblePackages = [
+ CompatiblePackage("com.onelouder.baconreader"),
+ CompatiblePackage("com.onelouder.baconreader.premium")
]
)
-class SpoofClientPatch : AbstractSpoofClientPatch(
- "http://baconreader.com/auth", Options, listOf(GetAuthorizationUrlFingerprint, RequestTokenFingerprint)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
+ "http://baconreader.com/auth", listOf(GetAuthorizationUrlFingerprint, RequestTokenFingerprint)
) {
-
override fun List.patchClientId(context: BytecodeContext) {
fun MethodFingerprintResult.patch(replacementString: String) {
val clientIdIndex = scanResult.stringsScanResult!!.matches.first().index
@@ -47,6 +43,4 @@ class SpoofClientPatch : AbstractSpoofClientPatch(
// Patch client id for access token request.
last().patch(clientId!!)
}
-
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch.kt
new file mode 100644
index 000000000..137cb137a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.reddit.customclients.boostforreddit.api
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
+import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
+
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ compatiblePackages = [CompatiblePackage("com.rubenmayayo.reddit")]
+)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
+ "http://rubenmayayo.com", listOf(GetClientIdFingerprint)
+) {
+ override fun List.patchClientId(context: BytecodeContext) {
+ first().mutableMethod.addInstructions(
+ 0,
+ """
+ const-string v0, "$clientId"
+ return-object v0
+ """
+ )
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/SpoofClientPatch.kt
deleted file mode 100644
index 52bef8513..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/SpoofClientPatch.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package app.revanced.patches.reddit.customclients.boostforreddit.api.patch
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
-import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
-
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"http://rubenmayayo.com\".")
-@Compatibility([Package("com.rubenmayayo.reddit")])
-class SpoofClientPatch : AbstractSpoofClientPatch(
- "http://rubenmayayo.com", Options, listOf(GetClientIdFingerprint)
-) {
- override fun List.patchClientId(context: BytecodeContext) {
- first().mutableMethod.addInstructions(
- 0,
- """
- const-string v0, "$clientId"
- return-object v0
- """
- )
- }
-
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
-}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/patch/SpoofClientPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch.kt
index 646afb11e..5a2a7e968 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/patch/SpoofClientPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch.kt
@@ -1,26 +1,37 @@
-package app.revanced.patches.reddit.customclients.infinityforreddit.api.patch
+package app.revanced.patches.reddit.customclients.infinityforreddit.api
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.GetHttpBasicAuthHeaderFingerprint
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.LoginActivityOnCreateFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"infinity://localhost\".")
-@Compatibility([Package("ml.docilealligator.infinityforreddit")])
-class SpoofClientPatch : AbstractSpoofClientPatch(
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ compatiblePackages = [
+ CompatiblePackage(
+ "ml.docilealligator.infinityforreddit", [
+ "5.4.0",
+ "5.4.1",
+ "5.4.2",
+ "6.0.1",
+ "6.0.2",
+ "6.0.4",
+ "6.0.6",
+ "6.1.1"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
"infinity://localhost",
- Options,
listOf(GetHttpBasicAuthHeaderFingerprint, LoginActivityOnCreateFingerprint)
) {
override fun List.patchClientId(context: BytecodeContext) {
@@ -37,6 +48,4 @@ class SpoofClientPatch : AbstractSpoofClientPatch(
}
}
}
-
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/patch/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/DisableAdsPatch.kt
similarity index 60%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/patch/DisableAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/DisableAdsPatch.kt
index ca3de93e2..b1ae51375 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/patch/DisableAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/DisableAdsPatch.kt
@@ -1,22 +1,21 @@
-package app.revanced.patches.reddit.customclients.joeyforreddit.ads.patch
+package app.revanced.patches.reddit.customclients.joeyforreddit.ads
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.joeyforreddit.ads.fingerprints.IsAdFreeUserFingerprint
-import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
+import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.DisablePiracyDetectionPatch
-@Patch
-@Name("Disable ads")
-@DependsOn([DisablePiracyDetectionPatch::class])
-@Compatibility([Package("o.o.joey")])
-class DisableAdsPatch : BytecodePatch(listOf(IsAdFreeUserFingerprint)) {
+@Patch(
+ name = "Disable ads",
+ dependencies = [DisablePiracyDetectionPatch::class],
+ compatiblePackages = [CompatiblePackage("o.o.joey")]
+)
+@Suppress("unused")
+object DisableAdsPatch : BytecodePatch(setOf(IsAdFreeUserFingerprint)) {
override fun execute(context: BytecodeContext) {
IsAdFreeUserFingerprint.result?.mutableMethod?.addInstructions(
0,
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch.kt
new file mode 100644
index 000000000..29ab8a71d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch.kt
@@ -0,0 +1,36 @@
+package app.revanced.patches.reddit.customclients.joeyforreddit.api
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
+import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.GetClientIdFingerprint
+import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.DisablePiracyDetectionPatch
+
+
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ dependencies = [DisablePiracyDetectionPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("o.o.joey"),
+ CompatiblePackage("o.o.joey.pro"),
+ CompatiblePackage("o.o.joey.dev")
+ ]
+)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
+ "https://127.0.0.1:65023/authorize_callback", listOf(GetClientIdFingerprint)
+) {
+ override fun List.patchClientId(context: BytecodeContext) {
+ first().mutableMethod.addInstructions(
+ 0,
+ """
+ const-string v0, "$clientId"
+ return-object v0
+ """
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/patch/SpoofClientPatch.kt
deleted file mode 100644
index a147e0e1e..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/patch/SpoofClientPatch.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package app.revanced.patches.reddit.customclients.joeyforreddit.api.patch
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
-import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.GetClientIdFingerprint
-import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
-
-@SpoofClientAnnotation
-@Description(
- "Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"https://127.0.0.1:65023/authorize_callback\"."
-)
-@Compatibility(
- [
- Package("o.o.joey"),
- Package("o.o.joey.pro"),
- Package("o.o.joey.dev")
- ]
-)
-@DependsOn([DisablePiracyDetectionPatch::class])
-class SpoofClientPatch : AbstractSpoofClientPatch(
- "https://127.0.0.1:65023/authorize_callback", Options, listOf(GetClientIdFingerprint)
-) {
- override fun List.patchClientId(context: BytecodeContext) {
- first().mutableMethod.addInstructions(
- 0,
- """
- const-string v0, "$clientId"
- return-object v0
- """
- )
- }
-
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/DisablePiracyDetectionPatch.kt
similarity index 88%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/DisablePiracyDetectionPatch.kt
index 360fa7d79..b03b2a838 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/DisablePiracyDetectionPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.patch
+package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
@@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
-class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerprint)) {
+object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
override fun execute(context: BytecodeContext) {
PiracyDetectionFingerprint.result?.mutableMethod?.addInstruction(
0,
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/SpoofClientPatch.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/patch/SpoofClientPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/SpoofClientPatch.kt
index 386c5da6e..026870b20 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/patch/SpoofClientPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/SpoofClientPatch.kt
@@ -1,29 +1,30 @@
-package app.revanced.patches.reddit.customclients.redditisfun.api.patch
+package app.revanced.patches.reddit.customclients.redditisfun.api
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult.StringMatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.BasicAuthorizationFingerprint
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.BuildAuthorizationStringFingerprint
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.GetUserAgentFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"redditisfun://auth\".")
-@Compatibility([Package("com.andrewshu.android.reddit"), Package("com.andrewshu.android.redditdonation")])
-class SpoofClientPatch : AbstractSpoofClientPatch(
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ compatiblePackages = [
+ CompatiblePackage("com.andrewshu.android.reddit"),
+ CompatiblePackage("com.andrewshu.android.redditdonation")
+ ]
+)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
"redditisfun://auth",
- Options,
listOf(BuildAuthorizationStringFingerprint, BasicAuthorizationFingerprint),
listOf(GetUserAgentFingerprint)
) {
@@ -66,6 +67,4 @@ class SpoofClientPatch : AbstractSpoofClientPatch(
"""
)
}
-
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/patch/SpoofClientPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt
index f4f6869ea..690e17861 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/patch/SpoofClientPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt
@@ -1,34 +1,34 @@
-package app.revanced.patches.reddit.customclients.relayforreddit.api.patch
+package app.revanced.patches.reddit.customclients.relayforreddit.api
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
-import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.GetLoggedInBearerTokenFingerprint
-import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.GetLoggedOutBearerTokenFingerprint
-import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.GetRefreshTokenFingerprint
-import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.LoginActivityClientIdFingerprint
+import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.*
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"dbrady://relay\".")
-@Compatibility([Package("free.reddit.news"), Package("reddit.news")])
-class SpoofClientPatch : AbstractSpoofClientPatch(
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ compatiblePackages = [
+ CompatiblePackage("free.reddit.news"),
+ CompatiblePackage("reddit.news")
+ ]
+)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
"dbrady://relay",
- Options,
listOf(
LoginActivityClientIdFingerprint,
GetLoggedInBearerTokenFingerprint,
GetLoggedOutBearerTokenFingerprint,
GetRefreshTokenFingerprint
- )
+ ),
+ miscellaneousFingerprints = listOf(SetRemoteConfigFingerprint)
) {
override fun List.patchClientId(context: BytecodeContext) {
forEach {
@@ -44,5 +44,7 @@ class SpoofClientPatch : AbstractSpoofClientPatch(
}
}
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
+ override fun List.patchMiscellaneous(context: BytecodeContext) =
+ // Do not load remote config which disables OAuth login remotely
+ first().mutableMethod.addInstructions(0, "return-void")
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/fingerprints/SetRemoteConfigFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/fingerprints/SetRemoteConfigFingerprint.kt
new file mode 100644
index 000000000..caba6282c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/fingerprints/SetRemoteConfigFingerprint.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object SetRemoteConfigFingerprint : MethodFingerprint(
+ strings = listOf("reddit_oauth_url"),
+ parameters = listOf("Lcom/google/firebase/remoteconfig/FirebaseRemoteConfig;")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/SpoofClientPatch.kt
new file mode 100644
index 000000000..88c85abf7
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/SpoofClientPatch.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.reddit.customclients.slide.api
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
+import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
+
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ compatiblePackages = [CompatiblePackage("me.ccrama.redditslide")]
+)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
+ "http://www.ccrama.me", listOf(GetClientIdFingerprint)
+) {
+ override fun List.patchClientId(context: BytecodeContext) {
+ first().mutableMethod.addInstructions(
+ 0,
+ """
+ const-string v0, "$clientId"
+ return-object v0
+ """
+ )
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/patch/SpoofClientPatch.kt
deleted file mode 100644
index 5c187cb25..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/patch/SpoofClientPatch.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package app.revanced.patches.reddit.customclients.slide.api.patch
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
-import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
-
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"http://www.ccrama.me\".")
-@Compatibility([Package("me.ccrama.redditslide")])
-class SpoofClientPatch : AbstractSpoofClientPatch(
- "http://www.ccrama.me", Options, listOf(GetClientIdFingerprint)
-) {
- override fun List.patchClientId(context: BytecodeContext) {
- first().mutableMethod.addInstructions(
- 0,
- """
- const-string v0, "$clientId"
- return-object v0
- """
- )
- }
-
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
-}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt
index 91460a420..43bad8f97 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt
@@ -1,20 +1,21 @@
-package app.revanced.patches.reddit.customclients.syncforreddit.ads.patch
+package app.revanced.patches.reddit.customclients.syncforreddit.ads
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
-import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
+import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
-@Patch
-@Name("Disable ads")
-@DependsOn([DisablePiracyDetectionPatch::class])
-@Compatibility([Package("com.laurencedawson.reddit_sync")])
-class DisableAdsPatch : BytecodePatch(listOf(IsAdsEnabledFingerprint)) {
+@Patch(
+ name = "Disable ads",
+ dependencies = [DisablePiracyDetectionPatch::class],
+ compatiblePackages = [CompatiblePackage("com.laurencedawson.reddit_sync")]
+)
+@Suppress("unused")
+object DisableAdsPatch : BytecodePatch(setOf(IsAdsEnabledFingerprint)) {
override fun execute(context: BytecodeContext) {
IsAdsEnabledFingerprint.result?.mutableMethod?.apply {
addInstructions(
@@ -26,5 +27,4 @@ class DisableAdsPatch : BytecodePatch(listOf(IsAdsEnabledFingerprint)) {
)
} ?: throw IsAdsEnabledFingerprint.exception
}
-
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/DisableSyncForLemmyBottomSheetPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/DisableSyncForLemmyBottomSheetPatch.kt
new file mode 100644
index 000000000..7f4ac4afc
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/DisableSyncForLemmyBottomSheetPatch.kt
@@ -0,0 +1,30 @@
+package app.revanced.patches.reddit.customclients.syncforreddit.annoyances.startup
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.customclients.syncforreddit.annoyances.startup.fingerprints.MainActivityOnCreate
+
+
+@Patch(
+ name = "Disable Sync for Lemmy bottom sheet",
+ description = "Disables the bottom sheet at the startup that asks you to signup to \"Sync for Lemmy\".",
+ compatiblePackages = [
+ CompatiblePackage("com.laurencedawson.reddit_sync", ["v23.06.30-13:39"]),
+ CompatiblePackage("com.laurencedawson.reddit_sync.pro"), // Version unknown.
+ CompatiblePackage("com.laurencedawson.reddit_sync.dev") // Version unknown.
+ ]
+)
+@Suppress("unused")
+object DisableSyncForLemmyBottomSheetPatch : BytecodePatch(setOf(MainActivityOnCreate)) {
+ override fun execute(context: BytecodeContext) {
+ MainActivityOnCreate.result?.mutableMethod?.apply {
+ val showBottomSheetIndex = implementation!!.instructions.lastIndex - 1
+
+ removeInstruction(showBottomSheetIndex)
+ } ?: throw MainActivityOnCreate.exception
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/patch/DisableSyncForLemmyBottomSheetPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/patch/DisableSyncForLemmyBottomSheetPatch.kt
deleted file mode 100644
index 41bc706bd..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/patch/DisableSyncForLemmyBottomSheetPatch.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package app.revanced.patches.reddit.customclients.syncforreddit.annoyances.startup.patch
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.reddit.customclients.syncforreddit.annoyances.startup.fingerprints.MainActivityOnCreate
-
-@Patch
-@Name("Disable Sync for Lemmy bottom sheet")
-@Description("Disables the bottom sheet at the startup that asks you to signup to \"Sync for Lemmy\".")
-@Compatibility(
- [
- Package("com.laurencedawson.reddit_sync", ["v23.06.30-13:39"]),
- Package("com.laurencedawson.reddit_sync.pro"), // Version unknown.
- Package("com.laurencedawson.reddit_sync.dev") // Version unknown.
- ]
-)
-class DisableSyncForLemmyBottomSheetPatch : BytecodePatch(listOf(MainActivityOnCreate)) {
- override fun execute(context: BytecodeContext) {
- MainActivityOnCreate.result?.mutableMethod?.apply {
- val showBottomSheetIndex = implementation!!.instructions.lastIndex - 1
-
- removeInstruction(showBottomSheetIndex)
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/SpoofClientPatch.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/SpoofClientPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/SpoofClientPatch.kt
index 7c329de37..9e91dcc6c 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/SpoofClientPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/SpoofClientPatch.kt
@@ -1,40 +1,39 @@
-package app.revanced.patches.reddit.customclients.syncforreddit.api.patch
+package app.revanced.patches.reddit.customclients.syncforreddit.api
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
-import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
-import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
+import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.ImgurImageAPIFingerprint
+import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import java.util.*
-@SpoofClientAnnotation
-@Description("Spoofs the client in order to allow logging in. " +
- "The OAuth application type has to be \"Installed app\" " +
- "and the redirect URI has to be set to \"http://redditsync/auth\".")
-@Compatibility(
- [
- Package("com.laurencedawson.reddit_sync"),
- Package("com.laurencedawson.reddit_sync.pro"),
- Package("com.laurencedawson.reddit_sync.dev")
+@Patch(
+ name = "Spoof client",
+ description = "Restores functionality of the app by using custom client ID's.",
+ dependencies = [DisablePiracyDetectionPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.laurencedawson.reddit_sync"),
+ CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
+ CompatiblePackage("com.laurencedawson.reddit_sync.dev")
]
)
-@DependsOn([DisablePiracyDetectionPatch::class])
-class SpoofClientPatch : AbstractSpoofClientPatch(
- "http://redditsync/auth", Options, listOf(GetAuthorizationStringFingerprint)
+@Suppress("unused")
+object SpoofClientPatch : AbstractSpoofClientPatch(
+ "http://redditsync/auth",
+ clientIdFingerprints = listOf(GetAuthorizationStringFingerprint),
+ miscellaneousFingerprints = listOf(ImgurImageAPIFingerprint)
) {
override fun List.patchClientId(context: BytecodeContext) {
forEach { fingerprintResult ->
@@ -71,5 +70,13 @@ class SpoofClientPatch : AbstractSpoofClientPatch(
}
}
- companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
+ // Use the non-commercial Imgur API endpoint.
+ override fun List.patchMiscellaneous(context: BytecodeContext) = first().let {
+ val apiUrlIndex = it.scanResult.stringsScanResult!!.matches.first().index
+
+ it.mutableMethod.replaceInstruction(
+ apiUrlIndex,
+ "const-string v1, \"https://api.imgur.com/3/image\""
+ )
+ }
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/ImgurImageAPIFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/ImgurImageAPIFingerprint.kt
new file mode 100644
index 000000000..5dc5b5ed8
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/ImgurImageAPIFingerprint.kt
@@ -0,0 +1,9 @@
+package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object ImgurImageAPIFingerprint : MethodFingerprint(
+ strings = listOf(
+ "https://imgur-apiv3.p.rapidapi.com/3/image",
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/DisablePiracyDetectionPatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/DisablePiracyDetectionPatch.kt
index 5ce7fb0bf..e075ee69c 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/DisablePiracyDetectionPatch.kt
@@ -1,15 +1,15 @@
-package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch
+package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
-@Description("Disables detection of modified versions.")
-class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerprint)) {
+@Patch(description = "Disables detection of modified versions.",)
+object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
override fun execute(context: BytecodeContext) {
- // Do not return an error if the fingerprint is not resolved.
+ // Do not throw an error if the fingerprint is not resolved.
// This is fine because new versions of the target app do not need this patch.
PiracyDetectionFingerprint.result?.mutableMethod?.apply {
addInstruction(
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/patch/DisableScreenshotPopupPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/patch/DisableScreenshotPopupPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch.kt
index f59c02078..404a0f854 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/patch/DisableScreenshotPopupPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch.kt
@@ -1,22 +1,20 @@
-package app.revanced.patches.reddit.layout.disablescreenshotpopup.patch
+package app.revanced.patches.reddit.layout.disablescreenshotpopup
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.reddit.layout.disablescreenshotpopup.annotations.DisableScreenshotPopupCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.layout.disablescreenshotpopup.fingerprints.DisableScreenshotPopupFingerprint
-@Patch
-@Name("Disable screenshot popup")
-@Description("Disables the popup that shows up when taking a screenshot.")
-@DisableScreenshotPopupCompatibility
-class DisableScreenshotPopupPatch : BytecodePatch(
- listOf(DisableScreenshotPopupFingerprint)
-) {
+@Patch(
+ name = "Disable screenshot popup",
+ description = "Disables the popup that shows up when taking a screenshot.",
+ compatiblePackages = [CompatiblePackage("com.reddit.frontpage")]
+)
+@Suppress("unused")
+object DisableScreenshotPopupPatch : BytecodePatch(setOf(DisableScreenshotPopupFingerprint)) {
override fun execute(context: BytecodeContext) {
DisableScreenshotPopupFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
?: throw DisableScreenshotPopupFingerprint.exception
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/annotations/DisableScreenshotPopupCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/annotations/DisableScreenshotPopupCompatibility.kt
deleted file mode 100644
index d0620b564..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/annotations/DisableScreenshotPopupCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.reddit.layout.disablescreenshotpopup.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.reddit.frontpage")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DisableScreenshotPopupCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt
new file mode 100644
index 000000000..2ee20c638
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt
@@ -0,0 +1,27 @@
+package app.revanced.patches.reddit.layout.premiumicon
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.reddit.layout.premiumicon.fingerprints.HasPremiumIconAccessFingerprint
+
+
+@Patch(
+ name = "Unlock premium Reddit icons",
+ compatiblePackages = [CompatiblePackage("com.reddit.frontpage")]
+)
+@Suppress("unused")
+object UnlockPremiumIconPatch : BytecodePatch(setOf(HasPremiumIconAccessFingerprint)) {
+ override fun execute(context: BytecodeContext) {
+ HasPremiumIconAccessFingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ ) ?: throw HasPremiumIconAccessFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt
deleted file mode 100644
index 079d5f6ca..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.reddit.layout.premiumicon.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.reddit.frontpage")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PremiumIconCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/HasPremiumIconAccessFingerprint.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/HasPremiumIconAccessFingerprint.kt
index c406791ed..1adeec614 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/HasPremiumIconAccessFingerprint.kt
@@ -2,7 +2,7 @@ package app.revanced.patches.reddit.layout.premiumicon.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-object PremiumIconFingerprint : MethodFingerprint(
+object HasPremiumIconAccessFingerprint : MethodFingerprint(
"Z",
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("MyAccount;") && methodDef.name == "isPremiumSubscriber"
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt
deleted file mode 100644
index 6f4c62a1c..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package app.revanced.patches.reddit.layout.premiumicon.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.reddit.layout.premiumicon.annotations.PremiumIconCompatibility
-import app.revanced.patches.reddit.layout.premiumicon.fingerprints.PremiumIconFingerprint
-
-@Patch
-@Name("Premium icon reddit")
-@Description("Unlocks premium Reddit app icons.")
-@PremiumIconCompatibility
-class PremiumIconPatch : BytecodePatch(
- listOf(
- PremiumIconFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- val method = PremiumIconFingerprint.result!!.mutableMethod
- method.addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/patch/SanitizeUrlQueryPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/SanitizeUrlQueryPatch.kt
similarity index 50%
rename from src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/patch/SanitizeUrlQueryPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/SanitizeUrlQueryPatch.kt
index 94404f078..5043bebad 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/patch/SanitizeUrlQueryPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/SanitizeUrlQueryPatch.kt
@@ -1,22 +1,21 @@
-package app.revanced.patches.reddit.misc.tracking.url.patch
+package app.revanced.patches.reddit.misc.tracking.url
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.reddit.misc.tracking.url.annotations.SanitizeUrlQueryCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.misc.tracking.url.fingerprints.ShareLinkFormatterFingerprint
-@Patch
-@Name("Sanitize sharing links")
-@Description("Removes (tracking) query parameters from the URLs when sharing links.")
-@SanitizeUrlQueryCompatibility
-class SanitizeUrlQueryPatch : BytecodePatch(
- listOf(ShareLinkFormatterFingerprint)
-) {
+
+@Patch(
+ name = "Sanitize sharing links",
+ description = "Removes (tracking) query parameters from the URLs when sharing links.",
+ compatiblePackages = [CompatiblePackage("com.reddit.frontpage")]
+)
+@Suppress("unused")
+object SanitizeUrlQueryPatch : BytecodePatch(setOf(ShareLinkFormatterFingerprint)) {
override fun execute(context: BytecodeContext) {
ShareLinkFormatterFingerprint.result?.mutableMethod?.addInstructions(
@@ -24,5 +23,4 @@ class SanitizeUrlQueryPatch : BytecodePatch(
"return-object p0"
) ?: throw ShareLinkFormatterFingerprint.exception
}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/annotations/SanitizeUrlQueryCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/annotations/SanitizeUrlQueryCompatibility.kt
deleted file mode 100644
index 6ba4a8902..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/annotations/SanitizeUrlQueryCompatibility.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package app.revanced.patches.reddit.misc.tracking.url.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.reddit.frontpage"
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class SanitizeUrlQueryCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/RemoveDebuggingDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/RemoveDebuggingDetectionPatch.kt
new file mode 100644
index 000000000..8edec2f80
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/RemoveDebuggingDetectionPatch.kt
@@ -0,0 +1,30 @@
+package app.revanced.patches.scbeasy.detection.debugging
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.scbeasy.detection.debugging.fingerprints.DebuggingDetectionFingerprint
+
+@Patch(
+ use = false,
+ name = "Remove debugging detection",
+ description = "Removes the USB and wireless debugging checks.",
+ compatiblePackages = [CompatiblePackage("com.scb.phone")]
+)
+@Suppress("unused")
+object RemoveDebuggingDetectionPatch : BytecodePatch(
+ setOf(DebuggingDetectionFingerprint)
+) {
+ override fun execute(context: BytecodeContext) {
+ DebuggingDetectionFingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x0
+ return v0
+ """
+ ) ?: throw DebuggingDetectionFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/annotations/RemoveDebuggingDetectionCompatibility.kt b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/annotations/RemoveDebuggingDetectionCompatibility.kt
deleted file mode 100644
index 095abdaa3..000000000
--- a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/annotations/RemoveDebuggingDetectionCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.scbeasy.detection.debugging.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.scb.phone")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class RemoveDebuggingDetectionCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/patch/RemoveDebuggingDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/patch/RemoveDebuggingDetectionPatch.kt
deleted file mode 100644
index 387caf2d2..000000000
--- a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/patch/RemoveDebuggingDetectionPatch.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package app.revanced.patches.scbeasy.detection.debugging.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.scbeasy.detection.debugging.annotations.RemoveDebuggingDetectionCompatibility
-import app.revanced.patches.scbeasy.detection.debugging.fingerprints.DebuggingDetectionFingerprint
-
-@Patch(false)
-@Name("Remove debugging detection")
-@Description("Removes the USB and wireless debugging checks.")
-@RemoveDebuggingDetectionCompatibility
-class RemoveDebuggingDetectionPatch : BytecodePatch(
- listOf(DebuggingDetectionFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- DebuggingDetectionFingerprint.result!!.mutableMethod.addInstructions(
- 0,
- """
- const/4 v0, 0x0
- return v0
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/RootDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/RootDetectionPatch.kt
new file mode 100644
index 000000000..7414ef176
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/RootDetectionPatch.kt
@@ -0,0 +1,21 @@
+package app.revanced.patches.serviceportalbund.detection.root
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.serviceportalbund.detection.root.fingerprints.RootDetectionFingerprint
+
+@Patch(
+ name = "Remove root detection",
+ description = "Removes the check for root permissions and unlocked bootloader.",
+ compatiblePackages = [CompatiblePackage("at.gv.bka.serviceportal")]
+)
+@Suppress("unused")
+object RootDetectionPatch : BytecodePatch(
+ setOf(RootDetectionFingerprint)
+) {
+ override fun execute(context: BytecodeContext) =
+ RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
+}
diff --git a/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/fingerprints/RootDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/fingerprints/RootDetectionFingerprint.kt
new file mode 100644
index 000000000..4feed493a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/fingerprints/RootDetectionFingerprint.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.serviceportalbund.detection.root.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+object RootDetectionFingerprint : MethodFingerprint(
+ "V",
+ accessFlags = AccessFlags.PUBLIC.value,
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
+ }
+)
diff --git a/src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/integrations/AbstractIntegrationsPatch.kt
similarity index 85%
rename from src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt
rename to src/main/kotlin/app/revanced/patches/shared/integrations/AbstractIntegrationsPatch.kt
index 378cfc30d..be2c41917 100644
--- a/src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/integrations/AbstractIntegrationsPatch.kt
@@ -1,20 +1,18 @@
-package app.revanced.patches.shared.integrations.patch
+package app.revanced.patches.shared.integrations
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint.RegisterResolver
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint.RegisterResolver
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
-@Description("Applies mandatory patches to implement the ReVanced integrations into the application.")
abstract class AbstractIntegrationsPatch(
private val integrationsDescriptor: String,
- private val hooks: Iterable
+ private val hooks: Set
) : BytecodePatch(hooks) {
/**
* [MethodFingerprint] for integrations.
diff --git a/src/main/kotlin/app/revanced/patches/shared/mapping/misc/patch/ResourceMappingPatch.kt b/src/main/kotlin/app/revanced/patches/shared/mapping/misc/ResourceMappingPatch.kt
similarity index 77%
rename from src/main/kotlin/app/revanced/patches/shared/mapping/misc/patch/ResourceMappingPatch.kt
rename to src/main/kotlin/app/revanced/patches/shared/mapping/misc/ResourceMappingPatch.kt
index 62d1043c4..c80a6b0c5 100644
--- a/src/main/kotlin/app/revanced/patches/shared/mapping/misc/patch/ResourceMappingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/mapping/misc/ResourceMappingPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.shared.mapping.misc.patch
+package app.revanced.patches.shared.mapping.misc
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
@@ -8,14 +8,12 @@ import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
-class ResourceMappingPatch : ResourcePatch {
- companion object {
- internal lateinit var resourceMappings: List
- private set
+object ResourceMappingPatch : ResourcePatch() {
+ internal lateinit var resourceMappings: List
+ private set
- private val THREAD_COUNT = Runtime.getRuntime().availableProcessors()
- private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT)
- }
+ private val THREAD_COUNT = Runtime.getRuntime().availableProcessors()
+ private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT)
override fun execute(context: ResourceContext) {
// save the file in memory to concurrently read from
@@ -34,7 +32,7 @@ class ResourceMappingPatch : ResourcePatch {
val batchStart = jobSize * threadIndex
val batchEnd = jobSize * (threadIndex + 1)
element@ for (i in batchStart until batchEnd) {
- // make sure to not to go out of bounds when rounding errors occur at calculating the jobSize
+ // make sure to not go out of bounds when rounding errors occur at calculating the jobSize
if (i >= resourcesLength) return@thread
val node = resources.item(i)
@@ -46,6 +44,7 @@ class ResourceMappingPatch : ResourcePatch {
if (node.nodeName != "public" || nameAttribute.startsWith("APKTOOL")) continue
val id = node.getAttribute("id").substring(2).toLong(16)
+
mappings.add(ResourceElement(typeAttribute, nameAttribute, id))
}
}
@@ -58,6 +57,6 @@ class ResourceMappingPatch : ResourcePatch {
resourceMappings = mappings
}
-}
-data class ResourceElement(val type: String, val name: String, val id: Long)
+ data class ResourceElement(val type: String, val name: String, val id: Long)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt
rename to src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt
index cea86414e..60949f08d 100644
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt
@@ -1,19 +1,17 @@
-package app.revanced.patches.shared.misc.fix.verticalscroll.patch
+package app.revanced.patches.shared.misc.fix.verticalscroll
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.shared.misc.fix.verticalscroll.annotations.VerticalScrollCompatibility
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.fix.verticalscroll.fingerprints.CanScrollVerticallyFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Description("Fixes issues with refreshing the feed when the first component is of type EmptyComponent.")
-@VerticalScrollCompatibility
-class VerticalScrollPatch : BytecodePatch(
- listOf(CanScrollVerticallyFingerprint)
+@Patch(description = "Fixes issues with refreshing the feed when the first component is of type EmptyComponent.")
+object VerticalScrollPatch : BytecodePatch(
+ setOf(CanScrollVerticallyFingerprint)
) {
override fun execute(context: BytecodeContext) {
CanScrollVerticallyFingerprint.result?.let {
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/annotations/VerticalScrollCompatibility.kt b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/annotations/VerticalScrollCompatibility.kt
deleted file mode 100644
index bd19fbc45..000000000
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/annotations/VerticalScrollCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.shared.misc.fix.verticalscroll.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.google.android.youtube"),
- Package("com.vanced.android.youtube")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class VerticalScrollCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/shared/settings/AbstractSettingsResourcePatch.kt
similarity index 98%
rename from src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/shared/settings/AbstractSettingsResourcePatch.kt
index 3819be0dd..e5dd40b20 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/AbstractSettingsResourcePatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.shared.settings.resource.patch
+package app.revanced.patches.shared.settings
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
@@ -23,7 +23,7 @@ import java.io.Closeable
abstract class AbstractSettingsResourcePatch(
private val preferenceFileName: String,
private val sourceDirectory: String,
-) : ResourcePatch, Closeable {
+) : ResourcePatch(), Closeable {
override fun execute(context: ResourceContext) {
/*
* used for self-restart
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt
index a24b6dfa9..6623c3bf4 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt
@@ -4,7 +4,7 @@ import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
import app.revanced.patches.shared.settings.preference.SummaryType
import app.revanced.patches.shared.settings.preference.addSummary
-import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch.Companion.include
+import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch.Companion.include
import org.w3c.dom.Document
import org.w3c.dom.Element
diff --git a/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/patch/RemoveFileSizeLimitPatch.kt b/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/patch/RemoveFileSizeLimitPatch.kt
rename to src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt
index 3fed6f538..88502cc1b 100644
--- a/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/patch/RemoveFileSizeLimitPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt
@@ -1,23 +1,23 @@
-package app.revanced.patches.solidexplorer2.functionality.filesize.patch
+package app.revanced.patches.solidexplorer2.functionality.filesize
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.solidexplorer2.functionality.filesize.fingerprints.OnReadyFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction
-@Patch
-@Name("Remove file size limit")
-@Description("Allows opening files larger than 2 MB in the text editor.")
-@Compatibility([Package("pl.solidexplorer2")])
-class RemoveFileSizeLimitPatch : BytecodePatch(listOf(OnReadyFingerprint)) {
+
+@Patch(
+ name = "Remove file size limit",
+ description = "Allows opening files larger than 2 MB in the text editor.",
+ compatiblePackages = [CompatiblePackage("pl.solidexplorer2")]
+)
+@Suppress("unused")
+object RemoveFileSizeLimitPatch : BytecodePatch(setOf(OnReadyFingerprint)) {
override fun execute(context: BytecodeContext) = OnReadyFingerprint.result?.let { result ->
val cmpIndex = result.scanResult.patternScanResult!!.startIndex + 1
val cmpResultRegister = result.mutableMethod.getInstruction(cmpIndex).registerA
diff --git a/src/main/kotlin/app/revanced/patches/songpal/badge/patch/BadgeTabPatch.kt b/src/main/kotlin/app/revanced/patches/songpal/badge/BadgeTabPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/songpal/badge/patch/BadgeTabPatch.kt
rename to src/main/kotlin/app/revanced/patches/songpal/badge/BadgeTabPatch.kt
index 9e00514e6..f542cd848 100644
--- a/src/main/kotlin/app/revanced/patches/songpal/badge/patch/BadgeTabPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/songpal/badge/BadgeTabPatch.kt
@@ -1,23 +1,23 @@
-package app.revanced.patches.songpal.badge.patch
+package app.revanced.patches.songpal.badge
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.songpal.badge.annotations.BadgeCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.songpal.badge.fingerprints.CreateTabsFingerprint
-@Patch
-@Name("Remove badge tab")
-@Description("Removes the badge tab from the activity tab.")
-@BadgeCompatibility
-class BadgeTabPatch : BytecodePatch(
- listOf(CreateTabsFingerprint)
-) {
+@Patch(
+ name = "Remove badge tab",
+ description = "Removes the badge tab from the activity tab.",
+ compatiblePackages = [CompatiblePackage("com.sony.songpal.mdr")]
+)
+object BadgeTabPatch : BytecodePatch(setOf(CreateTabsFingerprint)) {
+ const val ACTIVITY_TAB_DESCRIPTOR = "Ljp/co/sony/vim/framework/ui/yourheadphones/YhContract\$Tab;"
+ private val arrayTabs = listOf("Log", "HealthCare")
+
override fun execute(context: BytecodeContext) {
CreateTabsFingerprint.result?.mutableMethod?.apply {
removeInstructions(0, 2)
@@ -52,9 +52,4 @@ class BadgeTabPatch : BytecodePatch(
} ?: throw CreateTabsFingerprint.exception
}
-
- companion object {
- const val ACTIVITY_TAB_DESCRIPTOR = "Ljp/co/sony/vim/framework/ui/yourheadphones/YhContract\$Tab;"
- val arrayTabs = listOf("Log", "HealthCare")
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/songpal/badge/RemoveNotificationBadgePatch.kt b/src/main/kotlin/app/revanced/patches/songpal/badge/RemoveNotificationBadgePatch.kt
new file mode 100644
index 000000000..d039784a1
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/songpal/badge/RemoveNotificationBadgePatch.kt
@@ -0,0 +1,22 @@
+package app.revanced.patches.songpal.badge
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.songpal.badge.fingerprints.ShowNotificationFingerprint
+
+@Patch(
+ name = "Remove notification badge",
+ description = "Removes the red notification badge from the activity tab.",
+ compatiblePackages = [CompatiblePackage("com.sony.songpal.mdr")]
+)
+@Suppress("unused")
+object RemoveNotificationBadgePatch : BytecodePatch(setOf(ShowNotificationFingerprint)) {
+ override fun execute(context: BytecodeContext) {
+ ShowNotificationFingerprint.result?.mutableMethod?.addInstructions(0, "return-void")
+ ?: throw ShowNotificationFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/songpal/badge/annotations/BadgeCompatibility.kt b/src/main/kotlin/app/revanced/patches/songpal/badge/annotations/BadgeCompatibility.kt
deleted file mode 100644
index 0cd69f668..000000000
--- a/src/main/kotlin/app/revanced/patches/songpal/badge/annotations/BadgeCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.songpal.badge.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.sony.songpal.mdr")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class BadgeCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/songpal/badge/fingerprints/CreateTabsFingerprint.kt b/src/main/kotlin/app/revanced/patches/songpal/badge/fingerprints/CreateTabsFingerprint.kt
index b85e7464a..49030d710 100644
--- a/src/main/kotlin/app/revanced/patches/songpal/badge/fingerprints/CreateTabsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/songpal/badge/fingerprints/CreateTabsFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.songpal.badge.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.songpal.badge.patch.BadgeTabPatch
+import app.revanced.patches.songpal.badge.BadgeTabPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
diff --git a/src/main/kotlin/app/revanced/patches/songpal/badge/patch/RemoveNotificationBadgePatch.kt b/src/main/kotlin/app/revanced/patches/songpal/badge/patch/RemoveNotificationBadgePatch.kt
deleted file mode 100644
index 3794339a8..000000000
--- a/src/main/kotlin/app/revanced/patches/songpal/badge/patch/RemoveNotificationBadgePatch.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package app.revanced.patches.songpal.badge.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.songpal.badge.annotations.BadgeCompatibility
-import app.revanced.patches.songpal.badge.fingerprints.ShowNotificationFingerprint
-
-@Patch
-@Name("Remove notification badge")
-@Description("Removes the red notification badge from the activity tab.")
-@BadgeCompatibility
-class RemoveNotificationBadgePatch : BytecodePatch(
- listOf(ShowNotificationFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- ShowNotificationFingerprint.result?.mutableMethod?.apply {
- addInstructions(0, "return-void")
- } ?: throw ShowNotificationFingerprint.exception
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt
new file mode 100644
index 000000000..8e2123ed0
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt
@@ -0,0 +1,54 @@
+package app.revanced.patches.spotify.layout.theme
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
+import org.w3c.dom.Element
+
+@Patch(
+ name = "Custom theme",
+ description = "Applies a custom theme.",
+ compatiblePackages = [CompatiblePackage("com.spotify.music")]
+)
+@Suppress("unused")
+object CustomThemePatch : ResourcePatch() {
+ private var backgroundColor by stringPatchOption(
+ key = "backgroundColor",
+ default = "@android:color/black",
+ title = "Background color",
+ description = "The background color. Can be a hex color or a resource reference.",
+ )
+
+ private var accentColor by stringPatchOption(
+ key = "accentColor",
+ default = "#ff1ed760",
+ title = "Accent color",
+ description = "The accent color ('spotify green' by default). Can be a hex color or a resource reference.",
+ )
+
+ private var accentPressedColor by stringPatchOption(
+ key = "accentPressedColor",
+ default = "#ff169c46",
+ title = "Pressed accent for the dark theme",
+ description = "The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference."
+ )
+
+ override fun execute(context: ResourceContext) {
+ context.xmlEditor["res/values/colors.xml"].use { editor ->
+ val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
+
+ for (i in 0 until resourcesNode.childNodes.length) {
+ val node = resourcesNode.childNodes.item(i) as? Element ?: continue
+
+ node.textContent = when (node.getAttribute("name")) {
+ "gray_7" -> backgroundColor!!
+ "dark_brightaccent_background_base", "dark_base_text_brightaccent", "green_light" -> accentColor!!
+ "dark_brightaccent_background_press" -> accentPressedColor!!
+ else -> continue
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt
deleted file mode 100644
index 5a855c9fd..000000000
--- a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.spotify.layout.theme.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.spotify.music")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ThemeCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt
deleted file mode 100644
index c90b93ff7..000000000
--- a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package app.revanced.patches.spotify.layout.theme.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.OptionsContainer
-import app.revanced.patcher.patch.PatchOption
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.spotify.layout.theme.annotations.ThemeCompatibility
-import org.w3c.dom.Element
-
-@Patch
-@Name("Spotify theme")
-@Description("Applies a custom theme.")
-@ThemeCompatibility
-class ThemePatch : ResourcePatch {
- override fun execute(context: ResourceContext) {
- context.xmlEditor["res/values/colors.xml"].use { editor ->
- val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
-
- for (i in 0 until resourcesNode.childNodes.length) {
- val node = resourcesNode.childNodes.item(i) as? Element ?: continue
-
- node.textContent = when (node.getAttribute("name")) {
- "gray_7" -> backgroundColor!!
- "dark_brightaccent_background_base", "dark_base_text_brightaccent", "green_light" -> accentColor!!
- "dark_brightaccent_background_press" -> accentPressedColor!!
- else -> continue
- }
- }
- }
- }
-
- companion object : OptionsContainer() {
- var backgroundColor: String? by option(
- PatchOption.StringOption(
- key = "backgroundColor",
- default = "@android:color/black",
- title = "Background color",
- description = "The background color. Can be a hex color or a resource reference.",
- )
- )
- var accentColor: String? by option(
- PatchOption.StringOption(
- key = "accentColor",
- default = "#ff1ed760",
- title = "Accent color",
- description = "The accent color ('spotify green' by default). Can be a hex color or a resource reference.",
- )
- )
- var accentPressedColor: String? by option(
- PatchOption.StringOption(
- key = "accentPressedColor",
- default = "#ff169c46",
- title = "Pressed accent for the dark theme",
- description = "The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.",
- )
- )
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/patch/OnDemandPatch.kt b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt
similarity index 51%
rename from src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/patch/OnDemandPatch.kt
rename to src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt
index 7ab6ff29a..0edb23e9b 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/patch/OnDemandPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt
@@ -1,24 +1,20 @@
-package app.revanced.patches.spotify.lite.ondemand.patch
+package app.revanced.patches.spotify.lite.ondemand
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.spotify.lite.ondemand.annotations.OnDemandCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.spotify.lite.ondemand.fingerprints.OnDemandFingerprint
-@Patch
-@Name("Enable on demand")
-@Description("Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.")
-@OnDemandCompatibility
-class OnDemandPatch : BytecodePatch(
- listOf(
- OnDemandFingerprint
- )
-) {
+@Patch(
+ name = "Enable on demand",
+ description = "Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.",
+ compatiblePackages = [CompatiblePackage("com.spotify.lite")]
+)
+@Suppress("unused")
+object OnDemandPatch : BytecodePatch(setOf(OnDemandFingerprint)) {
override fun execute(context: BytecodeContext) {
OnDemandFingerprint.result?.apply {
val insertIndex = scanResult.patternScanResult!!.endIndex - 1
diff --git a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/annotations/OnDemandCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/annotations/OnDemandCompatibility.kt
deleted file mode 100644
index 2550824b2..000000000
--- a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/annotations/OnDemandCompatibility.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package app.revanced.patches.spotify.lite.ondemand.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package("com.spotify.lite")]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class OnDemandCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt b/src/main/kotlin/app/revanced/patches/spotify/navbar/PremiumNavbarTabPatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt
rename to src/main/kotlin/app/revanced/patches/spotify/navbar/PremiumNavbarTabPatch.kt
index a8126057c..8407ab791 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/spotify/navbar/PremiumNavbarTabPatch.kt
@@ -1,30 +1,25 @@
-package app.revanced.patches.spotify.premium_navbar_tab.patch
+package app.revanced.patches.spotify.navbar
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.spotify.premium_navbar_tab.annotations.PremiumNavbarTabCompatibility
-import app.revanced.patches.spotify.premium_navbar_tab.fingerprints.AddPremiumNavbarTabFingerprint
-import app.revanced.patches.spotify.premium_navbar_tab.fingerprints.AddPremiumNavbarTabParentFingerprint
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
+import app.revanced.patches.spotify.navbar.fingerprints.AddPremiumNavbarTabFingerprint
+import app.revanced.patches.spotify.navbar.fingerprints.AddPremiumNavbarTabParentFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
-@Patch
-@Name("Hide premium navbar")
-@Description("Removes the premium tab from the navbar.")
-@PremiumNavbarTabCompatibility
-@DependsOn([ResourceMappingPatch::class])
-class PremiumNavbarTabPatch : BytecodePatch(
- listOf(
- AddPremiumNavbarTabParentFingerprint
- )
-) {
+@Patch(
+ name = "Hide premium navbar",
+ description = "Removes the premium tab from the navbar.",
+ dependencies = [ResourceMappingPatch::class],
+ compatiblePackages = [CompatiblePackage("com.spotify.music")]
+)
+@Suppress("unused")
+object PremiumNavbarTabPatch : BytecodePatch(setOf(AddPremiumNavbarTabParentFingerprint)) {
override fun execute(context: BytecodeContext) {
val parentResult = AddPremiumNavbarTabParentFingerprint.result!!
AddPremiumNavbarTabFingerprint.resolve(context, parentResult.classDef)
diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/navbar/fingerprints/AddPremiumNavbarTabFingerprint.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/spotify/navbar/fingerprints/AddPremiumNavbarTabFingerprint.kt
index 296c87f8d..262164514 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/spotify/navbar/fingerprints/AddPremiumNavbarTabFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.spotify.premium_navbar_tab.fingerprints
+package app.revanced.patches.spotify.navbar.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/navbar/fingerprints/AddPremiumNavbarTabParentFingerprint.kt
similarity index 76%
rename from src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/spotify/navbar/fingerprints/AddPremiumNavbarTabParentFingerprint.kt
index e67bd8f6b..cd029b9fc 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/spotify/navbar/fingerprints/AddPremiumNavbarTabParentFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.spotify.premium_navbar_tab.fingerprints
+package app.revanced.patches.spotify.navbar.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt
deleted file mode 100644
index 6924ba5d4..000000000
--- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.spotify.premium_navbar_tab.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.spotify.music")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PremiumNavbarTabCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/strava/subscription/patch/UnlockSubscriptionPatch.kt b/src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/strava/subscription/patch/UnlockSubscriptionPatch.kt
rename to src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt
index 42a462e34..965077ff9 100644
--- a/src/main/kotlin/app/revanced/patches/strava/subscription/patch/UnlockSubscriptionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt
@@ -1,23 +1,22 @@
-package app.revanced.patches.strava.subscription.patch
+package app.revanced.patches.strava.subscription
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.strava.subscription.fingerprints.GetSubscribedFingerprint
-@Patch
-@Name("Unlock subscription features")
-@Description("Unlocks \"Matched Runs\" and \"Segment Efforts\".")
-@Compatibility([Package("com.strava", ["320.12"])])
-class UnlockSubscriptionPatch : BytecodePatch(listOf(GetSubscribedFingerprint)) {
+@Patch(
+ name = "Unlock subscription features",
+ description = "Unlocks \"Routes\", \"Matched Runs\" and \"Segment Efforts\".",
+ compatiblePackages = [CompatiblePackage("com.strava", ["320.12"])]
+)
+@Suppress("unused")
+object UnlockSubscriptionPatch : BytecodePatch(setOf(GetSubscribedFingerprint)) {
override fun execute(context: BytecodeContext) = GetSubscribedFingerprint.result?.let { result ->
val isSubscribedIndex = result.scanResult.patternScanResult!!.startIndex
result.mutableMethod.replaceInstruction(isSubscribedIndex, "const/4 v0, 0x1")
} ?: throw GetSubscribedFingerprint.exception
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/app/revanced/patches/strava/subscription/fingerprints/GetSubscribedFingerprint.kt b/src/main/kotlin/app/revanced/patches/strava/subscription/fingerprints/GetSubscribedFingerprint.kt
index a0f6ff393..c9cf6f921 100644
--- a/src/main/kotlin/app/revanced/patches/strava/subscription/fingerprints/GetSubscribedFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/strava/subscription/fingerprints/GetSubscribedFingerprint.kt
@@ -6,6 +6,6 @@ import com.android.tools.smali.dexlib2.Opcode
object GetSubscribedFingerprint : MethodFingerprint(
opcodes = listOf(Opcode.IGET_BOOLEAN),
customFingerprint = { methodDef, classDef ->
- classDef.type.endsWith("SubscriptionDetailResponse;") && methodDef.name == "getSubscribed"
+ classDef.type.endsWith("/SubscriptionDetailResponse;") && methodDef.name == "getSubscribed"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt b/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt
new file mode 100644
index 000000000..22e50c854
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt
@@ -0,0 +1,72 @@
+package app.revanced.patches.strava.upselling
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
+import app.revanced.patches.strava.upselling.fingerprints.GetModulesFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
+import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
+
+@Patch(
+ name = "Disable subscription suggestions",
+ compatiblePackages = [CompatiblePackage("com.strava", ["320.12"])]
+)
+@Suppress("unused")
+object DisableSubscriptionSuggestionsPatch : BytecodePatch(
+ setOf(GetModulesFingerprint)
+) {
+ private const val HELPER_METHOD_NAME = "getModulesIfNotUpselling"
+ private const val PAGE_SUFFIX = "_upsell"
+ private const val LABEL = "original"
+
+ override fun execute(context: BytecodeContext) = GetModulesFingerprint.result?.let { result ->
+ val className = result.classDef.type
+ val originalMethod = result.mutableMethod
+ val returnType = originalMethod.returnType
+
+ result.mutableClass.methods.add(ImmutableMethod(
+ className,
+ HELPER_METHOD_NAME,
+ emptyList(),
+ returnType,
+ AccessFlags.PRIVATE.value,
+ null,
+ null,
+ MutableMethodImplementation(3)
+ ).toMutable().apply {
+ addInstructions(
+ """
+ iget-object v0, p0, $className->page:Ljava/lang/String;
+ const-string v1, "$PAGE_SUFFIX"
+ invoke-virtual {v0, v1}, Ljava/lang/String;->endsWith(Ljava/lang/String;)Z
+ move-result v0
+ if-eqz v0, :$LABEL
+ invoke-static {}, Ljava/util/Collections;->emptyList()Ljava/util/List;
+ move-result-object v0
+ return-object v0
+ :$LABEL
+ iget-object v0, p0, $className->modules:Ljava/util/List;
+ return-object v0
+ """
+ )
+ })
+
+ val getModulesIndex = result.scanResult.patternScanResult!!.startIndex
+ with(originalMethod) {
+ removeInstruction(getModulesIndex)
+ addInstructions(
+ getModulesIndex,
+ """
+ invoke-direct {p0}, $className->$HELPER_METHOD_NAME()$returnType
+ move-result-object v0
+ """
+ )
+ }
+ } ?: throw GetModulesFingerprint.exception
+}
diff --git a/src/main/kotlin/app/revanced/patches/strava/upselling/fingerprints/GetModulesFingerprint.kt b/src/main/kotlin/app/revanced/patches/strava/upselling/fingerprints/GetModulesFingerprint.kt
new file mode 100644
index 000000000..a343d62f8
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/strava/upselling/fingerprints/GetModulesFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.strava.upselling.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.Opcode
+
+object GetModulesFingerprint : MethodFingerprint(
+ opcodes = listOf(Opcode.IGET_OBJECT),
+ customFingerprint = { methodDef, classDef ->
+ classDef.type.endsWith("/GenericLayoutEntry;") && methodDef.name == "getModules"
+ }
+)
diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt
similarity index 60%
rename from src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt
rename to src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt
index e7ff2319a..e39cd0777 100644
--- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt
@@ -1,26 +1,21 @@
-package app.revanced.patches.ticktick.misc.themeunlock.patch
+package app.revanced.patches.ticktick.misc.themeunlock
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.ticktick.misc.themeunlock.annotations.UnlockThemesCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.ticktick.misc.themeunlock.fingerprints.CheckLockedThemesFingerprint
import app.revanced.patches.ticktick.misc.themeunlock.fingerprints.SetThemeFingerprint
-@Patch
-@Name("Unlock themes")
-@Description("Unlocks all themes that are inaccessible until a certain level is reached.")
-@UnlockThemesCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(
- CheckLockedThemesFingerprint,
- SetThemeFingerprint
- )
-) {
+@Patch(
+ name = "Unlock themes",
+ description = "Unlocks all themes that are inaccessible until a certain level is reached.",
+ compatiblePackages = [CompatiblePackage("com.ticktick.task")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(setOf(CheckLockedThemesFingerprint, SetThemeFingerprint)) {
override fun execute(context: BytecodeContext) {
val lockedThemesMethod = CheckLockedThemesFingerprint.result!!.mutableMethod
lockedThemesMethod.addInstructions(
diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt
deleted file mode 100644
index 3fa4619e6..000000000
--- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.ticktick.misc.themeunlock.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.ticktick.task")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockThemesCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/HideAdsPatch.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/tiktok/ad/patch/HideAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/ad/HideAdsPatch.kt
index 975672dc6..bf6403f65 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/ad/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/ad/HideAdsPatch.kt
@@ -1,13 +1,11 @@
-package app.revanced.patches.tiktok.ad.patch
+package app.revanced.patches.tiktok.ad
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.tiktok.ad.annotations.HideAdsCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.tiktok.ad.fingerprints.ConvertHelpFeedItemListFingerprint
import app.revanced.patches.tiktok.ad.fingerprints.FeedItemListCloneFingerprint
import com.android.tools.smali.dexlib2.Opcode
@@ -15,15 +13,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
-@Patch
-@Name("Hide ads")
-@Description("Removes ads from TikTok.")
-@HideAdsCompatibility
-class HideAdsPatch : BytecodePatch(
- listOf(
- FeedItemListCloneFingerprint,
- ConvertHelpFeedItemListFingerprint
- )
+@Patch(
+ name = "Hide ads",
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]),
+ CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"])
+ ]
+)
+@Suppress("unused")
+object HideAdsPatch : BytecodePatch(
+ setOf(FeedItemListCloneFingerprint, ConvertHelpFeedItemListFingerprint)
) {
override fun execute(context: BytecodeContext) {
listOf(
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/HideAdsCompatibility.kt
deleted file mode 100644
index a6c21590f..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/HideAdsCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.ad.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/FeedFilterPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/FeedFilterPatch.kt
similarity index 57%
rename from src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/FeedFilterPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/feedfilter/FeedFilterPatch.kt
index d75b5032c..98ed1c235 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/FeedFilterPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/FeedFilterPatch.kt
@@ -1,31 +1,29 @@
-package app.revanced.patches.tiktok.feedfilter.patch
+package app.revanced.patches.tiktok.feedfilter
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
+import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.tiktok.feedfilter.annotations.FeedFilterCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.tiktok.feedfilter.fingerprints.FeedApiServiceLIZFingerprint
-import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
+import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
-import app.revanced.patches.tiktok.misc.settings.patch.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Feed filter")
-@Description("Filters tiktok videos: removing ads, removing livestreams.")
-@FeedFilterCompatibility
-class FeedFilterPatch : BytecodePatch(
- listOf(
- FeedApiServiceLIZFingerprint,
- SettingsStatusLoadFingerprint
- )
-) {
+@Patch(
+ name = "Feed filter",
+ description = "Filters tiktok videos: removing ads, removing livestreams.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+@Suppress("unused")
+object FeedFilterPatch : BytecodePatch(setOf(FeedApiServiceLIZFingerprint, SettingsStatusLoadFingerprint)) {
override fun execute(context: BytecodeContext) {
val method = FeedApiServiceLIZFingerprint.result!!.mutableMethod
for ((index, instruction) in method.implementation!!.instructions.withIndex()) {
@@ -37,10 +35,10 @@ class FeedFilterPatch : BytecodePatch(
)
break
}
- val method2 = SettingsStatusLoadFingerprint.result!!.mutableMethod
- method2.addInstruction(
+
+ SettingsStatusLoadFingerprint.result?.mutableMethod?.addInstruction(
0,
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableFeedFilter()V"
- )
+ ) ?: throw SettingsStatusLoadFingerprint.exception
}
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt
deleted file mode 100644
index 64d56b264..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.feedfilter.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class FeedFilterCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/DownloadsPatch.kt
similarity index 87%
rename from src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/DownloadsPatch.kt
index 50d954ab1..9b627e12d 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/DownloadsPatch.kt
@@ -1,7 +1,5 @@
-package app.revanced.patches.tiktok.interaction.downloads.patch
+package app.revanced.patches.tiktok.interaction.downloads
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -10,29 +8,33 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint2
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint3
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.DownloadPathParentFingerprint
-import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
-import app.revanced.patches.tiktok.misc.settings.patch.SettingsPatch
+import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Downloads")
-@Description("Removes download restrictions and changes the default path to download to.")
-@DownloadsCompatibility
-class DownloadsPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Downloads",
+ description = "Removes download restrictions and changes the default path to download to.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+@Suppress("unused")
+object DownloadsPatch : BytecodePatch(
+ setOf(
ACLCommonShareFingerprint,
ACLCommonShareFingerprint2,
ACLCommonShareFingerprint3,
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt
deleted file mode 100644
index bb2920640..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.interaction.downloads.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class DownloadsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt
index 774ffd45f..422bdaa92 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt
@@ -1,13 +1,9 @@
package app.revanced.patches.tiktok.interaction.downloads.fingerprints
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility
import com.android.tools.smali.dexlib2.AccessFlags
-@Name("Acl common share get show type")
-@DownloadsCompatibility
object ACLCommonShareFingerprint2 : MethodFingerprint(
"I",
AccessFlags.PUBLIC or AccessFlags.FINAL,
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt
index 3102f378b..a373a11a9 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt
@@ -1,13 +1,9 @@
package app.revanced.patches.tiktok.interaction.downloads.fingerprints
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility
import com.android.tools.smali.dexlib2.AccessFlags
-@Name("Acl common share get transcode")
-@DownloadsCompatibility
object ACLCommonShareFingerprint3 : MethodFingerprint(
"I",
AccessFlags.PUBLIC or AccessFlags.FINAL,
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/ShowSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/ShowSeekbarPatch.kt
similarity index 66%
rename from src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/ShowSeekbarPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/ShowSeekbarPatch.kt
index 85bbe3378..60fed08ce 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/ShowSeekbarPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/ShowSeekbarPatch.kt
@@ -1,26 +1,24 @@
-package app.revanced.patches.tiktok.interaction.seekbar.patch
+package app.revanced.patches.tiktok.interaction.seekbar
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.tiktok.interaction.seekbar.annotations.ShowSeekbarCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.SetSeekBarShowTypeFingerprint
import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.ShouldShowSeekBarFingerprint
-@Patch
-@Name("Show seekbar")
-@Description("Shows progress bar for all video.")
-@ShowSeekbarCompatibility
-class ShowSeekbarPatch : BytecodePatch(
- listOf(
- SetSeekBarShowTypeFingerprint,
- ShouldShowSeekBarFingerprint,
- )
-) {
+@Patch(
+ name = "Show seekbar",
+ description = "Shows progress bar for all video.",
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+@Suppress("unused")
+object ShowSeekbarPatch : BytecodePatch(setOf(SetSeekBarShowTypeFingerprint, ShouldShowSeekBarFingerprint)) {
override fun execute(context: BytecodeContext) {
ShouldShowSeekBarFingerprint.result?.mutableMethod?.apply {
addInstructions(
@@ -42,5 +40,4 @@ class ShowSeekbarPatch : BytecodePatch(
)
} ?: throw SetSeekBarShowTypeFingerprint.exception
}
-
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/ShowSeekbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/ShowSeekbarCompatibility.kt
deleted file mode 100644
index 3326e9f2a..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/ShowSeekbarCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.interaction.seekbar.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class ShowSeekbarCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/PlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/PlaybackSpeedPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt
index 8e0fb5277..dbde0bb50 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/PlaybackSpeedPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt
@@ -1,25 +1,24 @@
-package app.revanced.patches.tiktok.interaction.speed.patch
+package app.revanced.patches.tiktok.interaction.speed
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.tiktok.interaction.speed.annotations.PlaybackSpeedCompatibility
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint
import com.android.tools.smali.dexlib2.Opcode
-@Patch
-@Name("Playback speed")
-@Description("Enables the playback speed option for all videos.")
-@PlaybackSpeedCompatibility
-class PlaybackSpeedPatch : BytecodePatch(
- listOf(
- SpeedControlParentFingerprint
- )
-) {
+@Patch(
+ name = "Playback speed",
+ description = "Enables the playback speed option for all videos.",
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+@Suppress("unused")
+object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) {
override fun execute(context: BytecodeContext) {
val parentMethod = SpeedControlParentFingerprint.result!!.mutableMethod
val parentMethodInstructions = parentMethod.implementation!!.instructions
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/PlaybackSpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/PlaybackSpeedCompatibility.kt
deleted file mode 100644
index fbb92e8b1..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/PlaybackSpeedCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.interaction.speed.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlaybackSpeedCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/IntegrationsPatch.kt
new file mode 100644
index 000000000..b13321c0c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/IntegrationsPatch.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.tiktok.misc.integrations
+
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch
+import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprint
+
+@Patch(requiresIntegrations = true)
+object IntegrationsPatch : AbstractIntegrationsPatch(
+ "Lapp/revanced/tiktok/utils/ReVancedUtils;",
+ setOf(InitFingerprint)
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
index b4d095976..896637884 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
@@ -1,6 +1,6 @@
package app.revanced.patches.tiktok.misc.integrations.fingerprints
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
object InitFingerprint : IntegrationsFingerprint(
customFingerprint = { methodDef, _ ->
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/IntegrationsPatch.kt
deleted file mode 100644
index 9761c0f12..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/IntegrationsPatch.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.misc.integrations.patch
-
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
-import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprint
-
-@Name("Integrations")
-@RequiresIntegrations
-class IntegrationsPatch : AbstractIntegrationsPatch(
- "Lapp/revanced/tiktok/utils/ReVancedUtils;",
- listOf(InitFingerprint)
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/patch/DisableLoginRequirementPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/DisableLoginRequirementPatch.kt
similarity index 62%
rename from src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/patch/DisableLoginRequirementPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/DisableLoginRequirementPatch.kt
index c34ead152..33f4ec770 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/patch/DisableLoginRequirementPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/DisableLoginRequirementPatch.kt
@@ -1,24 +1,23 @@
-package app.revanced.patches.tiktok.misc.login.disablerequirement.patch
+package app.revanced.patches.tiktok.misc.login.disablerequirement
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.tiktok.misc.login.disablerequirement.annotations.DisableLoginRequirementCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.tiktok.misc.login.disablerequirement.fingerprints.MandatoryLoginServiceFingerprint
import app.revanced.patches.tiktok.misc.login.disablerequirement.fingerprints.MandatoryLoginServiceFingerprint2
-@Patch
-@Name("Disable login requirement")
-@Description("Do not force login.")
-@DisableLoginRequirementCompatibility
-class DisableLoginRequirementPatch : BytecodePatch(
- listOf(
- MandatoryLoginServiceFingerprint,
- MandatoryLoginServiceFingerprint2
- )
+@Patch(
+ name = "Disable login requirement",
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+@Suppress("unused")
+object DisableLoginRequirementPatch : BytecodePatch(
+ setOf(MandatoryLoginServiceFingerprint, MandatoryLoginServiceFingerprint2)
) {
override fun execute(context: BytecodeContext) {
listOf(
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/annotations/DisableLoginRequirementCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/annotations/DisableLoginRequirementCompatibility.kt
deleted file mode 100644
index faaaa0744..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/annotations/DisableLoginRequirementCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.misc.login.disablerequirement.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class DisableLoginRequirementCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt
index 623e0359f..1e40a0ac8 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt
@@ -1,11 +1,7 @@
package app.revanced.patches.tiktok.misc.login.disablerequirement.fingerprints
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.tiktok.misc.login.disablerequirement.annotations.DisableLoginRequirementCompatibility
-@Name("Mandatory login service fingerprint2")
-@DisableLoginRequirementCompatibility
object MandatoryLoginServiceFingerprint2 : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/MandatoryLoginService;") &&
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/patch/FixGoogleLoginPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/FixGoogleLoginPatch.kt
similarity index 59%
rename from src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/patch/FixGoogleLoginPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/FixGoogleLoginPatch.kt
index d6916bad0..13f595ed1 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/patch/FixGoogleLoginPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/FixGoogleLoginPatch.kt
@@ -1,24 +1,24 @@
-package app.revanced.patches.tiktok.misc.login.fixgoogle.patch
+package app.revanced.patches.tiktok.misc.login.fixgoogle
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.tiktok.misc.login.fixgoogle.annotations.FixGoogleLoginCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.tiktok.misc.login.fixgoogle.fingerprints.GoogleAuthAvailableFingerprint
import app.revanced.patches.tiktok.misc.login.fixgoogle.fingerprints.GoogleOneTapAuthAvailableFingerprint
-@Patch
-@Name("Fix google login")
-@Description("Allows logging in with a Google account.")
-@FixGoogleLoginCompatibility
-class FixGoogleLoginPatch : BytecodePatch(
- listOf(
- GoogleOneTapAuthAvailableFingerprint,
- GoogleAuthAvailableFingerprint
- )
+@Patch(
+ name = "Fix Google login",
+ description = "Allows logging in with a Google account.",
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+@Suppress("unused")
+object FixGoogleLoginPatch : BytecodePatch(
+ setOf(GoogleOneTapAuthAvailableFingerprint, GoogleAuthAvailableFingerprint)
) {
override fun execute(context: BytecodeContext) {
listOf(
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/annotations/FixGoogleLoginCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/annotations/FixGoogleLoginCompatibility.kt
deleted file mode 100644
index 62d7e5795..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/annotations/FixGoogleLoginCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.misc.login.fixgoogle.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class FixGoogleLoginCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/SettingsPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/misc/settings/SettingsPatch.kt
index dfa3c2368..eddec76de 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/SettingsPatch.kt
@@ -1,36 +1,54 @@
-package app.revanced.patches.tiktok.misc.settings.patch
+package app.revanced.patches.tiktok.misc.settings
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.tiktok.misc.settings.annotations.SettingsCompatibility
-import app.revanced.patches.tiktok.misc.settings.fingerprints.*
+import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
+import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityOnCreateFingerprint
+import app.revanced.patches.tiktok.misc.settings.fingerprints.AddSettingsEntryFingerprint
+import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsEntryFingerprint
+import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsEntryInfoFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
-@Patch
-@DependsOn([IntegrationsPatch::class])
-@Name("Settings")
-@Description("Adds ReVanced settings to TikTok.")
-@SettingsCompatibility
-class SettingsPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Settings",
+ description = "Adds ReVanced settings to TikTok.",
+ dependencies = [IntegrationsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ]
+)
+object SettingsPatch : BytecodePatch(
+ setOf(
AdPersonalizationActivityOnCreateFingerprint,
AddSettingsEntryFingerprint,
SettingsEntryFingerprint,
SettingsEntryInfoFingerprint,
)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
+
+ private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
+ "Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
+ ")Z"
+
+ private const val CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR =
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->createSettingsEntry(" +
+ "Ljava/lang/String;" +
+ "Ljava/lang/String;" +
+ ")Ljava/lang/Object;"
+
override fun execute(context: BytecodeContext) {
// Find the class name of classes which construct a settings entry
val settingsButtonClass = SettingsEntryFingerprint.result?.classDef?.type?.toClassName()
@@ -91,19 +109,4 @@ class SettingsPatch : BytecodePatch(
private fun String.toClassName(): String {
return substring(1, this.length - 1).replace("/", ".")
}
-
- private companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
-
- private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
- "$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
- "Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
- ")Z"
- private const val CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR =
- "$INTEGRATIONS_CLASS_DESCRIPTOR->createSettingsEntry(" +
- "Ljava/lang/String;" +
- "Ljava/lang/String;" +
- ")Ljava/lang/Object;"
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt
deleted file mode 100644
index b139f1328..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.misc.settings.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class SettingsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt
similarity index 77%
rename from src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt
rename to src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt
index 3227faf11..3e243d863 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt
@@ -1,41 +1,42 @@
-package app.revanced.patches.tiktok.misc.spoof.sim.patch
+package app.revanced.patches.tiktok.misc.spoof.sim
import app.revanced.extensions.findMutableMethodOf
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
-import app.revanced.patches.tiktok.misc.settings.patch.SettingsPatch
-import app.revanced.patches.tiktok.misc.spoof.sim.annotations.SpoofSimCompatibility
+import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-@Patch(false)
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Sim spoof")
-@Description("Spoofs the information which is retrieved from the sim-card.")
-@SpoofSimCompatibility
-class SpoofSimPatch : BytecodePatch() {
- private companion object {
- val replacements = hashMapOf(
- "getSimCountryIso" to "getCountryIso",
- "getNetworkCountryIso" to "getCountryIso",
- "getSimOperator" to "getOperator",
- "getNetworkOperator" to "getOperator",
- "getSimOperatorName" to "getOperatorName",
- "getNetworkOperatorName" to "getOperatorName"
- )
- }
+@Patch(
+ name = "SIM spoof",
+ description = "Spoofs the information which is retrieved from the SIM card.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.ss.android.ugc.trill"),
+ CompatiblePackage("com.zhiliaoapp.musically")
+ ],
+ use = false
+)
+@Suppress("unused")
+object SpoofSimPatch : BytecodePatch() {
+ private val replacements = hashMapOf(
+ "getSimCountryIso" to "getCountryIso",
+ "getNetworkCountryIso" to "getCountryIso",
+ "getSimOperator" to "getOperator",
+ "getNetworkOperator" to "getOperator",
+ "getSimOperatorName" to "getOperatorName",
+ "getNetworkOperatorName" to "getOperatorName"
+ )
override fun execute(context: BytecodeContext) {
// Find all api call to check sim information
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt
deleted file mode 100644
index b258cec9a..000000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.tiktok.misc.spoof.sim.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [
- Package("com.ss.android.ugc.trill"),
- Package("com.zhiliaoapp.musically")
- ]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class SpoofSimCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/trakt/UnlockProPatch.kt
similarity index 62%
rename from src/main/kotlin/app/revanced/patches/trakt/patch/UnlockProPatch.kt
rename to src/main/kotlin/app/revanced/patches/trakt/UnlockProPatch.kt
index 0d5254a02..a7f7f4d97 100644
--- a/src/main/kotlin/app/revanced/patches/trakt/patch/UnlockProPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/trakt/UnlockProPatch.kt
@@ -1,25 +1,32 @@
-package app.revanced.patches.trakt.patch
+package app.revanced.patches.trakt
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.trakt.annotations.UnlockProCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.trakt.fingerprints.IsVIPEPFingerprint
import app.revanced.patches.trakt.fingerprints.IsVIPFingerprint
import app.revanced.patches.trakt.fingerprints.RemoteUserFingerprint
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks pro features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(RemoteUserFingerprint)
+@Patch(
+ name = "Unlock pro",
+ compatiblePackages = [CompatiblePackage("tv.trakt.trakt", ["1.1.1"])]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(
+ setOf(RemoteUserFingerprint)
) {
+ private const val RETURN_TRUE_INSTRUCTIONS =
+ """
+ const/4 v0, 0x1
+ invoke-static {v0}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
+ move-result-object v1
+ return-object v1
+ """
+
override fun execute(context: BytecodeContext) {
RemoteUserFingerprint.result?.classDef?.let { remoteUserClass ->
arrayOf(IsVIPFingerprint, IsVIPEPFingerprint).onEach { fingerprint ->
@@ -33,14 +40,4 @@ class UnlockProPatch : BytecodePatch(
}
} ?: throw RemoteUserFingerprint.exception
}
-
- private companion object {
- const val RETURN_TRUE_INSTRUCTIONS =
- """
- const/4 v0, 0x1
- invoke-static {v0}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
- move-result-object v1
- return-object v1
- """
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/trakt/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index f68ab6732..000000000
--- a/src/main/kotlin/app/revanced/patches/trakt/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.trakt.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.trakt.trakt", arrayOf("1.1.1"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/fingerprints/BrightnessFingerprint.kt b/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/fingerprints/BrightnessFingerprint.kt
new file mode 100644
index 000000000..c6f371af8
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/fingerprints/BrightnessFingerprint.kt
@@ -0,0 +1,15 @@
+package app.revanced.patches.tudortmund.lockscreen.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+object BrightnessFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC.value,
+ parameters = listOf(),
+ customFingerprint = { method, classDef ->
+ method.name == "run"
+ && method.definingClass.contains("/ScreenPlugin\$")
+ && classDef.fields.any { it.type == "Ljava/lang/Float;" }
+ }
+)
diff --git a/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/patch/ShowOnLockscreenPatch.kt b/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/patch/ShowOnLockscreenPatch.kt
new file mode 100644
index 000000000..d9f704a52
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/patch/ShowOnLockscreenPatch.kt
@@ -0,0 +1,89 @@
+package app.revanced.patches.tudortmund.lockscreen.patch
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tudortmund.lockscreen.fingerprints.BrightnessFingerprint
+import com.android.tools.smali.dexlib2.Opcode
+import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
+import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
+import com.android.tools.smali.dexlib2.iface.reference.FieldReference
+import com.android.tools.smali.dexlib2.iface.reference.MethodReference
+
+@Patch(
+ name = "Show on lockscreen",
+ description = "Shows student id and student ticket on lockscreen.",
+ compatiblePackages = [CompatiblePackage("de.tudortmund.app")],
+ requiresIntegrations = true
+)
+@Suppress("unused")
+object ShowOnLockscreenPatch : BytecodePatch(
+ setOf(BrightnessFingerprint)
+) {
+ const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch;"
+
+ override fun execute(context: BytecodeContext) {
+ BrightnessFingerprint.result?.mutableMethod?.apply {
+ // Find the instruction where the brightness value is loaded into a register
+ val brightnessInstruction = implementation!!.instructions.firstNotNullOf { instruction ->
+ if (instruction.opcode != Opcode.IGET_OBJECT) return@firstNotNullOf null
+
+ val getInstruction = instruction as Instruction22c
+ val fieldReference = getInstruction.reference as FieldReference
+
+ if (fieldReference.type != "Ljava/lang/Float;") return@firstNotNullOf null
+
+ instruction
+ }
+
+ // Search for the instruction where we get the android.view.Window via the Activity.
+ // Gets the index of that instruction and the register of the Activity.
+ val (windowIndex, activityRegister) = implementation!!.instructions.withIndex()
+ .firstNotNullOf { (index, instruction) ->
+ if (instruction.opcode != Opcode.INVOKE_VIRTUAL)
+ return@firstNotNullOf null
+
+ val invokeInstruction = instruction as Instruction35c
+ val methodRef = invokeInstruction.reference as MethodReference
+
+ if (methodRef.name != "getWindow" || methodRef.returnType != "Landroid/view/Window;")
+ return@firstNotNullOf null
+
+ Pair(index, invokeInstruction.registerC)
+ }
+
+ // The register in which the brightness value is loaded
+ val brightnessRegister = brightnessInstruction.registerA
+
+ // Replaces the getWindow call with our custom one to run the lockscreen code
+ replaceInstruction(
+ windowIndex,
+ "invoke-static { v$activityRegister, v$brightnessRegister }, " +
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->" +
+ "getWindow" +
+ "(Landroidx/appcompat/app/AppCompatActivity;F)" +
+ "Landroid/view/Window;"
+ )
+
+ // Normally, the brightness is loaded into a register after the getWindow call.
+ // In order to pass the brightness value to our custom getWindow implementation,
+ // we need to add the same instructions before the getWindow call.
+ // The Float object is loaded into the brightness register and gets converted to a float.
+ addInstructions(
+ windowIndex,
+ """
+ invoke-virtual { v$brightnessRegister }, Ljava/lang/Float;->floatValue()F
+ move-result v$brightnessRegister
+ """
+ )
+
+ addInstruction(windowIndex, brightnessInstruction)
+
+ } ?: throw BrightnessFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/ads/DisableDashboardAds.kt b/src/main/kotlin/app/revanced/patches/tumblr/ads/DisableDashboardAds.kt
new file mode 100644
index 000000000..09972604a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/ads/DisableDashboardAds.kt
@@ -0,0 +1,37 @@
+package app.revanced.patches.tumblr.ads
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
+
+@Patch(
+ name = "Disable dashboard ads",
+ description = "Disables ads in the dashboard.",
+ compatiblePackages = [CompatiblePackage("com.tumblr")],
+ dependencies = [TimelineFilterPatch::class]
+)
+@Suppress("unused")
+object DisableDashboardAds : BytecodePatch() {
+ override fun execute(context: BytecodeContext) {
+ // The timeline object types are filtered by their name in the TimelineObjectType enum.
+ // This is often different from the "object_type" returned in the api (noted in comments here)
+ arrayOf(
+ "CLIENT_SIDE_MEDIATION", // "client_side_ad_waterfall"
+ "GEMINI_AD", // "backfill_ad"
+
+ // The object types below weren't actually spotted in the wild in testing, but they are valid Object types
+ // and their names clearly indicate that they are ads, so we just block them anyway,
+ // just in case they will be used in the future.
+ "NIMBUS_AD", // "nimbus_ad"
+ "CLIENT_SIDE_AD", // "client_side_ad"
+ "DISPLAY_IO_INTERSCROLLER_AD", // "display_io_interscroller"
+ "DISPLAY_IO_HEADLINE_VIDEO_AD", // "display_io_headline_video"
+ "FACEBOOK_BIDDAABLE", // "facebook_biddable_sdk_ad"
+ "GOOGLE_NATIVE" // "google_native_ad"
+ ).forEach {
+ TimelineFilterPatch.addObjectTypeFilter(it)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/inappupdate/DisableInAppUpdatePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/inappupdate/DisableInAppUpdatePatch.kt
new file mode 100644
index 000000000..574f5c383
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/inappupdate/DisableInAppUpdatePatch.kt
@@ -0,0 +1,22 @@
+package app.revanced.patches.tumblr.annoyances.inappupdate
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch
+
+@Patch(
+ name = "Disable in-app update",
+ description = "Disables the in-app update check and update prompt.",
+ dependencies = [OverrideFeatureFlagsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.tumblr")]
+)
+@Suppress("unused")
+object DisableInAppUpdatePatch : BytecodePatch() {
+ override fun execute(context: BytecodeContext) {
+ // Before checking for updates using Google Play core AppUpdateManager, the value of this feature flag is checked.
+ // If this flag is false or the last update check was today and no update check is performed.
+ OverrideFeatureFlagsPatch.addOverride("inAppUpdate", "false")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/DisableBlogNotificationReminderPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/DisableBlogNotificationReminderPatch.kt
new file mode 100644
index 000000000..e073da5f1
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/DisableBlogNotificationReminderPatch.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.tumblr.annoyances.notifications
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tumblr.annoyances.notifications.fingerprints.IsBlogNotifyEnabledFingerprint
+
+@Patch(
+ name = "Disable blog notification reminder",
+ description = "Disables the reminder to enable notifications for blogs you visit.",
+ compatiblePackages = [CompatiblePackage("com.tumblr")]
+)
+@Suppress("unused")
+object DisableBlogNotificationReminderPatch : BytecodePatch(
+ setOf(IsBlogNotifyEnabledFingerprint)
+) {
+ override fun execute(context: BytecodeContext) =
+ IsBlogNotifyEnabledFingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ # Return false for BlogNotifyCtaDialog.isEnabled() method.
+ const/4 v0, 0x0
+ return v0
+ """
+ ) ?: throw IsBlogNotifyEnabledFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/fingerprints/IsBlogNotifyEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/fingerprints/IsBlogNotifyEnabledFingerprint.kt
new file mode 100644
index 000000000..97d975c3d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/fingerprints/IsBlogNotifyEnabledFingerprint.kt
@@ -0,0 +1,9 @@
+package app.revanced.patches.tumblr.annoyances.notifications.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+// The BlogNotifyCtaDialog asks you if you want to enable notifications for a blog.
+// It shows whenever you visit a certain blog for the second time and disables itself
+// if it was shown a total of 3 times (stored in app storage).
+// This targets the BlogNotifyCtaDialog.isEnabled() method to let it always return false.
+object IsBlogNotifyEnabledFingerprint : MethodFingerprint(strings = listOf("isEnabled --> ", "blog_notify_enabled"))
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/DisableGiftMessagePopupPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/DisableGiftMessagePopupPatch.kt
new file mode 100644
index 000000000..17c15a792
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/DisableGiftMessagePopupPatch.kt
@@ -0,0 +1,23 @@
+package app.revanced.patches.tumblr.annoyances.popups
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tumblr.annoyances.popups.fingerprints.ShowGiftMessagePopupFingerprint
+
+@Patch(
+ name = "Disable gift message popup",
+ description = "Disables the popup suggesting to buy TumblrMart items for other people.",
+ compatiblePackages = [CompatiblePackage("com.tumblr")]
+)
+@Suppress("unused")
+object DisableGiftMessagePopupPatch : BytecodePatch(
+ setOf(ShowGiftMessagePopupFingerprint)
+) {
+ override fun execute(context: BytecodeContext) =
+ ShowGiftMessagePopupFingerprint.result?.mutableMethod?.addInstructions(0, "return-void")
+ ?: throw ShowGiftMessagePopupFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt
new file mode 100644
index 000000000..22ee4015c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt
@@ -0,0 +1,9 @@
+package app.revanced.patches.tumblr.annoyances.popups.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+// This method is responsible for loading and displaying the visual Layout of the Gift Message Popup.
+object ShowGiftMessagePopupFingerprint : MethodFingerprint(
+ strings = listOf("activity", "anchorView"),
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("GiftMessagePopup;") }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt
new file mode 100644
index 000000000..77202534d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt
@@ -0,0 +1,116 @@
+package app.revanced.patches.tumblr.featureflags
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
+import app.revanced.patches.tumblr.featureflags.fingerprints.GetFeatureValueFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
+import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
+import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
+
+@Patch(description = "Forcibly set the value of A/B testing features of your choice.")
+object OverrideFeatureFlagsPatch : BytecodePatch(
+ setOf(GetFeatureValueFingerprint)
+) {
+ /**
+ * Override a feature flag with a value.
+ *
+ * @param name The name of the feature flag to override.
+ * @param value The value to override the feature flag with.
+ */
+ @Suppress("KDocUnresolvedReference")
+ internal lateinit var addOverride: (name: String, value: String) -> Unit private set
+
+ override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let {
+ // The method we want to inject into does not have enough registers, so we inject a helper method
+ // and inject more instructions into it later, see addOverride.
+ // This is not in an integration since the unused variable would get compiled away and the method would
+ // get compiled to only have one register, which is not enough for our later injected instructions.
+ val helperMethod = ImmutableMethod(
+ it.method.definingClass,
+ "getValueOverride",
+ listOf(ImmutableMethodParameter("Lcom/tumblr/configuration/Feature;", null, "feature")),
+ "Ljava/lang/String;",
+ AccessFlags.PUBLIC or AccessFlags.FINAL,
+ null,
+ null,
+ MutableMethodImplementation(4)
+ ).toMutable().apply {
+ // This is the equivalent of
+ // String featureName = feature.toString()
+ //
+ // return null
+ addInstructions(
+ 0,
+ """
+ # toString() the enum value
+ invoke-virtual {p1}, Lcom/tumblr/configuration/Feature;->toString()Ljava/lang/String;
+ move-result-object v0
+
+ # !!! If you add more instructions above this line, update helperInsertIndex below!
+ # Here we will insert one compare & return for every registered Feature override
+ # This is done below in the addOverride function
+
+ # If none of the overrides returned a value, we should return null
+ const/4 v0, 0x0
+ return-object v0
+ """
+ )
+ }.also { helperMethod ->
+ it.mutableClass.methods.add(helperMethod)
+ }
+
+ // Here we actually insert the hook to call our helper method and return its value if it returns not null
+ // This is equivalent to
+ // String forcedValue = getValueOverride(feature)
+ // if (forcedValue != null) return forcedValue
+ val getFeatureIndex = it.scanResult.patternScanResult!!.startIndex
+ it.mutableMethod.addInstructionsWithLabels(
+ getFeatureIndex,
+ """
+ # Call the Helper Method with the Feature
+ invoke-virtual {p0, p1}, Lcom/tumblr/configuration/Configuration;->getValueOverride(Lcom/tumblr/configuration/Feature;)Ljava/lang/String;
+ move-result-object v0
+ # If it returned null, skip
+ if-eqz v0, :is_null
+ # If it didnt return null, return that string
+ return-object v0
+
+ # If our override helper returned null, we let the function continue normally
+ :is_null
+ nop
+ """
+ )
+
+ val helperInsertIndex = 2
+ addOverride = { name, value ->
+ // For every added override, we add a few instructions in the middle of the helper method
+ // to check if the feature is the one we want and return the override value if it is.
+ // This is equivalent to
+ // if (featureName == {name}) return {value}
+ helperMethod.addInstructionsWithLabels(
+ helperInsertIndex,
+ """
+ # v0 is still the string name of the currently checked feature from above
+ # Compare the current string with the override string
+ const-string v1, "$name"
+ invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
+ move-result v1
+ # If the current string is the one we want to override, we return the override value
+ if-eqz v1, :no_override
+ const-string v1, "$value"
+ return-object v1
+ # Else we just continue...
+ :no_override
+ nop
+ """
+ )
+ }
+ } ?: throw GetFeatureValueFingerprint.exception
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt
new file mode 100644
index 000000000..1507b5ddc
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt
@@ -0,0 +1,23 @@
+package app.revanced.patches.tumblr.featureflags.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.Opcode
+
+// This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature".
+// Features seem to be Tumblr's A/B testing program.
+// Feature states are loaded from the server in the "api-http2.tumblr.com/v2/config" request on (first) startup.
+// A lot of features are returned there, but most of them do not seem to do anything (anymore).
+// They were likely removed in newer App versions to always be on, but are still returned
+// as enabled for old App versions.
+// Some features seem to be very old and never removed, though, such as Google Login.
+// The startIndex of the opcode pattern is at the start of the function after the arg null check.
+// we want to insert our instructions there.
+object GetFeatureValueFingerprint : MethodFingerprint(
+ strings = listOf("feature"),
+ opcodes = listOf(
+ Opcode.IF_EQZ,
+ Opcode.INVOKE_STATIC,
+ Opcode.MOVE_RESULT
+ ),
+ customFingerprint = { method, _ -> method.definingClass == "Lcom/tumblr/configuration/Configuration;" }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt
new file mode 100644
index 000000000..1c9ec2a83
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt
@@ -0,0 +1,26 @@
+package app.revanced.patches.tumblr.live
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch
+import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
+
+@Patch(
+ name = "Disable Tumblr Live",
+ description = "Disable the Tumblr Live tab button and dashboard carousel.",
+ dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class],
+ compatiblePackages = [CompatiblePackage("com.tumblr")]
+)
+@Suppress("unused")
+object DisableTumblrLivePatch : BytecodePatch() {
+ override fun execute(context: BytecodeContext) {
+ // Hide the LIVE_MARQUEE timeline element that appears in the feed
+ // Called "live_marquee" in api response
+ TimelineFilterPatch.addObjectTypeFilter("LIVE_MARQUEE")
+
+ // Hide the Tab button for Tumblr Live by forcing the feature flag to false
+ OverrideFeatureFlagsPatch.addOverride("liveStreaming", "false")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/TimelineFilterPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/TimelineFilterPatch.kt
new file mode 100644
index 000000000..f82bb8461
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/TimelineFilterPatch.kt
@@ -0,0 +1,68 @@
+package app.revanced.patches.tumblr.timelinefilter
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.tumblr.timelinefilter.fingerprints.PostsResponseConstructorFingerprint
+import app.revanced.patches.tumblr.timelinefilter.fingerprints.TimelineConstructorFingerprint
+import app.revanced.patches.tumblr.timelinefilter.fingerprints.TimelineFilterIntegrationFingerprint
+import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
+
+@Patch(description = "Filter timeline objects.", requiresIntegrations = true)
+object TimelineFilterPatch : BytecodePatch(
+ setOf(TimelineConstructorFingerprint, TimelineFilterIntegrationFingerprint, PostsResponseConstructorFingerprint)
+) {
+ /**
+ * Add a filter to hide the given timeline object type.
+ * The list of all Timeline object types is found in the TimelineObjectType class,
+ * where they are mapped from their api name (returned by tumblr via the HTTP API) to the enum value name.
+ *
+ * @param typeName The enum name of the timeline object type to hide.
+ */
+ @Suppress("KDocUnresolvedReference")
+ internal lateinit var addObjectTypeFilter: (typeName: String) -> Unit private set
+
+ override fun execute(context: BytecodeContext) {
+ TimelineFilterIntegrationFingerprint.result?.let { integration ->
+ val filterInsertIndex = integration.scanResult.patternScanResult!!.startIndex
+
+ integration.mutableMethod.apply {
+ val addInstruction = getInstruction(filterInsertIndex + 1)
+ if (addInstruction.registerCount != 2) throw TimelineFilterIntegrationFingerprint.exception
+
+ val filterListRegister = addInstruction.registerC
+ val stringRegister = addInstruction.registerD
+
+ // Remove "BLOCKED_OBJECT_DUMMY"
+ removeInstructions(filterInsertIndex, 2)
+
+ addObjectTypeFilter = { typeName ->
+ // blockedObjectTypes.add({typeName})
+ addInstructionsWithLabels(
+ filterInsertIndex, """
+ const-string v$stringRegister, "$typeName"
+ invoke-virtual { v$filterListRegister, v$stringRegister }, Ljava/util/HashSet;->add(Ljava/lang/Object;)Z
+ """
+ )
+ }
+ }
+ } ?: throw TimelineFilterIntegrationFingerprint.exception
+
+ mapOf(
+ TimelineConstructorFingerprint to 1,
+ PostsResponseConstructorFingerprint to 2
+ ).forEach { (fingerprint, timelineObjectsRegister) ->
+ fingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ "invoke-static {p$timelineObjectsRegister}, " +
+ "Lapp/revanced/tumblr/patches/TimelineFilterPatch;->" +
+ "filterTimeline(Ljava/util/List;)V"
+ ) ?: throw fingerprint.exception
+ }
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/PostsResponseConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/PostsResponseConstructorFingerprint.kt
new file mode 100644
index 000000000..cab0a3c30
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/PostsResponseConstructorFingerprint.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.tumblr.timelinefilter.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+// This is the constructor of the PostsResponse class.
+// The same applies here as with the TimelineConstructorFingerprint.
+object PostsResponseConstructorFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.CONSTRUCTOR or AccessFlags.PUBLIC,
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/PostsResponse;") && methodDef.parameters.size == 4 },
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineConstructorFingerprint.kt
new file mode 100644
index 000000000..a8f59c416
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineConstructorFingerprint.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.tumblr.timelinefilter.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+// This is the constructor of the Timeline class.
+// It receives the List as an argument with a @Json annotation, so this should be the first time
+// that the List is exposed in non-library code.
+object TimelineConstructorFingerprint : MethodFingerprint(
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("/Timeline;") && methodDef.parameters[0].type == "Ljava/util/List;"
+ }, strings = listOf("timelineObjectsList")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineFilterIntegrationFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineFilterIntegrationFingerprint.kt
new file mode 100644
index 000000000..9e4a49e4b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineFilterIntegrationFingerprint.kt
@@ -0,0 +1,16 @@
+package app.revanced.patches.tumblr.timelinefilter.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.Opcode
+
+// This fingerprints the Integration TimelineFilterPatch.filterTimeline method.
+// The opcode fingerprint is searching for
+// if ("BLOCKED_OBJECT_DUMMY".equals(elementType)) iterator.remove();
+object TimelineFilterIntegrationFingerprint : MethodFingerprint(
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/TimelineFilterPatch;") },
+ strings = listOf("BLOCKED_OBJECT_DUMMY"),
+ opcodes = listOf(
+ Opcode.CONST_STRING, // "BLOCKED_OBJECT_DUMMY"
+ Opcode.INVOKE_VIRTUAL // HashSet.add(^)
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt b/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/UnlockPaidWidgetsPatch.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt
rename to src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/UnlockPaidWidgetsPatch.kt
index 665ba9f6c..9b11969b4 100644
--- a/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/UnlockPaidWidgetsPatch.kt
@@ -1,20 +1,22 @@
-package app.revanced.patches.twelvewidgets.unlock.patch
+package app.revanced.patches.twelvewidgets.unlock
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.twelvewidgets.unlock.fingerprints.*
-@Patch
-@Name("Unlock paid widgets")
-@Description("Unlocks paid widgets of the app")
-@Compatibility([Package("com.dci.dev.androidtwelvewidgets")])
-class UnlockPaidWidgetsPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Unlock paid widgets",
+ description = "Unlocks paid widgets of the app",
+ compatiblePackages = [CompatiblePackage("com.dci.dev.androidtwelvewidgets")]
+)
+@Suppress("unused")
+object UnlockPaidWidgetsPatch : BytecodePatch(
+ setOf(
AgendaDaysWidgetUnlockFingerprint,
CalendarBigWidgetUnlockFingerprint,
CalendarWideDayEventsWidgetUnlockFingerprint,
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/AudioAdsPatch.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/ad/audio/AudioAdsPatch.kt
index 79c8539d1..ae47f07d1 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/AudioAdsPatch.kt
@@ -1,28 +1,27 @@
-package app.revanced.patches.twitch.ad.audio.patch
+package app.revanced.patches.twitch.ad.audio
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.twitch.ad.audio.annotations.AudioAdsCompatibility
import app.revanced.patches.twitch.ad.audio.fingerprints.AudioAdsPresenterPlayFingerprint
-import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
+import app.revanced.patches.twitch.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Block audio ads")
-@Description("Blocks audio ads in streams and VODs.")
-@AudioAdsCompatibility
-class AudioAdsPatch : BytecodePatch(
- listOf(AudioAdsPresenterPlayFingerprint)
+@Patch(
+ name = "Block audio ads",
+ description = "Blocks audio ads in streams and VODs.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])],
+)
+@Suppress("unused")
+object AudioAdsPatch : BytecodePatch(
+ setOf(AudioAdsPresenterPlayFingerprint)
) {
override fun execute(context: BytecodeContext) {
// Block playAds call
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt
deleted file mode 100644
index b0b80ec49..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.twitch.ad.audio.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AudioAdsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/EmbeddedAdsPatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/ad/embedded/EmbeddedAdsPatch.kt
index bc586883c..3decfdb4a 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/EmbeddedAdsPatch.kt
@@ -1,33 +1,31 @@
-package app.revanced.patches.twitch.ad.embedded.patch
+package app.revanced.patches.twitch.ad.embedded
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
+import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.twitch.ad.embedded.annotations.EmbeddedAdsCompatibility
import app.revanced.patches.twitch.ad.embedded.fingerprints.CreateUsherClientFingerprint
-import app.revanced.patches.twitch.ad.video.patch.VideoAdsPatch
-import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.twitch.ad.video.VideoAdsPatch
+import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
+import app.revanced.patches.twitch.misc.settings.SettingsPatch
-@Patch
-@DependsOn([VideoAdsPatch::class, IntegrationsPatch::class, SettingsPatch::class])
-@Name("Block embedded ads")
-@Description("Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker.")
-@EmbeddedAdsCompatibility
-class EmbeddedAdsPatch : BytecodePatch(
- listOf(CreateUsherClientFingerprint)
+@Patch(
+ name = "Block embedded ads",
+ description = "Blocks embedded stream ads using services like Luminous or PurpleAdBlocker.",
+ dependencies = [VideoAdsPatch::class, IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])]
+)
+@Suppress("unused")
+object EmbeddedAdsPatch : BytecodePatch(
+ setOf(CreateUsherClientFingerprint)
) {
override fun execute(context: BytecodeContext) {
- val result = CreateUsherClientFingerprint.result ?: throw PatchException("${CreateUsherClientFingerprint.name} not found")
+ val result = CreateUsherClientFingerprint.result ?: throw CreateUsherClientFingerprint.exception
// Inject OkHttp3 application interceptor
result.mutableMethod.addInstructions(
@@ -50,7 +48,7 @@ class EmbeddedAdsPatch : BytecodePatch(
"revanced_hls_proxies",
listOf(
StringResource("revanced_proxy_disabled", "Disabled"),
- StringResource("revanced_proxy_ttv_lol", "TTV LOL proxy"),
+ StringResource("revanced_proxy_luminous", "Luminous proxy"),
StringResource("revanced_proxy_purpleadblock", "PurpleAdBlock proxy"),
)
),
@@ -58,11 +56,11 @@ class EmbeddedAdsPatch : BytecodePatch(
"revanced_hls_proxies_values",
listOf(
StringResource("key_revanced_proxy_disabled", "disabled"),
- StringResource("key_revanced_proxy_ttv_lol", "ttv-lol"),
+ StringResource("key_revanced_proxy_luminous", "luminous"),
StringResource("key_revanced_proxy_purpleadblock", "purpleadblock")
)
),
- default = "ttv-lol"
+ default = "luminous"
)
)
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/annotations/EmbeddedAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/annotations/EmbeddedAdsCompatibility.kt
deleted file mode 100644
index 5f72b4744..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/annotations/EmbeddedAdsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.twitch.ad.embedded.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1", "16.1.0"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class EmbeddedAdsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AbstractAdPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AbstractAdPatch.kt
index 041570b20..8dc505a67 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AbstractAdPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AbstractAdPatch.kt
@@ -10,7 +10,7 @@ import app.revanced.patcher.util.smali.ExternalLabel
abstract class AbstractAdPatch(
val conditionCall: String,
val skipLabelName: String,
- internal val fingerprints: Iterable? = null,
+ internal val fingerprints: Set = emptySet(),
) : BytecodePatch(fingerprints) {
protected fun createConditionInstructions(register: String = "v0") = """
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/VideoAdsPatch.kt
similarity index 88%
rename from src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/ad/video/VideoAdsPatch.kt
index 12ab6178e..b6fffe067 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/VideoAdsPatch.kt
@@ -1,34 +1,32 @@
-package app.revanced.patches.twitch.ad.video.patch
+package app.revanced.patches.twitch.ad.video
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.twitch.ad.shared.util.AbstractAdPatch
-import app.revanced.patches.twitch.ad.video.annotations.VideoAdsCompatibility
import app.revanced.patches.twitch.ad.video.fingerprints.CheckAdEligibilityLambdaFingerprint
import app.revanced.patches.twitch.ad.video.fingerprints.ContentConfigShowAdsFingerprint
import app.revanced.patches.twitch.ad.video.fingerprints.GetReadyToShowAdFingerprint
-import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
+import app.revanced.patches.twitch.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Block video ads")
-@Description("Blocks video ads in streams and VODs.")
-@VideoAdsCompatibility
-class VideoAdsPatch : AbstractAdPatch(
+@Patch(
+ name = "Block video ads",
+ description = "Blocks video ads in streams and VODs.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])]
+)
+object VideoAdsPatch : AbstractAdPatch(
"Lapp/revanced/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z",
"show_video_ads",
- listOf(
+ setOf(
ContentConfigShowAdsFingerprint,
CheckAdEligibilityLambdaFingerprint,
GetReadyToShowAdFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt
deleted file mode 100644
index 5f84ee957..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.twitch.ad.video.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1", "16.1.0"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class VideoAdsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/ShowDeletedMessagesPatch.kt
similarity index 84%
rename from src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/ShowDeletedMessagesPatch.kt
index caea45925..3e41e8650 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/ShowDeletedMessagesPatch.kt
@@ -1,33 +1,32 @@
-package app.revanced.patches.twitch.chat.antidelete.patch
+package app.revanced.patches.twitch.chat.antidelete
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.twitch.chat.antidelete.annotations.ShowDeletedMessagesCompatibility
import app.revanced.patches.twitch.chat.antidelete.fingerprints.ChatUtilCreateDeletedSpanFingerprint
import app.revanced.patches.twitch.chat.antidelete.fingerprints.DeletedMessageClickableSpanCtorFingerprint
import app.revanced.patches.twitch.chat.antidelete.fingerprints.SetHasModAccessFingerprint
-import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
+import app.revanced.patches.twitch.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Show deleted messages")
-@Description("Shows deleted chat messages behind a clickable spoiler.")
-@ShowDeletedMessagesCompatibility
-class ShowDeletedMessagesPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Show deleted messages",
+ description = "Shows deleted chat messages behind a clickable spoiler.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])]
+)
+@Suppress("unused")
+object ShowDeletedMessagesPatch : BytecodePatch(
+ setOf(
SetHasModAccessFingerprint,
DeletedMessageClickableSpanCtorFingerprint,
ChatUtilCreateDeletedSpanFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt
deleted file mode 100644
index a6c1d1d08..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.twitch.chat.antidelete.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1", "16.1.0"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ShowDeletedMessagesCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/AutoClaimChannelPointsPatch.kt
similarity index 76%
rename from src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/AutoClaimChannelPointsPatch.kt
index 3eeea6058..8a23e047d 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/AutoClaimChannelPointsPatch.kt
@@ -1,28 +1,27 @@
-package app.revanced.patches.twitch.chat.autoclaim.patch
+package app.revanced.patches.twitch.chat.autoclaim
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.twitch.chat.autoclaim.annotations.AutoClaimChannelPointsCompatibility
import app.revanced.patches.twitch.chat.autoclaim.fingerprints.CommunityPointsButtonViewDelegateFingerprint
-import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.twitch.misc.settings.SettingsPatch
-@Patch
-@DependsOn([SettingsPatch::class])
-@Name("Auto claim channel points")
-@Description("Automatically claim Channel Points.")
-@AutoClaimChannelPointsCompatibility
-class AutoClaimChannelPointPatch : BytecodePatch(
- listOf(CommunityPointsButtonViewDelegateFingerprint)
+@Patch(
+ name = "Auto claim channel points",
+ description = "Automatically claim Channel Points.",
+ dependencies = [SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])]
+)
+@Suppress("unused")
+object AutoClaimChannelPointPatch : BytecodePatch(
+ setOf(CommunityPointsButtonViewDelegateFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.CHAT.GENERAL.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/annotations/AutoClaimChannelPointsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/annotations/AutoClaimChannelPointsCompatibility.kt
deleted file mode 100644
index 85f708bb0..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/annotations/AutoClaimChannelPointsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.twitch.chat.autoclaim.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1", "16.1.0"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AutoClaimChannelPointsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/DebugModePatch.kt
similarity index 74%
rename from src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/debug/DebugModePatch.kt
index a38e80db8..ecfe0c5d3 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/DebugModePatch.kt
@@ -1,29 +1,29 @@
-package app.revanced.patches.twitch.debug.patch
+package app.revanced.patches.twitch.debug
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.twitch.debug.annotations.DebugModeCompatibility
import app.revanced.patches.twitch.debug.fingerprints.IsDebugConfigEnabledFingerprint
import app.revanced.patches.twitch.debug.fingerprints.IsOmVerificationEnabledFingerprint
import app.revanced.patches.twitch.debug.fingerprints.ShouldShowDebugOptionsFingerprint
-import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
+import app.revanced.patches.twitch.misc.settings.SettingsPatch
-@Patch(false)
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Debug mode")
-@Description("Enables Twitch's internal debugging mode.")
-@DebugModeCompatibility
-class DebugModePatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Debug mode",
+ description = "Enables Twitch's internal debugging mode.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("tv.twitch.android.app")],
+ use = false
+)
+@Suppress("unused")
+object DebugModePatch : BytecodePatch(
+ setOf(
IsDebugConfigEnabledFingerprint,
IsOmVerificationEnabledFingerprint,
ShouldShowDebugOptionsFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt
deleted file mode 100644
index 078bae90d..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.twitch.debug.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DebugModeCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/IntegrationsPatch.kt
new file mode 100644
index 000000000..66f6b035c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/IntegrationsPatch.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.twitch.misc.integrations
+
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch
+import app.revanced.patches.twitch.misc.integrations.fingerprints.InitFingerprint
+
+@Patch(requiresIntegrations = true)
+object IntegrationsPatch : AbstractIntegrationsPatch(
+ "Lapp/revanced/twitch/utils/ReVancedUtils;",
+ setOf(InitFingerprint)
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt
index 7eb3dfc2b..a508206a6 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt
@@ -1,9 +1,7 @@
package app.revanced.patches.twitch.misc.integrations.fingerprints
-import app.revanced.patcher.annotation.Name
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
-@Name("Init fingerprint")
object InitFingerprint : IntegrationsFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/TwitchApplication;") &&
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/patch/IntegrationsPatch.kt
deleted file mode 100644
index 21f7da9c8..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/patch/IntegrationsPatch.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.twitch.misc.integrations.patch
-
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
-import app.revanced.patches.twitch.misc.integrations.fingerprints.InitFingerprint
-
-@Name("Integrations")
-@RequiresIntegrations
-class IntegrationsPatch : AbstractIntegrationsPatch(
- "Lapp/revanced/twitch/utils/ReVancedUtils;",
- listOf(InitFingerprint)
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/SettingsPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitch/misc/settings/SettingsPatch.kt
index 8aec9bb52..b45bb2b9c 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/SettingsPatch.kt
@@ -1,8 +1,6 @@
-package app.revanced.patches.twitch.misc.settings.bytecode.patch
+package app.revanced.patches.twitch.misc.settings
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
@@ -10,37 +8,51 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.PreferenceCategory
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
-import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.twitch.misc.settings.annotations.SettingsCompatibility
+import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsOnClickFingerprint
import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsUpdatedFingerprint
import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsActivityOnCreateFingerprint
import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsMenuItemEnumFingerprint
-import app.revanced.patches.twitch.misc.settings.resource.patch.SettingsResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.immutable.ImmutableField
import java.io.Closeable
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsResourcePatch::class])
-@Name("Settings")
-@Description("Adds settings menu to Twitch.")
-@SettingsCompatibility
-class SettingsPatch : BytecodePatch(
- listOf(
+
+@Patch(
+ name = "Settings",
+ description = "Adds settings menu to Twitch.",
+ dependencies = [IntegrationsPatch::class, SettingsResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage("tv.twitch.android.app")
+ ]
+)
+object SettingsPatch : BytecodePatch(
+ setOf(
SettingsActivityOnCreateFingerprint,
SettingsMenuItemEnumFingerprint,
MenuGroupsUpdatedFingerprint,
MenuGroupsOnClickFingerprint
)
), Closeable {
+ private const val REVANCED_SETTINGS_MENU_ITEM_NAME = "RevancedSettings"
+ private const val REVANCED_SETTINGS_MENU_ITEM_ID = 0x7
+ private const val REVANCED_SETTINGS_MENU_ITEM_TITLE_RES = "revanced_settings"
+ private const val REVANCED_SETTINGS_MENU_ITEM_ICON_RES = "ic_settings"
+
+ private const val MENU_ITEM_ENUM_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuItem;"
+ private const val MENU_DISMISS_EVENT_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuViewDelegate\$Event\$OnDismissClicked;"
+
+ private const val INTEGRATIONS_PACKAGE = "app/revanced/twitch"
+ private const val SETTINGS_HOOKS_CLASS = "L$INTEGRATIONS_PACKAGE/settingsmenu/SettingsHooks;"
+ private const val REVANCED_UTILS_CLASS = "L$INTEGRATIONS_PACKAGE/utils/ReVancedUtils;"
+
override fun execute(context: BytecodeContext) {
// Hook onCreate to handle fragment creation
SettingsActivityOnCreateFingerprint.result?.apply {
@@ -102,49 +114,35 @@ class SettingsPatch : BytecodePatch(
addString("revanced_cancel", "Cancel", false)
}
- internal companion object {
- fun addString(identifier: String, value: String, formatted: Boolean = true) =
- SettingsResourcePatch.addString(identifier, value, formatted)
+ fun addString(identifier: String, value: String, formatted: Boolean = true) =
+ SettingsResourcePatch.addString(identifier, value, formatted)
- fun addPreferenceScreen(preferenceScreen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) =
- SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
+ fun addPreferenceScreen(preferenceScreen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) =
+ SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
- /* Private members */
- private const val REVANCED_SETTINGS_MENU_ITEM_NAME = "RevancedSettings"
- private const val REVANCED_SETTINGS_MENU_ITEM_ID = 0x7
- private const val REVANCED_SETTINGS_MENU_ITEM_TITLE_RES = "revanced_settings"
- private const val REVANCED_SETTINGS_MENU_ITEM_ICON_RES = "ic_settings"
+ private fun MethodFingerprintResult.injectMenuItem(
+ name: String,
+ value: Int,
+ titleResourceName: String,
+ iconResourceName: String
+ ) {
+ // Add new static enum member field
+ mutableClass.staticFields.add(
+ ImmutableField(
+ mutableMethod.definingClass,
+ name,
+ MENU_ITEM_ENUM_CLASS,
+ AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.ENUM or AccessFlags.STATIC,
+ null,
+ null,
+ null
+ ).toMutable()
+ )
- private const val MENU_ITEM_ENUM_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuItem;"
- private const val MENU_DISMISS_EVENT_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuViewDelegate\$Event\$OnDismissClicked;"
-
- private const val INTEGRATIONS_PACKAGE = "app/revanced/twitch"
- private const val SETTINGS_HOOKS_CLASS = "L$INTEGRATIONS_PACKAGE/settingsmenu/SettingsHooks;"
- private const val REVANCED_UTILS_CLASS = "L$INTEGRATIONS_PACKAGE/utils/ReVancedUtils;"
-
- private fun MethodFingerprintResult.injectMenuItem(
- name: String,
- value: Int,
- titleResourceName: String,
- iconResourceName: String
- ) {
- // Add new static enum member field
- mutableClass.staticFields.add(
- ImmutableField(
- mutableMethod.definingClass,
- name,
- MENU_ITEM_ENUM_CLASS,
- AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.ENUM or AccessFlags.STATIC,
- null,
- null,
- null
- ).toMutable()
- )
-
- // Add initializer for the new enum member
- mutableMethod.addInstructions(
- mutableMethod.implementation!!.instructions.size - 4,
- """
+ // Add initializer for the new enum member
+ mutableMethod.addInstructions(
+ mutableMethod.implementation!!.instructions.size - 4,
+ """
new-instance v0, $MENU_ITEM_ENUM_CLASS
const-string v1, "$titleResourceName"
invoke-static {v1}, $REVANCED_UTILS_CLASS->getStringId(Ljava/lang/String;)I
@@ -157,8 +155,7 @@ class SettingsPatch : BytecodePatch(
invoke-direct {v0, v4, v5, v1, v3}, $MENU_ITEM_ENUM_CLASS->(Ljava/lang/String;III)V
sput-object v0, $MENU_ITEM_ENUM_CLASS->$name:$MENU_ITEM_ENUM_CLASS
"""
- )
- }
+ )
}
/**
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/SettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/SettingsResourcePatch.kt
new file mode 100644
index 000000000..f61784611
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/SettingsResourcePatch.kt
@@ -0,0 +1,36 @@
+package app.revanced.patches.twitch.misc.settings
+
+import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch
+import app.revanced.patches.shared.settings.preference.impl.ArrayResource
+import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
+
+object SettingsResourcePatch : AbstractSettingsResourcePatch(
+"revanced_prefs",
+"twitch/settings"
+) {
+ /* Companion delegates */
+
+ /**
+ * Add a new string to the resources.
+ *
+ * @param identifier The key of the string.
+ * @param value The value of the string.
+ * @throws IllegalArgumentException if the string already exists.
+ */
+ fun addString(identifier: String, value: String, formatted: Boolean) =
+ AbstractSettingsResourcePatch.addString(identifier, value, formatted)
+
+ /**
+ * Add an array to the resources.
+ *
+ * @param arrayResource The array resource to add.
+ */
+ fun addArray(arrayResource: ArrayResource) = AbstractSettingsResourcePatch.addArray(arrayResource)
+
+ /**
+ * Add a preference to the settings.
+ *
+ * @param preferenceScreen The name of the preference screen.
+ */
+ fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = AbstractSettingsResourcePatch.addPreference(preferenceScreen)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/annotations/SettingsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/annotations/SettingsCompatibility.kt
deleted file mode 100644
index 2b632f8ee..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/annotations/SettingsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.twitch.misc.settings.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("tv.twitch.android.app")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class SettingsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/resource/patch/SettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/resource/patch/SettingsResourcePatch.kt
deleted file mode 100644
index 46feadd4a..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/resource/patch/SettingsResourcePatch.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package app.revanced.patches.twitch.misc.settings.resource.patch
-
-import app.revanced.patches.shared.settings.preference.impl.ArrayResource
-import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
-import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch
-
-class SettingsResourcePatch : AbstractSettingsResourcePatch(
-"revanced_prefs",
-"twitch/settings"
-) {
- internal companion object {
- /* Companion delegates */
-
- /**
- * Add a new string to the resources.
- *
- * @param identifier The key of the string.
- * @param value The value of the string.
- * @throws IllegalArgumentException if the string already exists.
- */
- fun addString(identifier: String, value: String, formatted: Boolean) =
- AbstractSettingsResourcePatch.addString(identifier, value, formatted)
-
- /**
- * Add an array to the resources.
- *
- * @param arrayResource The array resource to add.
- */
- fun addArray(arrayResource: ArrayResource) = AbstractSettingsResourcePatch.addArray(arrayResource)
-
- /**
- * Add a preference to the settings.
- *
- * @param preferenceScreen The name of the preference screen.
- */
- fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = AbstractSettingsResourcePatch.addPreference(preferenceScreen)
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt
index 2ba9d29c9..ec7715b22 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt
@@ -1,20 +1,20 @@
-package app.revanced.patches.twitter.misc.dynamiccolor.patch
+package app.revanced.patches.twitter.misc.dynamiccolor
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.twitter.misc.dynamiccolor.annotations.DynamicColorCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import java.io.FileWriter
import java.nio.file.Files
-@Patch
-@Name("Dynamic color")
-@Description("Replaces the default Twitter Blue with the users Material You palette.")
-@DynamicColorCompatibility
-class DynamicColorPatch : ResourcePatch {
+@Patch(
+ name = "Dynamic color",
+ description = "Replaces the default Twitter Blue with the user's Material You palette.",
+ compatiblePackages = [CompatiblePackage("com.twitter.android")]
+)
+@Suppress("unused")
+object DynamicColorPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
val resDirectory = context["res"]
if (!resDirectory.isDirectory) throw PatchException("The res folder can not be found.")
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt
deleted file mode 100644
index 3015f29f0..000000000
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.twitter.misc.dynamiccolor.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.twitter.android")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DynamicColorCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt
similarity index 81%
rename from src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
rename to src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt
index f5da4ddae..d2b8a9e7d 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt
@@ -1,7 +1,5 @@
-package app.revanced.patches.twitter.misc.hook.json.patch
+package app.revanced.patches.twitter.misc.hook.json
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
@@ -9,19 +7,32 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonHookPatchFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonInputStreamFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint
import java.io.Closeable
import java.io.InvalidClassException
-@Name("Json hook")
-@Description("Hooks the stream which reads JSON responses.")
-@RequiresIntegrations
-class JsonHookPatch : BytecodePatch(
- listOf(LoganSquareFingerprint)
+@Patch(
+ description = "Hooks the stream which reads JSON responses.",
+ requiresIntegrations = true
+)
+object JsonHookPatch : BytecodePatch(
+ setOf(LoganSquareFingerprint)
), Closeable {
+ private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
+ private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
+ private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
+ private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
+
+ /**
+ * The [JsonHookPatchHook] of the [JsonHookPatch].
+ *
+ * @see JsonHookPatchHook
+ */
+ internal lateinit var hooks: JsonHookPatchHook
+
override fun execute(context: BytecodeContext) {
JsonHookPatchFingerprint.also {
// Make sure the integrations are present.
@@ -65,7 +76,8 @@ class JsonHookPatch : BytecodePatch(
* @param descriptor The class descriptor of the hook.
* @throws ClassNotFoundException If the class could not be found.
*/
- internal class Hook(context: BytecodeContext, internal val descriptor: String) {
+ internal class
+ Hook(context: BytecodeContext, internal val descriptor: String) {
internal var added = false
init {
@@ -127,21 +139,4 @@ class JsonHookPatch : BytecodePatch(
override fun close() = hooks.close()
- internal companion object {
- private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
-
- private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
-
- private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
-
- private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
-
- /**
- * The [JsonHookPatchHook] of the [JsonHookPatch].
- *
- * @see JsonHookPatchHook
- */
- internal lateinit var hooks: JsonHookPatchHook
- }
-
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
index e115d2c1c..39d5c296c 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
@@ -2,7 +2,7 @@ package app.revanced.patches.twitter.misc.hook.patch
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
+import app.revanced.patches.twitter.misc.hook.json.JsonHookPatch
abstract class BaseHookPatchPatch(private val hookClassDescriptor: String) : BytecodePatch() {
override fun execute(context: BytecodeContext) =
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/HideAdsPatch.kt
new file mode 100644
index 000000000..40ff710bc
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/HideAdsPatch.kt
@@ -0,0 +1,15 @@
+package app.revanced.patches.twitter.misc.hook.patch.ads
+
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.twitter.misc.hook.json.JsonHookPatch
+import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
+
+@Patch(
+ name = "Hide ads",
+ description = "Hides ads.",
+ dependencies = [JsonHookPatch::class],
+ compatiblePackages = [CompatiblePackage("com.twitter.android")]
+)
+@Suppress("unused")
+object HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt
deleted file mode 100644
index d44fa95e0..000000000
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.twitter.misc.hook.patch.ads.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.twitter.android")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideAdsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt
deleted file mode 100644
index e978c5d67..000000000
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package app.revanced.patches.twitter.misc.hook.patch.ads.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
-import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
-import app.revanced.patches.twitter.misc.hook.patch.ads.annotations.HideAdsCompatibility
-
-@Patch
-@Name("Hide ads")
-@DependsOn([JsonHookPatch::class])
-@Description("Hides ads.")
-@HideAdsCompatibility
-class HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch.kt
new file mode 100644
index 000000000..d510df7d5
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch.kt
@@ -0,0 +1,16 @@
+package app.revanced.patches.twitter.misc.hook.patch.recommendation
+
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.twitter.misc.hook.json.JsonHookPatch
+import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
+
+@Patch(
+ name = "Hide recommended users",
+ dependencies = [JsonHookPatch::class],
+ compatiblePackages = [CompatiblePackage("com.twitter.android")]
+)
+@Suppress("unused")
+object HideRecommendedUsersPatch : BaseHookPatchPatch(
+ "Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt
deleted file mode 100644
index 196482e91..000000000
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.twitter.misc.hook.patch.recommendation.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.twitter.android")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideRecommendedUsersCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt
deleted file mode 100644
index c4c9bc084..000000000
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package app.revanced.patches.twitter.misc.hook.patch.recommendation.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
-import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
-import app.revanced.patches.twitter.misc.hook.patch.recommendation.annotations.HideRecommendedUsersCompatibility
-
-@Patch
-@Name("Hide recommended users")
-@DependsOn([JsonHookPatch::class])
-@Description("Hides recommended users.")
-@HideRecommendedUsersCompatibility
-class HideRecommendedUsersPatch : BaseHookPatchPatch(
- "Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/vsco/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/vsco/misc/pro/UnlockProPatch.kt
similarity index 64%
rename from src/main/kotlin/app/revanced/patches/vsco/misc/pro/patch/UnlockProPatch.kt
rename to src/main/kotlin/app/revanced/patches/vsco/misc/pro/UnlockProPatch.kt
index 5df0ec811..5d2ebb9ef 100644
--- a/src/main/kotlin/app/revanced/patches/vsco/misc/pro/patch/UnlockProPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/vsco/misc/pro/UnlockProPatch.kt
@@ -1,20 +1,20 @@
-package app.revanced.patches.vsco.misc.pro.patch
+package app.revanced.patches.vsco.misc.pro
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.vsco.misc.pro.fingerprints.RevCatSubscriptionFingerprint
-
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks pro features.")
-@Compatibility([Package("com.vsco.cam")])
-class UnlockProPatch : BytecodePatch(
- listOf(RevCatSubscriptionFingerprint)
+@Patch(
+ name = "Unlock pro",
+ description = "Unlocks pro features.",
+ compatiblePackages = [CompatiblePackage("com.vsco.cam")]
+)
+object UnlockProPatch : BytecodePatch(
+ setOf(RevCatSubscriptionFingerprint)
) {
override fun execute(context: BytecodeContext) {
RevCatSubscriptionFingerprint.result?.mutableMethod?.apply {
diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/FirebaseGetCertPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt
rename to src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/FirebaseGetCertPatch.kt
index e0dab0cbc..c3e4e769d 100644
--- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/FirebaseGetCertPatch.kt
@@ -1,19 +1,19 @@
-package app.revanced.patches.warnwetter.misc.firebasegetcert.patch
+package app.revanced.patches.warnwetter.misc.firebasegetcert
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints.GetMessagingCertFingerprint
import app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints.GetReqistrationCertFingerprint
-@Name("Spoof cert patch")
-@Description("Spoofs the X-Android-Cert header.")
-@FirebaseGetCertPatchCompatibility
-class FirebaseGetCertPatch : BytecodePatch(
- listOf(
+@Patch(
+ description = "Spoofs the X-Android-Cert header.",
+ compatiblePackages = [CompatiblePackage("de.dwd.warnapp")]
+)
+object FirebaseGetCertPatch : BytecodePatch(
+ setOf(
GetReqistrationCertFingerprint,
GetMessagingCertFingerprint
)
diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt
deleted file mode 100644
index 2a8f63791..000000000
--- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-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")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class FirebaseGetCertPatchCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnlockPatch.kt
new file mode 100644
index 000000000..2f40f8aef
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnlockPatch.kt
@@ -0,0 +1,31 @@
+package app.revanced.patches.warnwetter.misc.promocode
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.warnwetter.misc.firebasegetcert.FirebaseGetCertPatch
+import app.revanced.patches.warnwetter.misc.promocode.fingerprints.PromoCodeUnlockFingerprint
+
+@Patch(
+ name = "Promo code unlock",
+ description = "Disables the validation of promo code. Any code will work to unlock all features.",
+ dependencies = [FirebaseGetCertPatch::class],
+ compatiblePackages = [CompatiblePackage("de.dwd.warnapp")]
+)
+@Suppress("unused")
+object PromoCodeUnlockPatch : BytecodePatch(
+ setOf(PromoCodeUnlockFingerprint)
+) {
+ override fun execute(context: BytecodeContext) {
+ val method = PromoCodeUnlockFingerprint.result!!.mutableMethod
+ method.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt
deleted file mode 100644
index c82c22c02..000000000
--- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-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")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PromoCodeUnlockCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt
deleted file mode 100644
index 8fda000b7..000000000
--- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package app.revanced.patches.warnwetter.misc.promocode.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-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
-class PromoCodeUnlockPatch : BytecodePatch(
- listOf(
- PromoCodeUnlockFingerprint
- )
-) {
-
- override fun execute(context: BytecodeContext) {
- val method = PromoCodeUnlockFingerprint.result!!.mutableMethod
- method.addInstructions(
- 0,
- """
- const/4 v0, 0x1
- return v0
- """
- )
- }
-
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/patch/UnlockProPatch.kt
rename to src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch.kt
index bf1b72089..7bb5e121a 100644
--- a/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/patch/UnlockProPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch.kt
@@ -1,22 +1,20 @@
-package app.revanced.patches.windyapp.misc.unlockpro.patch
+package app.revanced.patches.windyapp.misc.unlockpro
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.windyapp.misc.unlockpro.annotations.UnlockProCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.windyapp.misc.unlockpro.fingerprints.CheckProFingerprint
-@Patch
-@Name("Unlock pro")
-@Description("Unlocks all pro features.")
-@UnlockProCompatibility
-class UnlockProPatch : BytecodePatch(
- listOf(
- CheckProFingerprint
- )
+@Patch(
+ name = "Unlock pro",
+ description = "Unlocks all pro features.",
+ compatiblePackages = [CompatiblePackage("co.windyapp.android")]
+)
+@Suppress("unused")
+object UnlockProPatch : BytecodePatch(
+ setOf(CheckProFingerprint)
) {
override fun execute(context: BytecodeContext) {
val method = CheckProFingerprint.result!!.mutableMethod
diff --git a/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/annotations/UnlockProCompatibility.kt
deleted file mode 100644
index fecdfb21c..000000000
--- a/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/annotations/UnlockProCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.windyapp.misc.unlockpro.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("co.windyapp.android")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt
index ea2eb2d07..e19765ba8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt
@@ -1,36 +1,44 @@
-package app.revanced.patches.youtube.ad.general.bytecode.patch
+package app.revanced.patches.youtube.ad.general
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.injectHideViewCall
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
-import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
-import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
-import app.revanced.patches.youtube.ad.getpremium.bytecode.patch.HideGetPremiumPatch
-import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.misc.fix.verticalscroll.VerticalScrollPatch
+import app.revanced.patches.youtube.ad.getpremium.HideGetPremiumPatch
+import app.revanced.patches.youtube.misc.fix.backtoexitgesture.FixBackToExitGesturePatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
-
-@Patch
-@DependsOn(
- [
+@Patch(
+ name = "Hide ads",
+ description = "Removes general ads.",
+ dependencies = [
HideGetPremiumPatch::class,
HideAdsResourcePatch::class,
VerticalScrollPatch::class,
FixBackToExitGesturePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
]
)
-@Name("Hide ads")
-@Description("Removes general ads.")
-@HideAdsCompatibility
-class HideAdsPatch : BytecodePatch() {
+@Suppress("unused")
+object HideAdsPatch : BytecodePatch() {
override fun execute(context: BytecodeContext) {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/HideAdsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsResourcePatch.kt
similarity index 80%
rename from src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/HideAdsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsResourcePatch.kt
index 7967f66d8..f701fab3e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/HideAdsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsResourcePatch.kt
@@ -1,25 +1,28 @@
-package app.revanced.patches.youtube.ad.general.resource.patch
+package app.revanced.patches.youtube.ad.general
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
-@DependsOn(
- [
+@Patch(
+ dependencies = [
LithoFilterPatch::class,
SettingsPatch::class,
ResourceMappingPatch::class
]
)
-@HideAdsCompatibility
-class HideAdsResourcePatch : ResourcePatch {
+object HideAdsResourcePatch : ResourcePatch() {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/AdsFilter;"
+
+ internal var adAttributionId: Long = -1
+
override fun execute(context: ResourceContext) {
PreferenceScreen.ADS.addPreferences(
SwitchPreference(
@@ -70,11 +73,4 @@ class HideAdsResourcePatch : ResourcePatch {
adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
}
-
- internal companion object {
- var adAttributionId: Long = -1
-
- private const val FILTER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/components/AdsFilter;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/HideAdsCompatibility.kt
deleted file mode 100644
index ee7b19831..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/HideAdsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.ad.general.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideAdsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt
index 1748b6008..139bec006 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt
@@ -1,24 +1,40 @@
-package app.revanced.patches.youtube.ad.getpremium.bytecode.patch
+package app.revanced.patches.youtube.ad.getpremium
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.ad.getpremium.annotations.HideGetPremiumCompatibility
-import app.revanced.patches.youtube.ad.getpremium.bytecode.fingerprints.GetPremiumViewFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.ad.getpremium.fingerprints.GetPremiumViewFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Hide get premium")
-@HideGetPremiumCompatibility
-class HideGetPremiumPatch : BytecodePatch(listOf(GetPremiumViewFingerprint)) {
+@Patch(
+ name = "Hide get premium",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideGetPremiumPatch;"
+
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.ADS.addPreferences(
SwitchPreference(
@@ -64,9 +80,4 @@ class HideGetPremiumPatch : BytecodePatch(listOf(GetPremiumViewFingerprint)) {
}
} ?: throw GetPremiumViewFingerprint.exception
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/HideGetPremiumPatch;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/annotations/HideGetPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/annotations/HideGetPremiumCompatibility.kt
deleted file mode 100644
index 7bbef9765..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/annotations/HideGetPremiumCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.ad.getpremium.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideGetPremiumCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/fingerprints/GetPremiumViewFingerprint.kt
similarity index 91%
rename from src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/fingerprints/GetPremiumViewFingerprint.kt
index 9f578996f..3ed58ed0a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/fingerprints/GetPremiumViewFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.ad.getpremium.bytecode.fingerprints
+package app.revanced.patches.youtube.ad.getpremium.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt
index 1df08ae80..31e442ee3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt
@@ -1,30 +1,43 @@
-package app.revanced.patches.youtube.ad.video.patch
+package app.revanced.patches.youtube.ad.video
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility
import app.revanced.patches.youtube.ad.video.fingerprints.LoadVideoAdsFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Video ads")
-@Description("Removes ads in the video player.")
-@VideoAdsCompatibility
-class VideoAdsPatch : BytecodePatch(
- listOf(
- LoadVideoAdsFingerprint,
- )
+@Patch(
+ name = "Video ads",
+ description = "Removes ads in the video player.",
+ dependencies = [
+ IntegrationsPatch::class,
+ SettingsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object VideoAdsPatch : BytecodePatch(
+ setOf(LoadVideoAdsFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.ADS.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt
deleted file mode 100644
index 0ed6826e4..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.ad.video.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class VideoAdsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt
new file mode 100644
index 000000000..e9638043f
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt
@@ -0,0 +1,48 @@
+package app.revanced.patches.youtube.interaction.copyvideourl
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
+import app.revanced.patches.youtube.video.information.VideoInformationPatch
+
+@Patch(
+ name = "Copy video url",
+ description = "Adds buttons in player to copy video links.",
+ dependencies = [
+ CopyVideoUrlResourcePatch::class,
+ PlayerControlsBytecodePatch::class,
+ VideoInformationPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object CopyVideoUrlBytecodePatch : BytecodePatch() {
+ private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
+ private val BUTTONS_DESCRIPTORS = listOf(
+ "$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
+ "$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
+ )
+
+ override fun execute(context: BytecodeContext) {
+ // Initialize buttons and inject visibility control
+ BUTTONS_DESCRIPTORS.forEach { descriptor ->
+ PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
+ PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlResourcePatch.kt
similarity index 85%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlResourcePatch.kt
index 48a265e8a..7720265eb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlResourcePatch.kt
@@ -1,19 +1,24 @@
-package app.revanced.patches.youtube.interaction.copyvideourl.resource.patch
+package app.revanced.patches.youtube.interaction.copyvideourl
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
-@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
-class CopyVideoUrlResourcePatch : ResourcePatch {
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ BottomControlsResourcePatch::class
+ ]
+)
+object CopyVideoUrlResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
PreferenceScreen(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt
deleted file mode 100644
index de373a122..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.interaction.copyvideourl.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class CopyVideoUrlCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt
deleted file mode 100644
index ba80eb1ad..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package app.revanced.patches.youtube.interaction.copyvideourl.bytecode.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.interaction.copyvideourl.annotation.CopyVideoUrlCompatibility
-import app.revanced.patches.youtube.interaction.copyvideourl.resource.patch.CopyVideoUrlResourcePatch
-import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
-import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
-
-@Patch
-@Name("Copy video url")
-@Description("Adds buttons in player to copy video links.")
-@DependsOn([
- CopyVideoUrlResourcePatch::class,
- PlayerControlsBytecodePatch::class,
- VideoInformationPatch::class
-])
-@CopyVideoUrlCompatibility
-class CopyVideoUrlBytecodePatch : BytecodePatch() {
- private companion object {
- const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
- val BUTTONS_DESCRIPTORS = listOf(
- "$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
- "$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
- )
- }
-
- override fun execute(context: BytecodeContext) {
-
- // Initialize buttons and inject visibility control
- BUTTONS_DESCRIPTORS.forEach { descriptor ->
- PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
- PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch.kt
new file mode 100644
index 000000000..f02aae13f
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch.kt
@@ -0,0 +1,52 @@
+package app.revanced.patches.youtube.interaction.downloads
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
+import app.revanced.patches.youtube.video.information.VideoInformationPatch
+
+@Patch(
+ name = "External downloads",
+ description = "Adds support to download and save YouTube videos using an external app.",
+ dependencies = [
+ ExternalDownloadsResourcePatch::class,
+ PlayerControlsBytecodePatch::class,
+ VideoInformationPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ ),
+ ]
+)
+@Suppress("unused")
+object ExternalDownloadsBytecodePatch : BytecodePatch() {
+ private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/ExternalDownloadButton;"
+
+ override fun execute(context: BytecodeContext) {
+ /*
+ initialize the control
+ */
+
+ PlayerControlsBytecodePatch.initializeControl(
+ "$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
+
+ /*
+ add code to change the visibility of the control
+ */
+
+ PlayerControlsBytecodePatch.injectVisibilityCheckCall(
+ "$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/ExternalDownloadsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsResourcePatch.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/ExternalDownloadsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsResourcePatch.kt
index d9040f05c..2d085528d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/ExternalDownloadsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsResourcePatch.kt
@@ -1,17 +1,22 @@
-package app.revanced.patches.youtube.interaction.downloads.resource.patch
+package app.revanced.patches.youtube.interaction.downloads
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.*
-import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
-@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
-class ExternalDownloadsResourcePatch : ResourcePatch {
+@Patch(
+ dependencies = [
+ BottomControlsResourcePatch::class,
+ SettingsPatch::class
+ ]
+)
+object ExternalDownloadsResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/ExternalDownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/ExternalDownloadsCompatibility.kt
deleted file mode 100644
index 4259448ad..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/ExternalDownloadsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.interaction.downloads.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ExternalDownloadsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/ExternalDownloadsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/ExternalDownloadsBytecodePatch.kt
deleted file mode 100644
index ccc952811..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/ExternalDownloadsBytecodePatch.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package app.revanced.patches.youtube.interaction.downloads.bytecode.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.interaction.downloads.annotation.ExternalDownloadsCompatibility
-import app.revanced.patches.youtube.interaction.downloads.resource.patch.ExternalDownloadsResourcePatch
-import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
-import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
-
-@Patch
-@Name("External downloads")
-@DependsOn([ExternalDownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoInformationPatch::class])
-@Description("Adds support to download and save YouTube videos using an external app.")
-@ExternalDownloadsCompatibility
-class ExternalDownloadsBytecodePatch : BytecodePatch() {
- private companion object {
- const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/ExternalDownloadButton;"
- }
-
- override fun execute(context: BytecodeContext) {
- /*
- initialize the control
- */
-
- PlayerControlsBytecodePatch.initializeControl(
- "$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
-
- /*
- add code to change the visibility of the control
- */
-
- PlayerControlsBytecodePatch.injectVisibilityCheckCall(
- "$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt
index 78e27e802..185292232 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt
@@ -1,33 +1,48 @@
-package app.revanced.patches.youtube.interaction.seekbar.patch
+package app.revanced.patches.youtube.interaction.seekbar
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.OnTouchEventHandlerFingerprint
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import com.android.tools.smali.dexlib2.Opcode
-import com.android.tools.smali.dexlib2.iface.Method
-import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
-import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
+import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-@Patch
-@DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
-@Name("Seekbar tapping")
-@Description("Enables tap-to-seek on the seekbar of the video player.")
-@SeekbarTappingCompatibility
-class EnableSeekbarTappingPatch : BytecodePatch(
- listOf(OnTouchEventHandlerFingerprint, SeekbarTappingFingerprint)
+@Patch(
+ name = "Seekbar tapping",
+ description = "Enables tap-to-seek on the seekbar of the video player.",
+ dependencies = [
+ IntegrationsPatch::class,
+ EnableSeekbarTappingResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object EnableSeekbarTappingPatch : BytecodePatch(
+ setOf(
+ OnTouchEventHandlerFingerprint,
+ SeekbarTappingFingerprint
+ )
) {
override fun execute(context: BytecodeContext) {
// Find the required methods to tap the seekbar.
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingResourcePatch.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingResourcePatch.kt
index 31e72ca22..a39bc0e8b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingResourcePatch.kt
@@ -1,14 +1,16 @@
-package app.revanced.patches.youtube.interaction.seekbar.patch
+package app.revanced.patches.youtube.interaction.seekbar
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@DependsOn([SettingsPatch::class])
-class EnableSeekbarTappingResourcePatch : ResourcePatch {
+@Patch(
+ dependencies = [SettingsPatch::class]
+)
+object EnableSeekbarTappingResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
SwitchPreference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt
deleted file mode 100644
index ba941a7b3..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.interaction.seekbar.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class SeekbarTappingCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt
index 16a27bdf7..04a6196ae 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt
@@ -1,36 +1,45 @@
-package app.revanced.patches.youtube.interaction.swipecontrols.patch.bytecode
+package app.revanced.patches.youtube.interaction.swipecontrols
import app.revanced.extensions.transformMethods
import app.revanced.extensions.traverseClassHierarchy
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.shared.fingerprints.WatchWhileActivityFingerprint
-import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.SwipeControlsHostActivityFingerprint
-import app.revanced.patches.youtube.interaction.swipecontrols.patch.resource.SwipeControlsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
-@Patch
-@Name("Swipe controls")
-@Description("Adds volume and brightness swipe controls.")
-@SwipeControlsCompatibility
-@DependsOn(
- [
+@Patch(
+ name = "Swipe controls",
+ description = "Adds volume and brightness swipe controls.",
+ dependencies = [
IntegrationsPatch::class,
PlayerTypeHookPatch::class,
SwipeControlsResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
]
)
-class SwipeControlsBytecodePatch : BytecodePatch(
- listOf(
+@Suppress("unused")
+object SwipeControlsBytecodePatch : BytecodePatch(
+ setOf(
WatchWhileActivityFingerprint,
SwipeControlsHostActivityFingerprint
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsResourcePatch.kt
similarity index 94%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsResourcePatch.kt
index 014397898..f4538da29 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsResourcePatch.kt
@@ -1,15 +1,17 @@
-package app.revanced.patches.youtube.interaction.swipecontrols.patch.resource
+package app.revanced.patches.youtube.interaction.swipecontrols
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.*
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
-@DependsOn([SettingsPatch::class])
-class SwipeControlsResourcePatch : ResourcePatch {
+@Patch(
+ dependencies = [SettingsPatch::class]
+)
+object SwipeControlsResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
PreferenceScreen(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt
deleted file mode 100644
index 4ca221ebd..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.interaction.swipecontrols.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class SwipeControlsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt
new file mode 100644
index 000000000..6421de5c0
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt
@@ -0,0 +1,80 @@
+package app.revanced.patches.youtube.layout.autocaptions
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.layout.autocaptions.fingerprints.StartVideoInformerFingerprint
+import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleButtonControllerFingerprint
+import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleTrackFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+
+@Patch(
+ name = "Disable auto captions",
+ description = "Disable forced captions from being automatically enabled.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ],
+)
+@Suppress("unused")
+object AutoCaptionsPatch : BytecodePatch(
+ setOf(StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint)
+) {
+ override fun execute(context: BytecodeContext) {
+ SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ SwitchPreference(
+ "revanced_auto_captions",
+ StringResource("revanced_auto_captions_title", "Disable auto captions"),
+ StringResource("revanced_auto_captions_summary_on", "Auto captions are disabled"),
+ StringResource("revanced_auto_captions_summary_off", "Auto captions are enabled")
+ )
+ )
+
+ mapOf(
+ StartVideoInformerFingerprint to 0,
+ SubtitleButtonControllerFingerprint to 1
+ ).forEach { (fingerprint, enabled) ->
+ fingerprint.result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x$enabled
+ sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
+ """
+ ) ?: throw fingerprint.exception
+ }
+
+ SubtitleTrackFingerprint.result?.mutableMethod?.addInstructionsWithLabels(
+ 0,
+ """
+ invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
+ move-result v0
+ if-eqz v0, :auto_captions_enabled
+ sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
+ if-nez v0, :auto_captions_enabled
+ const/4 v0, 0x1
+ return v0
+ :auto_captions_enabled
+ nop
+ """
+ )
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt
deleted file mode 100644
index a0f393982..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.autocaptions.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AutoCaptionsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt
index 31fab1f21..a1969ed09 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt
@@ -6,25 +6,11 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object StartVideoInformerFingerprint : MethodFingerprint(
- "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L", "L", "L"), listOf(
- Opcode.INVOKE_STATIC,
- Opcode.IGET_OBJECT,
- Opcode.IGET_OBJECT,
- Opcode.NEW_INSTANCE,
- Opcode.INVOKE_DIRECT,
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ opcodes = listOf(
Opcode.INVOKE_INTERFACE,
- Opcode.IF_EQZ,
- Opcode.CONST_STRING,
- Opcode.INVOKE_INTERFACE,
- Opcode.IGET_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT,
- Opcode.IF_EQZ,
- Opcode.IGET_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT,
- Opcode.CONST_4,
- Opcode.IF_EQ,
- Opcode.GOTO,
- )
+ Opcode.RETURN_VOID
+ ),
+ strings = listOf("pc")
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt
deleted file mode 100644
index d7c40a809..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-package app.revanced.patches.youtube.layout.autocaptions.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.autocaptions.fingerprints.StartVideoInformerFingerprint
-import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleButtonControllerFingerprint
-import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleTrackFingerprint
-import app.revanced.patches.youtube.layout.buttons.captions.annotations.HideCaptionsButtonCompatibility
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Disable auto captions")
-@Description("Disable forced captions from being automatically enabled.")
-@HideCaptionsButtonCompatibility
-class AutoCaptionsPatch : BytecodePatch(
- listOf(
- StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
- SwitchPreference(
- "revanced_auto_captions",
- StringResource("revanced_auto_captions_title", "Disable auto captions"),
- StringResource("revanced_auto_captions_summary_on", "Auto captions are disabled"),
- StringResource("revanced_auto_captions_summary_off", "Auto captions are enabled")
- )
- )
-
- val startVideoInformerMethod = StartVideoInformerFingerprint.result!!.mutableMethod
-
- startVideoInformerMethod.addInstructions(
- 0, """
- const/4 v0, 0x0
- sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
- """
- )
-
- val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod
-
- subtitleButtonControllerMethod.addInstructions(
- 0, """
- const/4 v0, 0x1
- sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
- """
- )
-
- val subtitleTrackMethod = SubtitleTrackFingerprint.result!!.mutableMethod
-
- subtitleTrackMethod.addInstructionsWithLabels(
- 0, """
- invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
- move-result v0
- if-eqz v0, :auto_captions_enabled
- sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
- if-nez v0, :auto_captions_enabled
- const/4 v0, 0x1
- return v0
- :auto_captions_enabled
- nop
- """
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt
similarity index 61%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt
index b4a69d2a4..433d1a345 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt
@@ -1,23 +1,40 @@
-package app.revanced.patches.youtube.layout.branding.icon.patch
+package app.revanced.patches.youtube.layout.branding
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.OptionsContainer
-import app.revanced.patcher.patch.PatchOption
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.branding.icon.annotations.CustomBrandingCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import java.io.File
import java.nio.file.Files
-@Patch(false)
-@Name("Custom branding")
-@Description("Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).")
-@CustomBrandingCompatibility
-class CustomBrandingPatch : ResourcePatch {
+@Patch(
+ name = "Custom branding",
+ description = "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube")
+ ],
+ use = false
+)
+@Suppress("unused")
+object CustomBrandingPatch : ResourcePatch() {
+ private var appName by stringPatchOption(
+ key = "appName",
+ default = "YouTube ReVanced",
+ title = "Application Name",
+ description = "The name of the application it will show on your home screen.",
+ required = true
+ )
+
+ private var iconPath by stringPatchOption(
+ key = "iconPath",
+ default = null,
+ title = "App Icon Path",
+ description = "A path containing mipmap resource folders with icons."
+ )
+
override fun execute(context: ResourceContext) {
fun copyResources(resourceGroups: List) {
iconPath?.let { iconPathString ->
@@ -65,25 +82,4 @@ class CustomBrandingPatch : ResourcePatch {
)
)
}
-
- companion object : OptionsContainer() {
- private var appName: String? by option(
- PatchOption.StringOption(
- key = "appName",
- default = "YouTube ReVanced",
- title = "Application Name",
- description = "The name of the application it will show on your home screen.",
- required = true
- )
- )
-
- private var iconPath: String? by option(
- PatchOption.StringOption(
- key = "iconPath",
- default = null,
- title = "App Icon Path",
- description = "A path containing mipmap resource folders with icons."
- )
- )
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch.kt
new file mode 100644
index 000000000..4a8dbc018
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch.kt
@@ -0,0 +1,62 @@
+package app.revanced.patches.youtube.layout.branding.header
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchException
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.patch.options.types.BooleanPatchOption.Companion.booleanPatchOption
+import kotlin.io.path.copyTo
+
+@Patch(
+ name = "Premium heading",
+ description = "Show or hide the premium heading.",
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube")
+ ]
+)
+@Suppress("unused")
+object PremiumHeadingPatch : ResourcePatch() {
+ private const val DEFAULT_HEADING_RES = "yt_wordmark_header"
+ private const val PREMIUM_HEADING_RES = "yt_premium_wordmark_header"
+
+ private val usePremiumHeading by booleanPatchOption(
+ key = "usePremiumHeading",
+ default = true,
+ title = "Use premium heading",
+ description = "Whether to use the premium heading.",
+ required = true,
+ )
+
+ override fun execute(context: ResourceContext) {
+ val resDirectory = context["res"]
+
+ val (original, replacement) = if (usePremiumHeading!!)
+ PREMIUM_HEADING_RES to DEFAULT_HEADING_RES
+ else
+ DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
+
+ val variants = arrayOf("light", "dark")
+
+ arrayOf(
+ "xxxhdpi",
+ "xxhdpi",
+ "xhdpi",
+ "hdpi",
+ "mdpi"
+ ).mapNotNull { dpi ->
+ resDirectory.resolve("drawable-$dpi").takeIf { it.exists() }?.toPath()
+ }.also {
+ if (it.isEmpty())
+ throw PatchException("The drawable folder can not be found. Therefore, the patch can not be applied.")
+ }.forEach { path ->
+
+ variants.forEach { mode ->
+ val fromPath = path.resolve("${original}_$mode.png")
+ val toPath = path.resolve("${replacement}_$mode.png")
+
+ fromPath.copyTo(toPath, true)
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt
deleted file mode 100644
index c021de553..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.branding.header.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PremiumHeadingCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt
deleted file mode 100644
index c5f408d2a..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package app.revanced.patches.youtube.layout.branding.header.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.branding.header.annotations.PremiumHeadingCompatibility
-import java.nio.file.Files
-import java.nio.file.StandardCopyOption
-import kotlin.io.path.exists
-
-@Patch
-@Name("Premium heading")
-@Description("Shows premium branding on the home screen.")
-@PremiumHeadingCompatibility
-class PremiumHeadingPatch : ResourcePatch {
- override fun execute(context: ResourceContext) {
- val resDirectory = context["res"]
- if (!resDirectory.isDirectory) throw PatchException("The res folder can not be found.")
-
- val (original, replacement) = "yt_premium_wordmark_header" to "yt_wordmark_header"
- val modes = arrayOf("light", "dark")
-
- arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi").forEach { size ->
- val headingDirectory = resDirectory.resolve("drawable-$size")
- modes.forEach { mode ->
- val fromPath = headingDirectory.resolve("${original}_$mode.png").toPath()
- val toPath = headingDirectory.resolve("${replacement}_$mode.png").toPath()
-
- if (!fromPath.exists())
- throw PatchException("The file $fromPath does not exist in the resources. Therefore, this patch can not succeed.")
- Files.copy(
- fromPath,
- toPath,
- StandardCopyOption.REPLACE_EXISTING
- )
- }
- }
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt
deleted file mode 100644
index ec6b73b27..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.branding.icon.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class CustomBrandingCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt
similarity index 82%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt
index 04eceb040..0dd28b2b3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt
@@ -1,25 +1,43 @@
-package app.revanced.patches.youtube.layout.buttons.action.patch
+package app.revanced.patches.youtube.layout.buttons.action
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.buttons.action.annotations.HideButtonsCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ name = "Hide video action buttons",
+ description = "Adds the options to hide action buttons under a video.",
+ dependencies = [
+ ResourceMappingPatch::class,
+ LithoFilterPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideButtonsPatch : ResourcePatch() {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/ButtonsFilter;"
-@Patch
-@DependsOn([ResourceMappingPatch::class, LithoFilterPatch::class])
-@Name("Hide video action buttons")
-@Description("Adds the options to hide action buttons under a video.")
-@HideButtonsCompatibility
-class HideButtonsPatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -93,9 +111,4 @@ class HideButtonsPatch : ResourcePatch {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
}
-
- private companion object {
- private const val FILTER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/components/ButtonsFilter;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt
deleted file mode 100644
index 718e0b562..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.buttons.action.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideButtonsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt
index 8857d8544..a04196b53 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt
@@ -1,35 +1,51 @@
-package app.revanced.patches.youtube.layout.buttons.autoplay.patch
+package app.revanced.patches.youtube.layout.buttons.autoplay
-import app.revanced.extensions.findIndexForIdResource
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
+import app.revanced.extensions.findIndexForIdResource
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.buttons.autoplay.annotations.AutoplayButtonCompatibility
-import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class, ResourceMappingPatch::class])
-@Name("Hide autoplay button")
-@Description("Hides the autoplay button in the video player.")
-@AutoplayButtonCompatibility
-class HideAutoplayButtonPatch : BytecodePatch(
- listOf(LayoutConstructorFingerprint)
+@Patch(
+ name = "Hide autoplay button",
+ description = "Hides the autoplay button in the video player.",
+ dependencies = [
+ IntegrationsPatch::class,
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideAutoplayButtonPatch : BytecodePatch(
+ setOf(LayoutConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt
deleted file mode 100644
index 1c3bcd4b5..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.buttons.autoplay.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AutoplayButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt
similarity index 62%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt
index 71d4a81f7..98f6a8328 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt
@@ -1,28 +1,43 @@
-package app.revanced.patches.youtube.layout.buttons.captions.patch
+package app.revanced.patches.youtube.layout.buttons.captions
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleButtonControllerFingerprint
-import app.revanced.patches.youtube.layout.buttons.captions.annotations.HideCaptionsButtonCompatibility
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Hide captions button")
-@Description("Hides the captions button on video player.")
-@HideCaptionsButtonCompatibility
-class HideCaptionsButtonPatch : BytecodePatch(listOf(
- SubtitleButtonControllerFingerprint,
-)) {
+@Patch(
+ name = "Hide captions button",
+ description = "Hides the captions button on video player.",
+ dependencies = [
+ IntegrationsPatch::class,
+ SettingsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideCaptionsButtonPatch : BytecodePatch(
+ setOf(SubtitleButtonControllerFingerprint)
+) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt
deleted file mode 100644
index efa557282..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.buttons.captions.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideCaptionsButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/HideCastButtonPatch.kt
similarity index 66%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/HideCastButtonPatch.kt
index 74bc155b5..fe3f83329 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/HideCastButtonPatch.kt
@@ -1,25 +1,28 @@
-package app.revanced.patches.youtube.layout.buttons.cast.patch
+package app.revanced.patches.youtube.layout.buttons.cast
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.buttons.cast.annotations.CastButtonCompatibility
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Hide cast button")
-@Description("Hides the cast button in the video player.")
-@CastButtonCompatibility
-class HideCastButtonPatch : BytecodePatch() {
+@Patch(
+ name = "Hide cast button",
+ description = "Hides the cast button in the video player.",
+ dependencies = [
+ IntegrationsPatch::class,
+ SettingsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube")
+ ]
+)
+object HideCastButtonPatch : BytecodePatch() {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/annotations/CastPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/annotations/CastPatchCompatibility.kt
deleted file mode 100644
index 8aace1028..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/annotations/CastPatchCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.buttons.cast.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class CastButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt
similarity index 87%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt
index fc708d6ef..07e77c68c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt
@@ -1,39 +1,54 @@
-package app.revanced.patches.youtube.layout.buttons.navigation.patch
+package app.revanced.patches.youtube.layout.buttons.navigation
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.buttons.navigation.annotations.NavigationButtonsCompatibility
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.*
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.injectHook
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn(
- [
+@Patch(
+ name = "Navigation buttons",
+ description = "Adds options to hide or change navigation buttons.",
+ dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
- ResolvePivotBarFingerprintsPatch::class,
+ ResolvePivotBarFingerprintsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
]
)
-@Name("Navigation buttons")
-@Description("Adds options to hide or change navigation buttons.")
-@NavigationButtonsCompatibility
-class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerprint)) {
+@Suppress("unused")
+object NavigationButtonsPatch : BytecodePatch(
+ setOf(AddCreateButtonViewFingerprint)
+) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/NavigationButtonsPatch;"
+
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -179,8 +194,4 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
mutableMethod.injectHook(hook, insertIndex)
}
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/NavigationButtonsPatch;"
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/ResolvePivotBarFingerprintsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/ResolvePivotBarFingerprintsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt
index eb7bfd40e..f85ece3a4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/ResolvePivotBarFingerprintsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt
@@ -1,21 +1,24 @@
-package app.revanced.patches.youtube.layout.buttons.navigation.patch
+package app.revanced.patches.youtube.layout.buttons.navigation
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.InitializeButtonsFingerprint
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.PivotBarConstructorFingerprint
-@DependsOn([ResourceMappingPatch::class])
-@Description("Resolves necessary fingerprints.")
-class ResolvePivotBarFingerprintsPatch : BytecodePatch(
- listOf(PivotBarConstructorFingerprint)
+@Patch(
+ description = "Resolves necessary fingerprints.",
+ dependencies = [ResourceMappingPatch::class]
+)
+object ResolvePivotBarFingerprintsPatch : BytecodePatch(
+ setOf(PivotBarConstructorFingerprint)
) {
+ internal var imageOnlyTabResourceId: Long = -1
+
override fun execute(context: BytecodeContext) {
// imageOnlyTabResourceId is used in InitializeButtonsFingerprint fingerprint
ResourceMappingPatch.resourceMappings.find { it.type == "layout" && it.name == "image_only_tab" }
@@ -32,7 +35,4 @@ class ResolvePivotBarFingerprintsPatch : BytecodePatch(
} ?: throw PivotBarConstructorFingerprint.exception
}
- internal companion object {
- var imageOnlyTabResourceId: Long = -1
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt
deleted file mode 100644
index 7afcbdcaa..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.buttons.navigation.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class NavigationButtonsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt
index 4d435d943..80f6618b9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.buttons.navigation.patch.ResolvePivotBarFingerprintsPatch
+import app.revanced.patches.youtube.layout.buttons.navigation.ResolvePivotBarFingerprintsPatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
@@ -9,5 +9,5 @@ object InitializeButtonsFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf(),
- literal = ResolvePivotBarFingerprintsPatch.imageOnlyTabResourceId
+ literalSupplier = { ResolvePivotBarFingerprintsPatch.imageOnlyTabResourceId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt
similarity index 66%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt
index b719359bf..ab77bf82c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt
@@ -1,35 +1,47 @@
-package app.revanced.patches.youtube.layout.buttons.player.hide.patch
+package app.revanced.patches.youtube.layout.buttons.player.hide
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.buttons.player.hide.annotations.HidePlayerButtonsCompatibility
+import app.revanced.patches.youtube.layout.buttons.player.hide.HidePlayerButtonsPatch.ParameterOffsets.HAS_NEXT
+import app.revanced.patches.youtube.layout.buttons.player.hide.HidePlayerButtonsPatch.ParameterOffsets.HAS_PREVIOUS
import app.revanced.patches.youtube.layout.buttons.player.hide.fingerprints.PlayerControlsVisibilityModelFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Hide player buttons")
-@Description("Adds the option to hide video player previous and next buttons.")
-@HidePlayerButtonsCompatibility
-class HidePlayerButtonsPatch : BytecodePatch(
- listOf(PlayerControlsVisibilityModelFingerprint)
+@Patch(
+ name = "Hide player buttons",
+ description = "Adds the option to hide video player previous and next buttons.",
+ dependencies = [
+ IntegrationsPatch::class,
+ SettingsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HidePlayerButtonsPatch : BytecodePatch(
+ setOf(PlayerControlsVisibilityModelFingerprint)
) {
- private object ParameterOffsets {
- const val HAS_NEXT = 5
- const val HAS_PREVIOUS = 6
- }
-
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
@@ -54,8 +66,8 @@ class HidePlayerButtonsPatch : BytecodePatch(
val callInstruction = mutableMethod.getInstruction(callIndex)
// overriding this parameter register hides the previous and next buttons
- val hasNextParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_NEXT
- val hasPreviousParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_PREVIOUS
+ val hasNextParameterRegister = callInstruction.startRegister + HAS_NEXT
+ val hasPreviousParameterRegister = callInstruction.startRegister + HAS_PREVIOUS
mutableMethod.addInstructions(
callIndex,
@@ -69,4 +81,9 @@ class HidePlayerButtonsPatch : BytecodePatch(
)
} ?: throw PlayerControlsVisibilityModelFingerprint.exception
}
+
+ private object ParameterOffsets {
+ const val HAS_NEXT = 5
+ const val HAS_PREVIOUS = 6
+ }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt
deleted file mode 100644
index e1a7726d2..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.buttons.player.hide.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HidePlayerButtonsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt
index 3b699b36f..f5bf28a24 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt
@@ -1,29 +1,41 @@
-package app.revanced.patches.youtube.layout.hide.albumcards.bytecode.patch
+package app.revanced.patches.youtube.layout.hide.albumcards
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.albumcards.annotations.AlbumCardsCompatibility
-import app.revanced.patches.youtube.layout.hide.albumcards.bytecode.fingerprints.AlbumCardsFingerprint
-import app.revanced.patches.youtube.layout.hide.albumcards.resource.patch.AlbumCardsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.albumcards.fingerprints.AlbumCardsFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn([IntegrationsPatch::class, AlbumCardsResourcePatch::class])
-@Name("Hide album cards")
-@Description("Hides the album cards below the artist description.")
-@AlbumCardsCompatibility
-class AlbumCardsPatch : BytecodePatch(
- listOf(
- AlbumCardsFingerprint,
- )
+@Patch(
+ name = "Hide album cards",
+ description = "Hides the album cards below the artist description.",
+ dependencies = [
+ IntegrationsPatch::class,
+ AlbumCardsResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object AlbumCardsPatch : BytecodePatch(
+ setOf(AlbumCardsFingerprint)
) {
override fun execute(context: BytecodeContext) {
AlbumCardsFingerprint.result?.let {
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsResourcePatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsResourcePatch.kt
index 2e22a4c5c..e40936404 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsResourcePatch.kt
@@ -1,18 +1,21 @@
-package app.revanced.patches.youtube.layout.hide.albumcards.resource.patch
+package app.revanced.patches.youtube.layout.hide.albumcards
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class AlbumCardsResourcePatch : ResourcePatch {
- companion object {
- internal var albumCardId: Long = -1
- }
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ],
+)
+object AlbumCardsResourcePatch : ResourcePatch() {
+ internal var albumCardId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt
deleted file mode 100644
index cbb7db662..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.albumcards.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AlbumCardsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/fingerprints/AlbumCardsFingerprint.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/fingerprints/AlbumCardsFingerprint.kt
index c7c808e2e..60deb9ee7 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/fingerprints/AlbumCardsFingerprint.kt
@@ -1,7 +1,7 @@
-package app.revanced.patches.youtube.layout.hide.albumcards.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.albumcards.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.albumcards.resource.patch.AlbumCardsResourcePatch
+import app.revanced.patches.youtube.layout.hide.albumcards.AlbumCardsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -16,5 +16,5 @@ object AlbumCardsFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- literal = AlbumCardsResourcePatch.albumCardId
+ literalSupplier = { AlbumCardsResourcePatch.albumCardId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt
new file mode 100644
index 000000000..c6cbea4b7
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt
@@ -0,0 +1,63 @@
+package app.revanced.patches.youtube.layout.hide.breakingnews
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.breakingnews.fingerprints.BreakingNewsFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch(
+ name = "Hide breaking news shelf",
+ description = "Hides the breaking news shelf on the homepage tab.",
+ dependencies = [
+ IntegrationsPatch::class,
+ BreakingNewsResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object BreakingNewsPatch : BytecodePatch(
+ setOf(BreakingNewsFingerprint)
+) {
+ override fun execute(context: BytecodeContext) {
+ BreakingNewsFingerprint.result?.let {
+ val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
+ val moveResultIndex = insertIndex - 1
+
+ it.mutableMethod.apply {
+ val breakingNewsViewRegister =
+ getInstruction(moveResultIndex).registerA
+
+ addInstruction(
+ insertIndex,
+ """
+ invoke-static {v$breakingNewsViewRegister},
+ Lapp/revanced/integrations/patches/HideBreakingNewsPatch;
+ ->
+ hideBreakingNews(Landroid/view/View;)V
+ """
+ )
+ }
+
+ } ?: throw BreakingNewsFingerprint.exception
+
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsResourcePatch.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsResourcePatch.kt
index 2a679a965..cbfafb170 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsResourcePatch.kt
@@ -1,18 +1,21 @@
-package app.revanced.patches.youtube.layout.hide.breakingnews.resource.patch
+package app.revanced.patches.youtube.layout.hide.breakingnews
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class BreakingNewsResourcePatch : ResourcePatch {
- companion object {
- internal var horizontalCardListId: Long = -1
- }
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ],
+)
+object BreakingNewsResourcePatch : ResourcePatch() {
+ internal var horizontalCardListId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt
deleted file mode 100644
index 47cee050b..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.breakingnews.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class BreakingNewsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt
deleted file mode 100644
index ee09bed14..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.breakingnews.bytecode.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.breakingnews.annotations.BreakingNewsCompatibility
-import app.revanced.patches.youtube.layout.hide.breakingnews.bytecode.fingerprints.BreakingNewsFingerprint
-import app.revanced.patches.youtube.layout.hide.breakingnews.resource.patch.BreakingNewsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-
-@Patch
-@DependsOn([IntegrationsPatch::class, BreakingNewsResourcePatch::class])
-@Name("Hide breaking news shelf")
-@Description("Hides the breaking news shelf on the homepage tab.")
-@BreakingNewsCompatibility
-class BreakingNewsPatch : BytecodePatch(
- listOf(BreakingNewsFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- BreakingNewsFingerprint.result?.let {
- val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
- val moveResultIndex = insertIndex - 1
-
- it.mutableMethod.apply {
- val breakingNewsViewRegister = getInstruction(moveResultIndex).registerA
-
- addInstruction(
- insertIndex,
- """
- invoke-static {v$breakingNewsViewRegister},
- Lapp/revanced/integrations/patches/HideBreakingNewsPatch;
- ->
- hideBreakingNews(Landroid/view/View;)V
- """
- )
- }
-
- } ?: throw BreakingNewsFingerprint.exception
-
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/fingerprints/BreakingNewsFingerprint.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/fingerprints/BreakingNewsFingerprint.kt
index 2e5592d8c..e69335488 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/fingerprints/BreakingNewsFingerprint.kt
@@ -1,7 +1,7 @@
-package app.revanced.patches.youtube.layout.hide.breakingnews.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.breakingnews.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.breakingnews.resource.patch.BreakingNewsResourcePatch
+import app.revanced.patches.youtube.layout.hide.breakingnews.BreakingNewsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -16,5 +16,5 @@ object BreakingNewsFingerprint : LiteralValueFingerprint(
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT,
),
- literal = BreakingNewsResourcePatch.horizontalCardListId
+ literalSupplier = { BreakingNewsResourcePatch.horizontalCardListId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/patch/CommentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/patch/CommentsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt
index 02054c4b2..daef32de5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/patch/CommentsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt
@@ -1,24 +1,42 @@
-package app.revanced.patches.youtube.layout.hide.comments.patch
+package app.revanced.patches.youtube.layout.hide.comments
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.comments.annotations.HideCommentsCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ name = "Comments",
+ description = "Hides components related to comments.",
+ dependencies = [
+ SettingsPatch::class,
+ LithoFilterPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object CommentsPatch : ResourcePatch() {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/CommentsFilter;"
-@Patch
-@Name("Comments")
-@Description("Hides components related to comments.")
-@HideCommentsCompatibility
-@DependsOn([SettingsPatch::class, LithoFilterPatch::class])
-class CommentsPatch : ResourcePatch {
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
@@ -44,8 +62,4 @@ class CommentsPatch : ResourcePatch {
)
)
}
-
- private companion object {
- const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/CommentsFilter;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/HideCommentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/HideCommentsCompatibility.kt
deleted file mode 100644
index 3186af1d0..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/HideCommentsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.comments.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideCommentsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt
new file mode 100644
index 000000000..4c7f311e6
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt
@@ -0,0 +1,53 @@
+package app.revanced.patches.youtube.layout.hide.crowdfundingbox
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
+
+@Patch(
+ name = "Hide crowdfunding box",
+ description = "Hides the crowdfunding box between the player and video description.",
+ dependencies = [
+ IntegrationsPatch::class,
+ CrowdfundingBoxResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object CrowdfundingBoxPatch : BytecodePatch(
+ setOf(CrowdfundingBoxFingerprint)
+) {
+ private const val INTEGRATIONS_METHOD_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"
+
+ override fun execute(context: BytecodeContext) {
+ CrowdfundingBoxFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val insertIndex = it.scanResult.patternScanResult!!.endIndex
+ val objectRegister = getInstruction(insertIndex).registerA
+
+ addInstruction(insertIndex, "invoke-static {v$objectRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR")
+ }
+ } ?: throw CrowdfundingBoxFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxResourcePatch.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxResourcePatch.kt
index 4d0cc7c20..0bfb0f2f5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxResourcePatch.kt
@@ -1,18 +1,21 @@
-package app.revanced.patches.youtube.layout.hide.crowdfundingbox.resource.patch
+package app.revanced.patches.youtube.layout.hide.crowdfundingbox
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class CrowdfundingBoxResourcePatch : ResourcePatch {
- companion object {
- internal var crowdfundingBoxId: Long = -1
- }
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ],
+)
+object CrowdfundingBoxResourcePatch : ResourcePatch() {
+ internal var crowdfundingBoxId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt
deleted file mode 100644
index 0978625f6..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class CrowdfundingBoxCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt
deleted file mode 100644
index 1ebdb0eb6..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.crowdfundingbox.bytecode.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations.CrowdfundingBoxCompatibility
-import app.revanced.patches.youtube.layout.hide.crowdfundingbox.bytecode.fingerprints.CrowdfundingBoxFingerprint
-import app.revanced.patches.youtube.layout.hide.crowdfundingbox.resource.patch.CrowdfundingBoxResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-
-@Patch
-@DependsOn([IntegrationsPatch::class, CrowdfundingBoxResourcePatch::class])
-@Name("Hide crowdfunding box")
-@Description("Hides the crowdfunding box between the player and video description.")
-@CrowdfundingBoxCompatibility
-class CrowdfundingBoxPatch : BytecodePatch(
- listOf(
- CrowdfundingBoxFingerprint,
- )
-) {
- override fun execute(context: BytecodeContext) {
- CrowdfundingBoxFingerprint.result?.let {
- it.mutableMethod.apply {
- val insertIndex = it.scanResult.patternScanResult!!.endIndex
- val objectRegister = getInstruction(insertIndex).registerA
-
- addInstruction(insertIndex, "invoke-static {v$objectRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR")
- }
- } ?: throw CrowdfundingBoxFingerprint.exception
- }
-
- private companion object {
- const val INTEGRATIONS_METHOD_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt
similarity index 81%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt
index 946b00bef..31039bd03 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt
@@ -1,7 +1,7 @@
-package app.revanced.patches.youtube.layout.hide.crowdfundingbox.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.crowdfundingbox.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.crowdfundingbox.resource.patch.CrowdfundingBoxResourcePatch
+import app.revanced.patches.youtube.layout.hide.crowdfundingbox.CrowdfundingBoxResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -13,5 +13,5 @@ object CrowdfundingBoxFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
),
- literal = CrowdfundingBoxResourcePatch.crowdfundingBoxId
+ literalSupplier = { CrowdfundingBoxResourcePatch.crowdfundingBoxId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt
index 43f7208ed..8afa56d00 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt
@@ -1,30 +1,44 @@
-package app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.patch
+package app.revanced.patches.youtube.layout.hide.endscreencards
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.endscreencards.annotations.HideEndscreenCardsCompatibility
-import app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.fingerprints.LayoutCircleFingerprint
-import app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.fingerprints.LayoutIconFingerprint
-import app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.fingerprints.LayoutVideoFingerprint
-import app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch.HideEndscreenCardsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutCircleFingerprint
+import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutIconFingerprint
+import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutVideoFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
-@Patch
-@DependsOn([IntegrationsPatch::class, HideEndscreenCardsResourcePatch::class])
-@Name("Hide endscreen cards")
-@Description("Hides the suggested video cards at the end of a video in fullscreen.")
-@HideEndscreenCardsCompatibility
-class HideEndscreenCardsPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Hide endscreen cards",
+ description = "Hides the suggested video cards at the end of a video in fullscreen.",
+ dependencies = [
+ IntegrationsPatch::class,
+ HideEndscreenCardsResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideEndscreenCardsPatch : BytecodePatch(
+ setOf(
LayoutCircleFingerprint,
LayoutIconFingerprint,
LayoutVideoFingerprint,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsResourcePatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsResourcePatch.kt
index 78c0253b9..790c141c1 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsResourcePatch.kt
@@ -1,20 +1,23 @@
-package app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch
+package app.revanced.patches.youtube.layout.hide.endscreencards
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class HideEndscreenCardsResourcePatch : ResourcePatch {
- internal companion object {
- var layoutCircle: Long = -1
- var layoutIcon: Long = -1
- var layoutVideo: Long = -1
- }
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ],
+)
+object HideEndscreenCardsResourcePatch : ResourcePatch() {
+ internal var layoutCircle: Long = -1
+ internal var layoutIcon: Long = -1
+ internal var layoutVideo: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt
deleted file mode 100644
index f6017cf54..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.endscreencards.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideEndscreenCardsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutCircleFingerprint.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutCircleFingerprint.kt
index f2de24985..36f245bf0 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutCircleFingerprint.kt
@@ -1,6 +1,6 @@
-package app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints
-import app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch.HideEndscreenCardsResourcePatch
+import app.revanced.patches.youtube.layout.hide.endscreencards.HideEndscreenCardsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
@@ -13,5 +13,5 @@ object LayoutCircleFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- literal = HideEndscreenCardsResourcePatch.layoutCircle
+ literalSupplier = { HideEndscreenCardsResourcePatch.layoutCircle }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutIconFingerprint.kt
similarity index 62%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutIconFingerprint.kt
index 13de055b3..c9e2dbf4d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutIconFingerprint.kt
@@ -1,17 +1,15 @@
-package app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints
-import app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch.HideEndscreenCardsResourcePatch
+import app.revanced.patches.youtube.layout.hide.endscreencards.HideEndscreenCardsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
object LayoutIconFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;",
opcodes = listOf(
- Opcode.CONST_4,
- Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- literal = HideEndscreenCardsResourcePatch.layoutIcon
+ literalSupplier = { HideEndscreenCardsResourcePatch.layoutIcon }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutVideoFingerprint.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutVideoFingerprint.kt
index b7b54a530..57b284789 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/fingerprints/LayoutVideoFingerprint.kt
@@ -1,6 +1,6 @@
-package app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints
-import app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch.HideEndscreenCardsResourcePatch
+import app.revanced.patches.youtube.layout.hide.endscreencards.HideEndscreenCardsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
@@ -13,5 +13,5 @@ object LayoutVideoFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- literal = HideEndscreenCardsResourcePatch.layoutVideo
+ literalSupplier = { HideEndscreenCardsResourcePatch.layoutVideo }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt
new file mode 100644
index 000000000..f8a4458bf
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt
@@ -0,0 +1,92 @@
+package app.revanced.patches.youtube.layout.hide.filterbar
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.FilterBarHeightFingerprint
+import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.RelatedChipCloudFingerprint
+import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.SearchResultsChipBarFingerprint
+import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
+import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
+
+@Patch(
+ name = "Hide filter bar",
+ description = "Hides the filter bar in video feeds.",
+ dependencies = [HideFilterBarResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideFilterBarPatch : BytecodePatch(
+ setOf(
+ RelatedChipCloudFingerprint,
+ SearchResultsChipBarFingerprint,
+ FilterBarHeightFingerprint
+ )
+) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideFilterBarPatch;"
+
+ override fun execute(context: BytecodeContext) {
+ FilterBarHeightFingerprint.patch { register ->
+ """
+ invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInFeed(I)I
+ move-result v$register
+ """
+ }
+
+ RelatedChipCloudFingerprint.patch(1) { register ->
+ "invoke-static { v$register }, " +
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V"
+ }
+
+ SearchResultsChipBarFingerprint.patch(-1, -2) { register ->
+ """
+ invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInSearch(I)I
+ move-result v$register
+ """
+ }
+ }
+
+ /**
+ * Patch a [MethodFingerprint] with a given [instructions].
+ *
+ * @param RegisterInstruction The type of instruction to get the register from.
+ * @param insertIndexOffset The offset to add to the end index of the [MethodFingerprint].
+ * @param hookRegisterOffset The offset to add to the register of the hook.
+ * @param instructions The instructions to add with the register as a parameter.
+ */
+ private fun MethodFingerprint.patch(
+ insertIndexOffset: Int = 0,
+ hookRegisterOffset: Int = 0,
+ instructions: (Int) -> String
+ ) =
+ result?.let {
+ it.mutableMethod.apply {
+ val endIndex = it.scanResult.patternScanResult!!.endIndex
+
+ val insertIndex = endIndex + insertIndexOffset
+ val register =
+ getInstruction(endIndex + hookRegisterOffset).registerA
+
+ addInstructions(insertIndex, instructions(register))
+ }
+ } ?: throw exception
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarResourcePatch.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarResourcePatch.kt
index 9360541b1..b726c25ac 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarResourcePatch.kt
@@ -1,16 +1,20 @@
-package app.revanced.patches.youtube.layout.hide.filterbar.patch
+package app.revanced.patches.youtube.layout.hide.filterbar
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
+object HideFilterBarResourcePatch : ResourcePatch() {
+ internal var filterBarHeightId = -1L
+ internal var relatedChipCloudMarginId = -1L
+ internal var barContainerHeightId = -1L
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class HideFilterBarResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -78,12 +82,6 @@ class HideFilterBarResourcePatch : ResourcePatch {
barContainerHeightId = "bar_container_height".layoutResourceId()
}
- internal companion object {
- var filterBarHeightId = -1L
- var relatedChipCloudMarginId = -1L
- var barContainerHeightId = -1L
-
private fun String.layoutResourceId(type: String = "dimen") =
ResourceMappingPatch.resourceMappings.single { it.type == type && it.name == this }.id
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/annotations/HideFilterBar.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/annotations/HideFilterBar.kt
deleted file mode 100644
index 8ff7bf497..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/annotations/HideFilterBar.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.filterbar.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideFilterBar
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt
index 2bea01f58..2f7f36a2b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch
+import app.revanced.patches.youtube.layout.hide.filterbar.HideFilterBarResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -15,5 +15,5 @@ object FilterBarHeightFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT,
Opcode.IPUT
),
- literal = HideFilterBarResourcePatch.filterBarHeightId
+ literalSupplier = { HideFilterBarResourcePatch.filterBarHeightId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt
index fd811c155..cafd605d0 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch
+import app.revanced.patches.youtube.layout.hide.filterbar.HideFilterBarResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -14,5 +14,5 @@ object RelatedChipCloudFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
- literal = HideFilterBarResourcePatch.relatedChipCloudMarginId
+ literalSupplier = { HideFilterBarResourcePatch.relatedChipCloudMarginId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt
index 866ec82f8..da4a1c943 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch
+import app.revanced.patches.youtube.layout.hide.filterbar.HideFilterBarResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -16,5 +16,5 @@ object SearchResultsChipBarFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
- literal = HideFilterBarResourcePatch.barContainerHeightId
+ literalSupplier = { HideFilterBarResourcePatch.barContainerHeightId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarPatch.kt
deleted file mode 100644
index 02c7fa009..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarPatch.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.filterbar.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.filterbar.annotations.HideFilterBar
-import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.FilterBarHeightFingerprint
-import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.RelatedChipCloudFingerprint
-import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.SearchResultsChipBarFingerprint
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-
-@Patch
-@Name("Hide filter bar")
-@Description("Hides the filter bar in video feeds.")
-@DependsOn([HideFilterBarResourcePatch::class])
-@HideFilterBar
-class HideFilterBarPatch : BytecodePatch(
- listOf(
- RelatedChipCloudFingerprint,
- SearchResultsChipBarFingerprint,
- FilterBarHeightFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- FilterBarHeightFingerprint.patch { register ->
- """
- invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInFeed(I)I
- move-result v$register
- """
- }
-
- RelatedChipCloudFingerprint.patch(1) { register ->
- "invoke-static { v$register }, " +
- "$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V"
- }
-
- SearchResultsChipBarFingerprint.patch(-1, -2) { register ->
- """
- invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInSearch(I)I
- move-result v$register
- """
- }
- }
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/HideFilterBarPatch;"
-
- /**
- * Patch a [MethodFingerprint] with a given [instructions].
- *
- * @param RegisterInstruction The type of instruction to get the register from.
- * @param insertIndexOffset The offset to add to the end index of the [MethodFingerprint].
- * @param hookRegisterOffset The offset to add to the register of the hook.
- * @param instructions The instructions to add with the register as a parameter.
- */
- private fun MethodFingerprint.patch(
- insertIndexOffset: Int = 0,
- hookRegisterOffset: Int = 0,
- instructions: (Int) -> String
- ) =
- result?.let {
- it.mutableMethod.apply {
- val endIndex = it.scanResult.patternScanResult!!.endIndex
-
- val insertIndex = endIndex + insertIndexOffset
- val register = getInstruction(endIndex + hookRegisterOffset).registerA
-
- addInstructions(insertIndex, instructions(register))
- }
- } ?: throw exception
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt
index 1f9e63867..8ec4bd788 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt
@@ -1,31 +1,47 @@
-package app.revanced.patches.youtube.layout.hide.floatingmicrophone.patch
+package app.revanced.patches.youtube.layout.hide.floatingmicrophone
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.floatingmicrophone.annotations.HideFloatingMicrophoneButtonCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.floatingmicrophone.fingerprints.ShowFloatingMicrophoneButtonFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-@Patch
-@Name("Hide floating microphone button")
-@Description("Hides the floating microphone button which appears in search.")
-@DependsOn([HideFloatingMicrophoneButtonResourcePatch::class])
-@HideFloatingMicrophoneButtonCompatibility
-class HideFloatingMicrophoneButtonPatch : BytecodePatch(
- listOf(ShowFloatingMicrophoneButtonFingerprint)
+@Patch(
+ name = "Hide floating microphone button",
+ description = "Hides the floating microphone button which appears in search.",
+ dependencies = [HideFloatingMicrophoneButtonResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideFloatingMicrophoneButtonPatch : BytecodePatch(
+ setOf(ShowFloatingMicrophoneButtonFingerprint)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideFloatingMicrophoneButtonPatch;"
+
override fun execute(context: BytecodeContext) {
ShowFloatingMicrophoneButtonFingerprint.result?.let { result ->
with(result.mutableMethod) {
val insertIndex = result.scanResult.patternScanResult!!.startIndex + 1
- val showButtonRegister = getInstruction(insertIndex - 1).registerA
+ val showButtonRegister =
+ getInstruction(insertIndex - 1).registerA
addInstructions(
insertIndex,
@@ -37,9 +53,4 @@ class HideFloatingMicrophoneButtonPatch : BytecodePatch(
}
} ?: throw ShowFloatingMicrophoneButtonFingerprint.exception
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/HideFloatingMicrophoneButtonPatch;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonResourcePatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonResourcePatch.kt
index 7dcb04ab8..ba5b0372b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonResourcePatch.kt
@@ -1,18 +1,23 @@
-package app.revanced.patches.youtube.layout.hide.floatingmicrophone.patch
+package app.revanced.patches.youtube.layout.hide.floatingmicrophone
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.floatingmicrophone.annotations.HideFloatingMicrophoneButtonCompatibility
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ]
+)
+object HideFloatingMicrophoneButtonResourcePatch : ResourcePatch() {
+ internal var fabButtonId: Long = -1
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-@HideFloatingMicrophoneButtonCompatibility
-class HideFloatingMicrophoneButtonResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
@@ -29,8 +34,4 @@ class HideFloatingMicrophoneButtonResourcePatch : ResourcePatch {
fabButtonId = ResourceMappingPatch.resourceMappings.find { it.type == "id" && it.name == "fab" }?.id
?: throw PatchException("Can not find required fab button resource id")
}
-
- internal companion object {
- var fabButtonId: Long = -1
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt
deleted file mode 100644
index 04d54c63e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.floatingmicrophone.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideFloatingMicrophoneButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt
index 16deabe29..bc1e4efba 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt
@@ -1,8 +1,8 @@
package app.revanced.patches.youtube.layout.hide.floatingmicrophone.fingerprints
import app.revanced.patcher.extensions.or
+import app.revanced.patches.youtube.layout.hide.floatingmicrophone.HideFloatingMicrophoneButtonResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.layout.hide.floatingmicrophone.patch.HideFloatingMicrophoneButtonResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -15,5 +15,5 @@ object ShowFloatingMicrophoneButtonFingerprint : LiteralValueFingerprint(
Opcode.IF_EQZ,
Opcode.RETURN_VOID
),
- literal = HideFloatingMicrophoneButtonResourcePatch.fabButtonId
+ literalSupplier = { HideFloatingMicrophoneButtonResourcePatch.fabButtonId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/patch/HideLayoutComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt
similarity index 81%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/patch/HideLayoutComponentsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt
index 8ca4278b2..d88ad6cd7 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/patch/HideLayoutComponentsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt
@@ -1,35 +1,48 @@
-package app.revanced.patches.youtube.layout.hide.general.patch
+package app.revanced.patches.youtube.layout.hide.general
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
+import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.shared.settings.preference.impl.TextPreference
-import app.revanced.patches.youtube.layout.hide.general.annotations.HideLayoutComponentsCompatibility
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
-@Patch
-@Name("Hide layout components")
-@Description("Hides general layout components.")
-@DependsOn([LithoFilterPatch::class, SettingsPatch::class])
-@HideLayoutComponentsCompatibility
-class HideLayoutComponentsPatch : BytecodePatch(
- listOf(ParseElementFromBufferFingerprint)
+@Patch(
+ name = "Hide layout components",
+ description = "Hides general layout components.",
+ dependencies = [
+ LithoFilterPatch::class,
+ SettingsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideLayoutComponentsPatch : BytecodePatch(
+ setOf(ParseElementFromBufferFingerprint)
) {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
+
override fun execute(context: BytecodeContext) {
PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
@@ -38,6 +51,40 @@ class HideLayoutComponentsPatch : BytecodePatch(
StringResource("revanced_hide_gray_separator_summary_on", "Gray separators are hidden"),
StringResource("revanced_hide_gray_separator_summary_off", "Gray separators are shown")
),
+ SwitchPreference(
+ "revanced_hide_join_membership_button",
+ StringResource("revanced_hide_join_membership_button_title", "Hide \"Join\" button"),
+ StringResource("revanced_hide_join_membership_button_summary_on", "Button is hidden"),
+ StringResource("revanced_hide_join_membership_button_summary_off", "Button is shown")
+ ),
+
+ SwitchPreference(
+ "revanced_hide_notify_me_button",
+ StringResource("revanced_hide_notify_me_button_title", "Hide \"Notify me\" button"),
+ StringResource("revanced_hide_notify_me_button_summary_on", "Button is hidden"),
+ StringResource("revanced_hide_notify_me_button_summary_off", "Button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_timed_reactions",
+ StringResource("revanced_hide_timed_reactions_title", "Hide timed reactions"),
+ StringResource("revanced_hide_timed_reactions_summary_on", "Timed reactions are hidden"),
+ StringResource("revanced_hide_timed_reactions_summary_off", "Timed reactions are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_search_result_shelf_header",
+ StringResource(
+ "revanced_hide_search_result_shelf_header_title",
+ "Hide search result shelf header"
+ ),
+ StringResource(
+ "revanced_hide_search_result_shelf_header_summary_on",
+ "Shelf header is hidden"
+ ),
+ StringResource(
+ "revanced_hide_search_result_shelf_header_summary_off",
+ "Shelf header is shown"
+ )
+ ),
SwitchPreference(
"revanced_hide_channel_guidelines",
StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
@@ -54,7 +101,7 @@ class HideLayoutComponentsPatch : BytecodePatch(
"revanced_hide_expandable_chip",
StringResource(
"revanced_hide_expandable_chip_title",
- "Hide the expandable chip under videos"
+ "Hide expandable chip under videos"
),
StringResource(
"revanced_hide_expandable_chip_summary_on",
@@ -185,12 +232,6 @@ class HideLayoutComponentsPatch : BytecodePatch(
StringResource("revanced_hide_image_shelf_summary_on", "Image shelf is hidden"),
StringResource("revanced_hide_image_shelf_summary_off", "Image shelf is shown")
),
- SwitchPreference(
- "revanced_hide_audio_track_button",
- StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"),
- StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"),
- StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown")
- ),
SwitchPreference(
"revanced_hide_latest_posts_ads",
StringResource("revanced_hide_latest_posts_ads_title", "Hide latest posts"),
@@ -240,8 +281,9 @@ class HideLayoutComponentsPatch : BytecodePatch(
StringResource("revanced_custom_filter_strings_title", "Custom filter"),
StringResource(
"revanced_custom_filter_strings_summary",
- "Filter components by their name separated by a comma"
- )
+ "List of components to filter separated by new line"
+ ),
+ inputType = InputType.TEXT_MULTI_LINE
)
)
)
@@ -274,9 +316,4 @@ class HideLayoutComponentsPatch : BytecodePatch(
// endregion
}
-
- internal companion object {
- private const val FILTER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/annotations/HideLayoutComponentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/annotations/HideLayoutComponentsCompatibility.kt
deleted file mode 100644
index 962bbc66d..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/annotations/HideLayoutComponentsCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.general.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideLayoutComponentsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt
index c4eb75057..a09daed51 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt
@@ -1,39 +1,58 @@
-package app.revanced.patches.youtube.layout.hide.infocards.patch
+package app.revanced.patches.youtube.layout.hide.infocards
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.youtube.layout.hide.infocards.annotations.HideInfocardsCompatibility
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsIncognitoFingerprint
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsIncognitoParentFingerprint
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsMethodCallFingerprint
-import app.revanced.patches.youtube.layout.hide.infocards.resource.patch.HideInfocardsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
-@Patch
-@DependsOn([IntegrationsPatch::class, HideInfocardsResourcePatch::class])
-@Name("Hide info cards")
-@Description("Hides info cards in videos.")
-@HideInfocardsCompatibility
-class HideInfoCardsPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Hide info cards",
+ description = "Hides info cards in videos.",
+ dependencies = [
+ IntegrationsPatch::class,
+ LithoFilterPatch::class,
+ HideInfocardsResourcePatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideInfoCardsPatch : BytecodePatch(
+ setOf(
InfocardsIncognitoParentFingerprint,
InfocardsMethodCallFingerprint,
)
) {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/HideInfoCardsFilterPatch;"
+
override fun execute(context: BytecodeContext) {
- InfocardsIncognitoFingerprint.also {
+ InfocardsIncognitoFingerprint.also {
it.resolve(context, InfocardsIncognitoParentFingerprint.result!!.classDef)
}.result!!.mutableMethod.apply {
val invokeInstructionIndex = implementation!!.instructions.indexOfFirst {
@@ -66,5 +85,8 @@ class HideInfoCardsPatch : BytecodePatch(
)
)
}
+
+ // Info cards can also appear as litho components.
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfocardsResourcePatch.kt
similarity index 60%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfocardsResourcePatch.kt
index 27a1e48c0..fe3220fab 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfocardsResourcePatch.kt
@@ -1,20 +1,21 @@
-package app.revanced.patches.youtube.layout.hide.infocards.resource.patch
+package app.revanced.patches.youtube.layout.hide.infocards
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.infocards.annotations.HideInfocardsCompatibility
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@HideInfocardsCompatibility
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class HideInfocardsResourcePatch : ResourcePatch {
- internal companion object {
- var drawerResourceId: Long = -1
- }
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ],
+)
+object HideInfocardsResourcePatch : ResourcePatch() {
+ internal var drawerResourceId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt
deleted file mode 100644
index 2406c2ce2..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.infocards.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideInfocardsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt
index 9d8446717..1336de5e4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.layout.hide.infocards.fingerprints
+import app.revanced.patches.youtube.layout.hide.infocards.HideInfocardsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.layout.hide.infocards.resource.patch.HideInfocardsResourcePatch
import com.android.tools.smali.dexlib2.Opcode
object InfocardsMethodCallFingerprint : LiteralValueFingerprint(
@@ -11,5 +11,5 @@ object InfocardsMethodCallFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_INTERFACE,
),
strings = listOf("Missing ControlsOverlayPresenter for InfoCards to work."),
- literal = HideInfocardsResourcePatch.drawerResourceId
+ literalSupplier = { HideInfocardsResourcePatch.drawerResourceId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt
new file mode 100644
index 000000000..83321ce09
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt
@@ -0,0 +1,55 @@
+package app.revanced.patches.youtube.layout.hide.loadmorebutton
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.fingerprints.HideLoadMoreButtonFingerprint
+import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch(
+ name = "Hide \"Load more\" button",
+ description = "Hides the button under videos that loads similar videos.",
+ dependencies = [HideLoadMoreButtonResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideLoadMoreButtonPatch : BytecodePatch(
+ setOf(HideLoadMoreButtonFingerprint)
+) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideLoadMoreButtonPatch;"
+
+ override fun execute(context: BytecodeContext) {
+ HideLoadMoreButtonFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val moveRegisterIndex = it.scanResult.patternScanResult!!.endIndex
+ val viewRegister =
+ getInstruction(moveRegisterIndex).registerA
+
+ val insertIndex = moveRegisterIndex + 1
+ addInstruction(
+ insertIndex,
+ "invoke-static { v$viewRegister }, " +
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V"
+ )
+ }
+ } ?: throw HideLoadMoreButtonFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/resource/patch/HideLoadMoreButtonResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonResourcePatch.kt
similarity index 59%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/resource/patch/HideLoadMoreButtonResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonResourcePatch.kt
index b50779d26..ae2e7a8ed 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/resource/patch/HideLoadMoreButtonResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonResourcePatch.kt
@@ -1,22 +1,29 @@
-package app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch
+package app.revanced.patches.youtube.layout.hide.loadmorebutton
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ dependencies = [
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ]
+)
+object HideLoadMoreButtonResourcePatch : ResourcePatch() {
+ internal var expandButtonDownId: Long = -1
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class HideLoadMoreButtonResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
"revanced_hide_load_more_button",
- StringResource("revanced_hide_load_more_button_title", "Hide Load More button"),
- StringResource("revanced_hide_load_more_button_summary_on", "Load More button is hidden"),
- StringResource("revanced_hide_load_more_button_summary_off", "Load More button is shown")
+ StringResource("revanced_hide_load_more_button_title", "Hide \"Load More\" button"),
+ StringResource("revanced_hide_load_more_button_summary_on", "Button is hidden"),
+ StringResource("revanced_hide_load_more_button_summary_off", "Button is shown")
)
)
@@ -24,8 +31,4 @@ class HideLoadMoreButtonResourcePatch : ResourcePatch {
it.type == "layout" && it.name == "expand_button_down"
}.id
}
-
- internal companion object {
- var expandButtonDownId: Long = -1
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/annotations/HideLoadMoreButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/annotations/HideLoadMoreButtonCompatibility.kt
deleted file mode 100644
index 821868a10..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/annotations/HideLoadMoreButtonCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideLoadMoreButtonCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/patch/HideLoadMoreButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/patch/HideLoadMoreButtonPatch.kt
deleted file mode 100644
index 97c34561f..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/patch/HideLoadMoreButtonPatch.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.loadmorebutton.bytecode.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.loadmorebutton.bytecode.fingerprints.HideLoadMoreButtonFingerprint
-import app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch.HideLoadMoreButtonResourcePatch
-import app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations.HideLoadMoreButtonCompatibility
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-
-@Patch
-@Name("Hide load more button")
-@Description("Hides the button under videos that loads similar videos.")
-@DependsOn([HideLoadMoreButtonResourcePatch::class])
-@HideLoadMoreButtonCompatibility
-class HideLoadMoreButtonPatch : BytecodePatch(listOf(HideLoadMoreButtonFingerprint)) {
- override fun execute(context: BytecodeContext) {
- HideLoadMoreButtonFingerprint.result?.let {
- it.mutableMethod.apply {
- val moveRegisterIndex = it.scanResult.patternScanResult!!.endIndex
- val viewRegister = getInstruction(moveRegisterIndex).registerA
-
- val insertIndex = moveRegisterIndex + 1
- addInstruction(
- insertIndex,
- "invoke-static { v$viewRegister }, " +
- "$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V"
- )
- }
- } ?: throw HideLoadMoreButtonFingerprint.exception
- }
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/HideLoadMoreButtonPatch;"
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/fingerprints/HideLoadMoreButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/fingerprints/HideLoadMoreButtonFingerprint.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/fingerprints/HideLoadMoreButtonFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/fingerprints/HideLoadMoreButtonFingerprint.kt
index 258ba7d9e..49894a271 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/fingerprints/HideLoadMoreButtonFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/fingerprints/HideLoadMoreButtonFingerprint.kt
@@ -1,6 +1,6 @@
-package app.revanced.patches.youtube.layout.hide.loadmorebutton.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.loadmorebutton.fingerprints
-import app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch.HideLoadMoreButtonResourcePatch
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.HideLoadMoreButtonResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
@@ -11,5 +11,5 @@ object HideLoadMoreButtonFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT
),
- literal = HideLoadMoreButtonResourcePatch.expandButtonDownId
+ literalSupplier = { HideLoadMoreButtonResourcePatch.expandButtonDownId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/HideEmailAddressPatch.kt
similarity index 59%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/HideEmailAddressPatch.kt
index 2c2eabc2e..1d1c6157f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/HideEmailAddressPatch.kt
@@ -1,29 +1,37 @@
-package app.revanced.patches.youtube.layout.hide.personalinformation.bytecode.patch
+package app.revanced.patches.youtube.layout.hide.personalinformation
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.personalinformation.annotations.HideEmailAddressCompatibility
-import app.revanced.patches.youtube.layout.hide.personalinformation.bytecode.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
-import app.revanced.patches.youtube.layout.hide.personalinformation.resource.patch.HideEmailAddressResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.hide.personalinformation.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn([IntegrationsPatch::class, HideEmailAddressResourcePatch::class])
-@Name("Hide email address")
-@Description("Hides the email address in the account switcher.")
-@HideEmailAddressCompatibility
-class HideEmailAddressPatch : BytecodePatch(
- listOf(
- AccountSwitcherAccessibilityLabelFingerprint
- )
+@Patch(
+ name = "Hide email address",
+ description = "Hides the email address in the account switcher.",
+ dependencies = [IntegrationsPatch::class, HideEmailAddressResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideEmailAddressPatch : BytecodePatch(
+ setOf(AccountSwitcherAccessibilityLabelFingerprint)
) {
override fun execute(context: BytecodeContext) {
AccountSwitcherAccessibilityLabelFingerprint.result?.let {
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/HideEmailAddressResourcePatch.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/HideEmailAddressResourcePatch.kt
index bd6bf8c83..8044a32e3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/HideEmailAddressResourcePatch.kt
@@ -1,18 +1,17 @@
-package app.revanced.patches.youtube.layout.hide.personalinformation.resource.patch
+package app.revanced.patches.youtube.layout.hide.personalinformation
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class HideEmailAddressResourcePatch : ResourcePatch {
- companion object {
- internal var accountSwitcherAccessibilityLabelId: Long = -1
- }
+@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
+@Suppress("unused")
+object HideEmailAddressResourcePatch : ResourcePatch() {
+ internal var accountSwitcherAccessibilityLabelId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt
deleted file mode 100644
index ba0bd1d31..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.personalinformation.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideEmailAddressCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
index 915aa5422..7c2bec781 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
@@ -1,7 +1,7 @@
-package app.revanced.patches.youtube.layout.hide.personalinformation.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.personalinformation.fingerprints
+import app.revanced.patches.youtube.layout.hide.personalinformation.HideEmailAddressResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.layout.hide.personalinformation.resource.patch.HideEmailAddressResourcePatch
import com.android.tools.smali.dexlib2.Opcode
object AccountSwitcherAccessibilityLabelFingerprint : LiteralValueFingerprint(
@@ -16,5 +16,5 @@ object AccountSwitcherAccessibilityLabelFingerprint : LiteralValueFingerprint(
Opcode.APUT_OBJECT,
Opcode.CONST,
),
- literal = HideEmailAddressResourcePatch.accountSwitcherAccessibilityLabelId
+ literalSupplier = { HideEmailAddressResourcePatch.accountSwitcherAccessibilityLabelId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/patch/HidePlayerFlyoutMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt
similarity index 82%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/patch/HidePlayerFlyoutMenuPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt
index 9099f5824..b7d556374 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/patch/HidePlayerFlyoutMenuPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt
@@ -1,24 +1,41 @@
-package app.revanced.patches.youtube.layout.hide.player.flyoutmenupanel.patch
+package app.revanced.patches.youtube.layout.hide.player.flyoutmenupanel
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.player.flyoutmenupanel.annotations.HidePlayerFlyoutMenuItemsCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ name = "Player flyout menu",
+ description = "Hides player flyout menu items.",
+ dependencies = [
+ LithoFilterPatch::class,
+ SettingsPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ])
+ ]
+)
+@Suppress("unused")
+object HidePlayerFlyoutMenuPatch : ResourcePatch() {
+ private const val KEY = "revanced_hide_player_flyout"
+
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/PlayerFlyoutMenuItemsFilter;"
-@Patch
-@Name("Player flyout menu")
-@Description("Hides player flyout menu items.")
-@DependsOn([LithoFilterPatch::class, SettingsPatch::class])
-@HidePlayerFlyoutMenuItemsCompatibility
-class HidePlayerFlyoutMenuPatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -92,11 +109,4 @@ class HidePlayerFlyoutMenuPatch : ResourcePatch {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
}
-
- private companion object {
- const val KEY = "revanced_hide_player_flyout"
-
- const val FILTER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/components/PlayerFlyoutMenuItemsFilter;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/annotations/HidePlayerFlyoutMenuItemsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/annotations/HidePlayerFlyoutMenuItemsCompatibility.kt
deleted file mode 100644
index 3149b8d77..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/annotations/HidePlayerFlyoutMenuItemsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.player.flyoutmenupanel.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HidePlayerFlyoutMenuItemsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt
similarity index 61%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt
index dcdecd722..39b2a540a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt
@@ -1,37 +1,46 @@
-package app.revanced.patches.youtube.layout.hide.seekbar.patch
+package app.revanced.patches.youtube.layout.hide.seekbar
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.shared.fingerprints.SeekbarFingerprint
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.shared.fingerprints.SeekbarFingerprint
import app.revanced.patches.shared.fingerprints.SeekbarOnDrawFingerprint
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.seekbar.annotations.HideSeekbarCompatibility
-import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
-import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.layout.seekbar.SeekbarColorBytecodePatch
+import app.revanced.patches.youtube.layout.seekbar.SeekbarPreferencesPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([
- IntegrationsPatch::class,
- SettingsPatch::class,
- // Does not alter the behavior of the seek bar by default.
- SeekbarColorBytecodePatch::class,
- // Used to add preferences to the seekbar settings menu.
- SeekbarPreferencesPatch::class
-])
-@Name("Hide seekbar")
-@Description("Hides the seekbar.")
-@HideSeekbarCompatibility
-class HideSeekbarPatch : BytecodePatch(
- listOf(SeekbarFingerprint)
+@Patch(
+ name = "Hide seekbar",
+ description = "Hides the seekbar.",
+ dependencies = [
+ IntegrationsPatch::class,
+ SettingsPatch::class,
+ SeekbarColorBytecodePatch::class,
+ SeekbarPreferencesPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideSeekbarPatch : BytecodePatch(
+ setOf(SeekbarFingerprint)
) {
override fun execute(context: BytecodeContext) {
SeekbarPreferencesPatch.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt
deleted file mode 100644
index a1fdebcc1..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.seekbar.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideSeekbarCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt
similarity index 66%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt
index 04262324a..c6708c049 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt
@@ -1,42 +1,50 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.patch
+package app.revanced.patches.youtube.layout.hide.shorts
+import app.revanced.extensions.exception
import app.revanced.extensions.findIndexForIdResource
import app.revanced.extensions.injectHideViewCall
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-import app.revanced.patches.youtube.layout.hide.shorts.annotations.HideShortsComponentsCompatibility
-import app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints.*
-import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
+import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.*
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-@Patch
-@DependsOn(
- [
+@Patch(
+ name = "Hide Shorts components",
+ description = "Hides components from YouTube Shorts.",
+ dependencies = [
IntegrationsPatch::class,
LithoFilterPatch::class,
HideShortsComponentsResourcePatch::class,
ResourceMappingPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
]
)
-@Name("Hide Shorts components")
-@Description("Hides components from YouTube Shorts.")
-@HideShortsComponentsCompatibility
-class HideShortsComponentsPatch : BytecodePatch(
- listOf(
+@Suppress("unused")
+object HideShortsComponentsPatch : BytecodePatch(
+ setOf(
CreateShortsButtonsFingerprint,
ReelConstructorFingerprint,
BottomNavigationBarFingerprint,
@@ -44,9 +52,9 @@ class HideShortsComponentsPatch : BytecodePatch(
SetPivotBarVisibilityParentFingerprint
)
) {
- override fun execute(context: BytecodeContext) {
- LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+ private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
+ override fun execute(context: BytecodeContext) {
// region Hide the Shorts shelf.
ReelConstructorFingerprint.result?.let {
@@ -65,13 +73,20 @@ class HideShortsComponentsPatch : BytecodePatch(
// endregion
- // region Hide the Shorts buttons.
+ // region Hide the Shorts buttons in older versions of YouTube.
// Some Shorts buttons are views, hide them by setting their visibility to GONE.
CreateShortsButtonsFingerprint.result?.let {
- ShortsButtons.values().forEach { button -> button.injectHideCall(it.mutableMethod) }
+ ShortsButtons.entries.forEach { button -> button.injectHideCall(it.mutableMethod) }
} ?: throw CreateShortsButtonsFingerprint.exception
+
+ // endregion
+
+ // region Hide the Shorts buttons in newer versions of YouTube.
+
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+
// endregion
// region Hide the navigation bar.
@@ -83,10 +98,10 @@ class HideShortsComponentsPatch : BytecodePatch(
SetPivotBarVisibilityFingerprint.result!!.let { result ->
result.mutableMethod.apply {
- val checkCastIndex = result.scanResult.patternScanResult!!.endIndex
- val viewRegister = getInstruction(checkCastIndex).registerA
+ val insertIndex = result.scanResult.patternScanResult!!.endIndex
+ val viewRegister = getInstruction(insertIndex - 1).registerA
addInstruction(
- checkCastIndex + 1,
+ insertIndex,
"sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->pivotBar:" +
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
)
@@ -122,21 +137,18 @@ class HideShortsComponentsPatch : BytecodePatch(
// endregion
}
- private companion object {
- private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
- private enum class ShortsButtons(private val resourceName: String, private val methodName: String) {
- COMMENTS("reel_dyn_comment", "hideShortsCommentsButton"),
- REMIX("reel_dyn_remix", "hideShortsRemixButton"),
- SHARE("reel_dyn_share", "hideShortsShareButton");
+ private enum class ShortsButtons(private val resourceName: String, private val methodName: String) {
+ COMMENTS("reel_dyn_comment", "hideShortsCommentsButton"),
+ REMIX("reel_dyn_remix", "hideShortsRemixButton"),
+ SHARE("reel_dyn_share", "hideShortsShareButton");
- fun injectHideCall(method: MutableMethod) {
- val referencedIndex = method.findIndexForIdResource(resourceName)
+ fun injectHideCall(method: MutableMethod) {
+ val referencedIndex = method.findIndexForIdResource(resourceName)
- val setIdIndex = referencedIndex + 1
- val viewRegister = method.getInstruction(setIdIndex).registerC
- method.injectHideViewCall(setIdIndex, viewRegister, FILTER_CLASS_DESCRIPTOR, methodName)
- }
+ val setIdIndex = referencedIndex + 1
+ val viewRegister = method.getInstruction(setIdIndex).registerC
+ method.injectHideViewCall(setIdIndex, viewRegister, FILTER_CLASS_DESCRIPTOR, methodName)
}
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt
similarity index 91%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt
index bc8197055..574eb752f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt
@@ -1,16 +1,19 @@
-package app.revanced.patches.youtube.layout.hide.shorts.resource.patch
+package app.revanced.patches.youtube.layout.hide.shorts
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
+object HideShortsComponentsResourcePatch : ResourcePatch() {
+ internal var reelMultipleItemShelfId = -1L
+ internal var reelPlayerRightCellButtonHeight = -1L
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class HideShortsComponentsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -93,9 +96,4 @@ class HideShortsComponentsResourcePatch : ResourcePatch {
reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
reelPlayerRightCellButtonHeight = "reel_player_right_cell_button_height".getId()
}
-
- companion object {
- var reelMultipleItemShelfId = -1L
- var reelPlayerRightCellButtonHeight = -1L
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/annotations/HideShortsComponentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/annotations/HideShortsComponentsCompatibility.kt
deleted file mode 100644
index 97c071786..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/annotations/HideShortsComponentsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.shorts.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideShortsComponentsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityFingerprint.kt
deleted file mode 100644
index fdd010b1b..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityFingerprint.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
-
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import com.android.tools.smali.dexlib2.Opcode
-
-object SetPivotBarVisibilityFingerprint : MethodFingerprint(
- parameters = listOf("Z"),
- opcodes = listOf(
- Opcode.IGET_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT,
- Opcode.IF_EQZ,
- Opcode.RETURN_VOID,
- Opcode.IGET_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CHECK_CAST,
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/BottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/BottomNavigationBarFingerprint.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/BottomNavigationBarFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/BottomNavigationBarFingerprint.kt
index a5ca9d9c4..a451bb459 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/BottomNavigationBarFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/BottomNavigationBarFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/CreateShortsButtonsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/CreateShortsButtonsFingerprint.kt
similarity index 56%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/CreateShortsButtonsFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/CreateShortsButtonsFingerprint.kt
index 4412d8796..3a3222d22 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/CreateShortsButtonsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/CreateShortsButtonsFingerprint.kt
@@ -1,7 +1,7 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
+import app.revanced.patches.youtube.layout.hide.shorts.HideShortsComponentsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
@@ -9,5 +9,5 @@ object CreateShortsButtonsFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("Z", "Z", "L"),
- literal = HideShortsComponentsResourcePatch.reelPlayerRightCellButtonHeight
+ literalSupplier = { HideShortsComponentsResourcePatch.reelPlayerRightCellButtonHeight }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/ReelConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/ReelConstructorFingerprint.kt
similarity index 59%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/ReelConstructorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/ReelConstructorFingerprint.kt
index a9b195ba3..215d297ca 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/ReelConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/ReelConstructorFingerprint.kt
@@ -1,13 +1,13 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
import app.revanced.patcher.extensions.or
+import app.revanced.patches.youtube.layout.hide.shorts.HideShortsComponentsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object ReelConstructorFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
opcodes = listOf(Opcode.INVOKE_VIRTUAL),
- literal = HideShortsComponentsResourcePatch.reelMultipleItemShelfId
+ literalSupplier = { HideShortsComponentsResourcePatch.reelMultipleItemShelfId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/RenderBottomNavigationBarFingerprint.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/RenderBottomNavigationBarFingerprint.kt
index f20e9c62c..8adeec080 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/RenderBottomNavigationBarFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
similarity index 74%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
index 70a2ebc0a..44f98a0b2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/SetPivotBarVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/SetPivotBarVisibilityFingerprint.kt
new file mode 100644
index 000000000..464a9eb79
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/SetPivotBarVisibilityFingerprint.kt
@@ -0,0 +1,16 @@
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.Opcode
+
+object SetPivotBarVisibilityFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ parameters = listOf("Z"),
+ opcodes = listOf(
+ Opcode.CHECK_CAST,
+ Opcode.IF_EQZ
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
index 170569b9a..14431fc7e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt
similarity index 61%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt
index a8efcdcba..836a601f3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt
@@ -1,29 +1,38 @@
-package app.revanced.patches.youtube.layout.hide.time.patch
+package app.revanced.patches.youtube.layout.hide.time
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.time.annotations.HideTimeCompatibility
import app.revanced.patches.youtube.layout.hide.time.fingerprints.TimeCounterFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Hide timestamp")
-@Description("Hides timestamp in video player.")
-@HideTimeCompatibility
-class HideTimestampPatch : BytecodePatch(
- listOf(
- TimeCounterFingerprint
- )
+@Patch(
+ name = "Hide timestamp",
+ description = "Hides timestamp in video player.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideTimestampPatch : BytecodePatch(
+ setOf(TimeCounterFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt
deleted file mode 100644
index bfc3ecbc7..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.time.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideTimeCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/HideWatermarkPatch.kt
similarity index 67%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/HideWatermarkPatch.kt
index e2b7f12f3..72bda6de5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/HideWatermarkPatch.kt
@@ -1,32 +1,42 @@
-package app.revanced.patches.youtube.layout.hide.watermark.patch
+package app.revanced.patches.youtube.layout.hide.watermark
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.watermark.annotations.HideWatermarkCompatibility
import app.revanced.patches.youtube.layout.hide.watermark.fingerprints.HideWatermarkFingerprint
import app.revanced.patches.youtube.layout.hide.watermark.fingerprints.HideWatermarkParentFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Hide watermark")
-@Description("Hides creator's watermarks on videos.")
-@HideWatermarkCompatibility
-class HideWatermarkPatch : BytecodePatch(
- listOf(
- HideWatermarkParentFingerprint
- )
+@Patch(
+ name = "Hide watermark",
+ description = "Hides creator's watermarks on videos.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HideWatermarkPatch : BytecodePatch(
+ setOf(HideWatermarkParentFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWatermarkCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWatermarkCompatibility.kt
deleted file mode 100644
index 58cfdd922..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWatermarkCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.watermark.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideWatermarkCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt
index d9848d0df..e91a9ff2b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt
@@ -1,29 +1,38 @@
-package app.revanced.patches.youtube.layout.panels.popup.patch
+package app.revanced.patches.youtube.layout.panels.popup
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.panels.popup.annotations.PlayerPopupPanelsCompatibility
import app.revanced.patches.youtube.layout.panels.popup.fingerprints.EngagementPanelControllerFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Disable player popup panels")
-@Description("Disables panels from appearing automatically when going into fullscreen (playlist or live chat).")
-@PlayerPopupPanelsCompatibility
-class PlayerPopupPanelsPatch : BytecodePatch(
- listOf(
- EngagementPanelControllerFingerprint
- )
+@Patch(
+ name = "Disable player popup panels",
+ description = "Disables panels from appearing automatically when going into fullscreen (playlist or live chat).",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object PlayerPopupPanelsPatch : BytecodePatch(
+ setOf(EngagementPanelControllerFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt
deleted file mode 100644
index 78eb5708e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.panels.popup.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerPopupPanelsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt
new file mode 100644
index 000000000..764434c33
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt
@@ -0,0 +1,43 @@
+package app.revanced.patches.youtube.layout.player.background
+
+import app.revanced.extensions.doRecursively
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import org.w3c.dom.Element
+
+@Patch(
+ name = "Remove player controls background",
+ description = "Removes the background from the video player controls.",
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ],
+ use = false
+)
+@Suppress("unused")
+object PlayerControlsBackgroundPatch : ResourcePatch() {
+ private const val RESOURCE_FILE_PATH = "res/drawable/player_button_circle_background.xml"
+
+ override fun execute(context: ResourceContext) {
+ context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
+ editor.file.doRecursively node@{ node ->
+ if (node !is Element) return@node
+
+ node.getAttributeNode("android:color")?.let { attribute ->
+ attribute.textContent = "@android:color/transparent"
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/annotations/PlayerControlsBackgroundCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/annotations/PlayerControlsBackgroundCompatibility.kt
deleted file mode 100644
index 2a6f35bbe..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/annotations/PlayerControlsBackgroundCompatibility.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package app.revanced.patches.youtube.layout.player.background.annotations
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerControlsBackgroundCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/patch/PlayerControlsBackgroundPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/patch/PlayerControlsBackgroundPatch.kt
deleted file mode 100644
index 5096eb771..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/patch/PlayerControlsBackgroundPatch.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package app.revanced.patches.youtube.layout.player.background.patch
-
-import app.revanced.extensions.doRecursively
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.player.background.annotations.PlayerControlsBackgroundCompatibility
-import org.w3c.dom.Element
-
-@Patch(false)
-@Name("Remove player controls background")
-@Description("Removes the background from the video player controls.")
-@PlayerControlsBackgroundCompatibility
-class PlayerControlsBackgroundPatch : ResourcePatch {
- override fun execute(context: ResourceContext) {
- context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
- editor.file.doRecursively node@{ node ->
- if (node !is Element) return@node
-
- node.getAttributeNode("android:color")?.let { attribute ->
- attribute.textContent = "@android:color/transparent"
- }
- }
- }
- }
-
- private companion object {
- const val RESOURCE_FILE_PATH = "res/drawable/player_button_circle_background.xml"
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/bytecode/patch/CustomPlayerOverlayOpacityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt
similarity index 55%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/bytecode/patch/CustomPlayerOverlayOpacityPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt
index cbb46b92a..5da8d54bb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/bytecode/patch/CustomPlayerOverlayOpacityPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt
@@ -1,26 +1,28 @@
-package app.revanced.patches.youtube.layout.player.overlay.bytecode.patch
+package app.revanced.patches.youtube.layout.player.overlay
-import app.revanced.extensions.indexOfFirstConstantInstructionValue
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
+import app.revanced.extensions.indexOfFirstConstantInstructionValue
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.player.overlay.annotations.PlayerOverlayPatchCompatibility
-import app.revanced.patches.youtube.layout.player.overlay.bytecode.fingerprints.CreatePlayerOverviewFingerprint
-import app.revanced.patches.youtube.layout.player.overlay.resource.patch.CustomPlayerOverlayOpacityResourcePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.layout.player.overlay.fingerprints.CreatePlayerOverviewFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@Name("Custom player overlay opacity")
-@Description("Change the opacity of the player background, when player controls are visible.")
-@DependsOn([CustomPlayerOverlayOpacityResourcePatch::class])
-@PlayerOverlayPatchCompatibility
-class CustomPlayerOverlayOpacityPatch : BytecodePatch(listOf(CreatePlayerOverviewFingerprint)) {
+@Patch(
+ name = "Custom player overlay opacity",
+ description = "Change the opacity of the player background, when player controls are visible.",
+ dependencies = [CustomPlayerOverlayOpacityResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube")
+ ]
+)
+@Suppress("unused")
+object CustomPlayerOverlayOpacityPatch : BytecodePatch(setOf(CreatePlayerOverviewFingerprint)) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/CustomPlayerOverlayOpacityPatch;"
+
override fun execute(context: BytecodeContext) {
CreatePlayerOverviewFingerprint.result?.let { result ->
result.mutableMethod.apply {
@@ -38,8 +40,4 @@ class CustomPlayerOverlayOpacityPatch : BytecodePatch(listOf(CreatePlayerOvervie
}
} ?: throw CreatePlayerOverviewFingerprint.exception
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/CustomPlayerOverlayOpacityPatch;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/resource/patch/CustomPlayerOverlayOpacityResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityResourcePatch.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/resource/patch/CustomPlayerOverlayOpacityResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityResourcePatch.kt
index e868a8e20..b7eba42dd 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/resource/patch/CustomPlayerOverlayOpacityResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityResourcePatch.kt
@@ -1,16 +1,20 @@
-package app.revanced.patches.youtube.layout.player.overlay.resource.patch
+package app.revanced.patches.youtube.layout.player.overlay
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ dependencies = [SettingsPatch::class, ResourceMappingPatch::class]
+)
+object CustomPlayerOverlayOpacityResourcePatch : ResourcePatch() {
+ internal var scrimOverlayId = -1L
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class CustomPlayerOverlayOpacityResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
TextPreference(
@@ -31,8 +35,4 @@ class CustomPlayerOverlayOpacityResourcePatch : ResourcePatch {
it.type == "id" && it.name == "scrim_overlay"
}.id
}
-
- internal companion object {
- var scrimOverlayId = -1L
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/annotations/PlayerOverlayPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/annotations/PlayerOverlayPatchCompatibility.kt
deleted file mode 100644
index 71d89ce7e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/annotations/PlayerOverlayPatchCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.player.overlay.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerOverlayPatchCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/bytecode/fingerprints/CreatePlayerOverviewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/fingerprints/CreatePlayerOverviewFingerprint.kt
similarity index 78%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/bytecode/fingerprints/CreatePlayerOverviewFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/fingerprints/CreatePlayerOverviewFingerprint.kt
index ec617403e..8cc77efac 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/bytecode/fingerprints/CreatePlayerOverviewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/fingerprints/CreatePlayerOverviewFingerprint.kt
@@ -1,9 +1,9 @@
-package app.revanced.patches.youtube.layout.player.overlay.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.player.overlay.fingerprints
import app.revanced.extensions.containsConstantInstructionValue
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.youtube.layout.player.overlay.resource.patch.CustomPlayerOverlayOpacityResourcePatch
+import app.revanced.patches.youtube.layout.player.overlay.CustomPlayerOverlayOpacityResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
similarity index 84%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
index 34c22181f..3ab8e1efa 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
@@ -1,46 +1,42 @@
-package app.revanced.patches.youtube.layout.returnyoutubedislike.patch
+package app.revanced.patches.youtube.layout.returnyoutubedislike
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
-import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
-import app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch.ReturnYouTubeDislikeResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
+import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-@Patch
-@DependsOn(
- [
+@Patch(
+ name = "Return YouTube Dislike",
+ description = "Shows the dislike count of videos using the Return YouTube Dislike API.",
+ dependencies = [
IntegrationsPatch::class,
VideoIdPatch::class,
ReturnYouTubeDislikeResourcePatch::class,
PlayerTypeHookPatch::class,
+ ],
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube", ["18.32.39"])
]
)
-@Name("Return YouTube Dislike")
-@Description("Shows the dislike count of videos using the Return YouTube Dislike API.")
-@ReturnYouTubeDislikeCompatibility
-class ReturnYouTubeDislikePatch : BytecodePatch(
- listOf(
+@Suppress("unused")
+object ReturnYouTubeDislikePatch : BytecodePatch(
+ setOf(
TextComponentConstructorFingerprint,
ShortsTextViewFingerprint,
DislikesOldLayoutTextViewFingerprint,
@@ -49,10 +45,13 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
RemoveLikeFingerprint,
)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;"
+
override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
- VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
+ VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
// endregion
@@ -71,7 +70,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->sendVote(I)V
"""
)
- } ?: throw PatchException("Failed to find ${fingerprint.name} method.")
+ } ?: throw fingerprint.exception
}
// endregion
@@ -200,16 +199,11 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
// endregion
}
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;"
-
- private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
- private data class VotePatch(val fingerprint: MethodFingerprint, val voteKind: Vote)
- private enum class Vote(val value: Int) {
- LIKE(1),
- DISLIKE(-1),
- REMOVE_LIKE(0)
- }
+ private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
+ private data class VotePatch(val fingerprint: MethodFingerprint, val voteKind: Vote)
+ private enum class Vote(val value: Int) {
+ LIKE(1),
+ DISLIKE(-1),
+ REMOVE_LIKE(0)
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikeResourcePatch.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikeResourcePatch.kt
index 304623ced..491cfd265 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikeResourcePatch.kt
@@ -1,19 +1,19 @@
-package app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch
+package app.revanced.patches.youtube.layout.returnyoutubedislike
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.resources.ResourceUtils.mergeStrings
-@DependsOn([SettingsPatch::class])
-class ReturnYouTubeDislikeResourcePatch : ResourcePatch {
- companion object {
- internal var oldUIDislikeId: Long = -1
- }
+@Patch(
+ dependencies = [SettingsPatch::class]
+)
+object ReturnYouTubeDislikeResourcePatch : ResourcePatch() {
+ internal var oldUIDislikeId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.addPreference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt
deleted file mode 100644
index 189902dbe..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ReturnYouTubeDislikeCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt
index 19557dde0..4afcb8694 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt
@@ -1,8 +1,8 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
+import app.revanced.patches.youtube.layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch.ReturnYouTubeDislikeResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -18,5 +18,5 @@ object DislikesOldLayoutTextViewFingerprint : LiteralValueFingerprint(
Opcode.IF_NEZ, // textview register
Opcode.GOTO,
),
- literal = ReturnYouTubeDislikeResourcePatch.oldUIDislikeId
+ literalSupplier = { ReturnYouTubeDislikeResourcePatch.oldUIDislikeId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt
index 1009acbd5..a012ad54b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt
@@ -1,12 +1,12 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
+import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object ShortsTextViewFingerprint : MethodFingerprint(
- // 18.29.38 method is public final visibility, but in 18.23.35 and older it's protected final.
- // If 18.23.35 is dropped then accessFlags should be specified here.
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("L", "L"),
opcodes = listOf(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt
similarity index 51%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt
index 21dc3495f..900e1c296 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt
@@ -1,31 +1,43 @@
-package app.revanced.patches.youtube.layout.searchbar.patch
+package app.revanced.patches.youtube.layout.searchbar
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.searchbar.annotations.WideSearchbarCompatibility
import app.revanced.patches.youtube.layout.searchbar.fingerprints.CreateSearchSuggestionsFingerprint
import app.revanced.patches.youtube.layout.searchbar.fingerprints.SetWordmarkHeaderFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Wide searchbar")
-@Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.")
-@WideSearchbarCompatibility
-class WideSearchbarPatch : BytecodePatch(
- listOf(
- SetWordmarkHeaderFingerprint, CreateSearchSuggestionsFingerprint
+@Patch(
+ name = "Wide searchbar",
+ description = "Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object WideSearchbarPatch : BytecodePatch(
+ setOf(
+ SetWordmarkHeaderFingerprint,
+ CreateSearchSuggestionsFingerprint
)
) {
override fun execute(context: BytecodeContext) {
@@ -49,31 +61,29 @@ class WideSearchbarPatch : BytecodePatch(
}
}
- private companion object {
- /**
- * Walk a fingerprints method at a given index mutably.
- *
- * @param index The index to walk at.
- * @param fromFingerprint The fingerprint to walk the method on.
- * @return The [MutableMethod] which was walked on.
- */
- fun BytecodeContext.walkMutable(index: Int, fromFingerprint: MethodFingerprint) =
- fromFingerprint.result?.let {
- toMethodWalker(it.method).nextMethod(index, true).getMethod() as MutableMethod
- } ?: throw fromFingerprint.exception
+ /**
+ * Walk a fingerprints method at a given index mutably.
+ *
+ * @param index The index to walk at.
+ * @param fromFingerprint The fingerprint to walk the method on.
+ * @return The [MutableMethod] which was walked on.
+ */
+ fun BytecodeContext.walkMutable(index: Int, fromFingerprint: MethodFingerprint) =
+ fromFingerprint.result?.let {
+ toMethodWalker(it.method).nextMethod(index, true).getMethod() as MutableMethod
+ } ?: throw fromFingerprint.exception
- /**
- * Injects instructions required for certain methods.
- */
- fun MutableMethod.injectSearchBarHook() {
- addInstructions(
- implementation!!.instructions.size - 1,
- """
+ /**
+ * Injects instructions required for certain methods.
+ */
+ fun MutableMethod.injectSearchBarHook() {
+ addInstructions(
+ implementation!!.instructions.size - 1,
+ """
invoke-static {}, Lapp/revanced/integrations/patches/WideSearchbarPatch;->enableWideSearchbar()Z
move-result p0
"""
- )
- }
+ )
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt
deleted file mode 100644
index c171c6d9e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.searchbar.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class WideSearchbarCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorBytecodePatch.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorBytecodePatch.kt
index 065b894b8..4a98b7fb6 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorBytecodePatch.kt
@@ -1,35 +1,37 @@
-package app.revanced.patches.youtube.layout.seekbar.bytecode.patch
+package app.revanced.patches.youtube.layout.seekbar
-import app.revanced.extensions.indexOfFirstConstantInstructionValue
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
+import app.revanced.extensions.indexOfFirstConstantInstructionValue
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility
-import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.PlayerSeekbarColorFingerprint
-import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
-import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.ShortsSeekbarColorFingerprint
-import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
-import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch
-import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.youtube.layout.seekbar.fingerprints.PlayerSeekbarColorFingerprint
+import app.revanced.patches.youtube.layout.seekbar.fingerprints.SetSeekbarClickedColorFingerprint
+import app.revanced.patches.youtube.layout.seekbar.fingerprints.ShortsSeekbarColorFingerprint
+import app.revanced.patches.youtube.layout.theme.LithoColorHookPatch
+import app.revanced.patches.youtube.layout.theme.LithoColorHookPatch.lithoColorOverrideHook
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
-@Description("Hide or set a custom seekbar color")
-@DependsOn([IntegrationsPatch::class, LithoColorHookPatch::class, SeekbarColorResourcePatch::class])
-@SeekbarColorCompatibility
-class SeekbarColorBytecodePatch : BytecodePatch(
- listOf(PlayerSeekbarColorFingerprint, ShortsSeekbarColorFingerprint, SetSeekbarClickedColorFingerprint)
+@Patch(
+ description = "Hide or set a custom seekbar color",
+ dependencies = [IntegrationsPatch::class, LithoColorHookPatch::class, SeekbarColorResourcePatch::class],
+ compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
+)
+object SeekbarColorBytecodePatch : BytecodePatch(
+ setOf(PlayerSeekbarColorFingerprint, ShortsSeekbarColorFingerprint, SetSeekbarClickedColorFingerprint)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/SeekbarColorPatch;"
+
override fun execute(context: BytecodeContext) {
fun MutableMethod.addColorChangeInstructions(resourceId: Long) {
- var registerIndex = indexOfFirstConstantInstructionValue(resourceId) + 2
- var colorRegister = getInstruction(registerIndex).registerA
+ val registerIndex = indexOfFirstConstantInstructionValue(resourceId) + 2
+ val colorRegister = getInstruction(registerIndex).registerA
addInstructions(
registerIndex + 1,
"""
@@ -71,8 +73,4 @@ class SeekbarColorBytecodePatch : BytecodePatch(
lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getLithoColor")
}
-
- private companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/SeekbarColorPatch;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarColorResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorResourcePatch.kt
similarity index 75%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarColorResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorResourcePatch.kt
index 6991daaa4..581748b5c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarColorResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorResourcePatch.kt
@@ -1,15 +1,18 @@
-package app.revanced.patches.youtube.layout.seekbar.resource
+package app.revanced.patches.youtube.layout.seekbar
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import org.w3c.dom.Element
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class SeekbarColorResourcePatch : ResourcePatch {
+@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
+object SeekbarColorResourcePatch : ResourcePatch(){
+ internal var reelTimeBarPlayedColorId = -1L
+ internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
+ internal var inlineTimeBarPlayedNotHighlightedColorId = -1L
override fun execute(context: ResourceContext) {
fun findColorResource(resourceName: String): Long {
@@ -39,10 +42,4 @@ class SeekbarColorResourcePatch : ResourcePatch {
scaleNode.replaceChild(replacementNode, shapeNode)
}
}
-
- companion object {
- internal var reelTimeBarPlayedColorId = -1L
- internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
- internal var inlineTimeBarPlayedNotHighlightedColorId = -1L
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarPreferencesPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarPreferencesPatch.kt
similarity index 52%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarPreferencesPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarPreferencesPatch.kt
index 84599bf6e..1283fd233 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarPreferencesPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarPreferencesPatch.kt
@@ -1,19 +1,20 @@
-package app.revanced.patches.youtube.layout.seekbar.resource
+package app.revanced.patches.youtube.layout.seekbar
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.*
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.BasePreference
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import java.io.Closeable
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class SeekbarPreferencesPatch : ResourcePatch, Closeable {
- override fun execute(context: ResourceContext) {
+@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
+object SeekbarPreferencesPatch : ResourcePatch(), Closeable {
+ private val seekbarPreferences = mutableListOf()
+ override fun execute(context: ResourceContext) {
// Nothing to do here. All work is done in close method.
}
@@ -27,11 +28,6 @@ class SeekbarPreferencesPatch : ResourcePatch, Closeable {
)
}
- companion object {
- private val seekbarPreferences = mutableListOf()
-
- internal fun addPreferences(vararg preferencesToAdd: BasePreference) {
- seekbarPreferences.addAll(preferencesToAdd)
- }
- }
+ internal fun addPreferences(vararg preferencesToAdd: BasePreference) =
+ seekbarPreferences.addAll(preferencesToAdd)
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/annotations/SeekbarColorCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/annotations/SeekbarColorCompatibility.kt
deleted file mode 100644
index 845bbff94..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/annotations/SeekbarColorCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.seekbar.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class SeekbarColorCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/PlayerSeekbarColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/PlayerSeekbarColorFingerprint.kt
similarity index 80%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/PlayerSeekbarColorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/PlayerSeekbarColorFingerprint.kt
index 67851084a..a4f89764b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/PlayerSeekbarColorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/PlayerSeekbarColorFingerprint.kt
@@ -1,9 +1,9 @@
-package app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.seekbar.fingerprints
import app.revanced.extensions.containsConstantInstructionValue
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
+import app.revanced.patches.youtube.layout.seekbar.SeekbarColorResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
object PlayerSeekbarColorFingerprint : MethodFingerprint(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/SetSeekbarClickedColorFingerprint.kt
similarity index 84%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/SetSeekbarClickedColorFingerprint.kt
index 43eb358d5..a72dcff56 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/SetSeekbarClickedColorFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.seekbar.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/ShortsSeekbarColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/ShortsSeekbarColorFingerprint.kt
similarity index 55%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/ShortsSeekbarColorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/ShortsSeekbarColorFingerprint.kt
index 738e9e433..8b9554c2d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/ShortsSeekbarColorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/fingerprints/ShortsSeekbarColorFingerprint.kt
@@ -1,11 +1,11 @@
-package app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.seekbar.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
+import app.revanced.patches.youtube.layout.seekbar.SeekbarColorResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object ShortsSeekbarColorFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
- literal = SeekbarColorResourcePatch.reelTimeBarPlayedColorId,
+ literalSupplier = { SeekbarColorResourcePatch.reelTimeBarPlayedColorId },
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt
index 88d4489d4..ddc1e9c15 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt
@@ -1,8 +1,6 @@
-package app.revanced.patches.youtube.layout.sponsorblock.bytecode.patch
+package app.revanced.patches.youtube.layout.sponsorblock
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -11,25 +9,23 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
-import app.revanced.patches.shared.fingerprints.SeekbarFingerprint
+import app.revanced.patches.youtube.shared.fingerprints.SeekbarFingerprint
import app.revanced.patches.shared.fingerprints.SeekbarOnDrawFingerprint
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
-import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.AppendTimeFingerprint
-import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.ControlsOverlayFingerprint
-import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.RectangleFieldInvalidatorFingerprint
-import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
+import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.AppendTimeFingerprint
+import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.ControlsOverlayFingerprint
+import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
-import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
-import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
+import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
+import app.revanced.patches.youtube.video.information.VideoInformationPatch
+import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.*
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
@@ -37,9 +33,23 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
-@Patch
-@DependsOn(
- [
+@Patch(
+ name = "SponsorBlock",
+ description = "Integrates SponsorBlock which allows skipping video segments such as sponsored content.",
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ],
+ dependencies = [
IntegrationsPatch::class,
VideoIdPatch::class,
// Required to skip segments on time.
@@ -47,20 +57,27 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
// Used to prevent SponsorBlock from running on Shorts because SponsorBlock does not yet support Shorts.
PlayerTypeHookPatch::class,
PlayerControlsBytecodePatch::class,
- SponsorBlockResourcePatch::class,
+ SponsorBlockResourcePatch::class
]
)
-@Name("SponsorBlock")
-@Description("Integrates SponsorBlock which allows skipping video segments such as sponsored content.")
-@SponsorBlockCompatibility
-class SponsorBlockBytecodePatch : BytecodePatch(
- listOf(
+@Suppress("unused")
+object SponsorBlockBytecodePatch : BytecodePatch(
+ setOf(
SeekbarFingerprint,
AppendTimeFingerprint,
LayoutConstructorFingerprint,
- AutoRepeatParentFingerprint,
+ AutoRepeatParentFingerprint
)
) {
+ private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/sponsorblock/SegmentPlaybackController;"
+ private const val INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController;"
+ private const val INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/sponsorblock/ui/VotingButtonController;"
+ private const val INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/sponsorblock/ui/SponsorBlockViewController;"
+
override fun execute(context: BytecodeContext) {
LayoutConstructorFingerprint.result?.let {
if (!ControlsOverlayFingerprint.resolve(context, it.classDef))
@@ -78,9 +95,9 @@ class SponsorBlockBytecodePatch : BytecodePatch(
}
/*
- * Set current video id
+ * Set current video id.
*/
- VideoIdPatch.injectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
+ VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
/*
* Seekbar drawing
@@ -268,15 +285,4 @@ class SponsorBlockBytecodePatch : BytecodePatch(
// TODO: isSBChannelWhitelisting implementation
}
-
- private companion object {
- const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/sponsorblock/SegmentPlaybackController;"
- const val INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController;"
- const val INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/sponsorblock/ui/VotingButtonController;"
- const val INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/sponsorblock/ui/SponsorBlockViewController;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockResourcePatch.kt
similarity index 89%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockResourcePatch.kt
index 65d8a2deb..57bbb2afc 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockResourcePatch.kt
@@ -1,19 +1,19 @@
-package app.revanced.patches.youtube.layout.sponsorblock.resource.patch
+package app.revanced.patches.youtube.layout.sponsorblock
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.copyXmlNode
import app.revanced.util.resources.ResourceUtils.mergeStrings
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class SponsorBlockResourcePatch : ResourcePatch {
+@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
+object SponsorBlockResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.addPreference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt
deleted file mode 100644
index 6262c3b17..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.sponsorblock.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class SponsorBlockCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/AppendTimeFingerprint.kt
similarity index 91%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/AppendTimeFingerprint.kt
index 18d2497cb..528460d44 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/AppendTimeFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.sponsorblock.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/ControlsOverlayFingerprint.kt
similarity index 90%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ControlsOverlayFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/ControlsOverlayFingerprint.kt
index 934386bc1..eb584f08d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ControlsOverlayFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/ControlsOverlayFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.sponsorblock.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt
similarity index 92%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt
index 623c760f3..33dbb04e4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.sponsorblock.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt
similarity index 62%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt
index 135676df0..b8684cec5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt
@@ -1,33 +1,45 @@
-package app.revanced.patches.youtube.layout.spoofappversion.bytecode.patch
+package app.revanced.patches.youtube.layout.spoofappversion
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.spoofappversion.annotations.SpoofAppVersionCompatibility
-import app.revanced.patches.youtube.layout.spoofappversion.bytecode.fingerprints.SpoofAppVersionFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.layout.spoofappversion.fingerprints.SpoofAppVersionFingerprint
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Spoof app version")
-@Description("Tricks YouTube into thinking you are running an older version of the app. One of the side effects also includes restoring the old UI.")
-@SpoofAppVersionCompatibility
-class SpoofAppVersionPatch : BytecodePatch(
- listOf(
- SpoofAppVersionFingerprint
- )
+@Patch(
+ name = "Spoof app version",
+ description = "Tricks YouTube into thinking you are running an older version of the app. " +
+ "One of the side effects also includes restoring the old UI.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object SpoofAppVersionPatch : BytecodePatch(
+ setOf(SpoofAppVersionFingerprint)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/spoof/SpoofAppVersionPatch;"
+
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
@@ -49,17 +61,19 @@ class SpoofAppVersionPatch : BytecodePatch(
ArrayResource(
"revanced_spoof_app_version_target_entries",
listOf(
- StringResource("revanced_spoof_app_version_target_entry_1", "17.08.35 - Restore old UI layout"),
- StringResource("revanced_spoof_app_version_target_entry_2", "16.08.35 - Restore explore tab"),
- StringResource("revanced_spoof_app_version_target_entry_3", "16.01.35 - Restore old Shorts player"),
+ StringResource("revanced_spoof_app_version_target_entry_1", "18.20.39 - Restore wide video speed & quality menu"),
+ StringResource("revanced_spoof_app_version_target_entry_2", "17.08.35 - Restore old UI layout"),
+ StringResource("revanced_spoof_app_version_target_entry_3", "16.08.35 - Restore explore tab"),
+ StringResource("revanced_spoof_app_version_target_entry_4", "16.01.35 - Restore old Shorts player"),
)
),
ArrayResource(
"revanced_spoof_app_version_target_entry_values",
listOf(
- StringResource("revanced_spoof_app_version_target_entry_value_1", "17.08.35"),
- StringResource("revanced_spoof_app_version_target_entry_value_2", "16.08.35"),
- StringResource("revanced_spoof_app_version_target_entry_value_3", "16.01.35"),
+ StringResource("revanced_spoof_app_version_target_entry_value_1", "18.20.39"),
+ StringResource("revanced_spoof_app_version_target_entry_value_2", "17.08.35"),
+ StringResource("revanced_spoof_app_version_target_entry_value_3", "16.08.35"),
+ StringResource("revanced_spoof_app_version_target_entry_value_4", "16.01.35"),
)
)
)
@@ -73,14 +87,10 @@ class SpoofAppVersionPatch : BytecodePatch(
mutableMethod.addInstructions(
insertIndex,
"""
- invoke-static {v$buildOverrideNameRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR;->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String;
+ invoke-static {v$buildOverrideNameRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$buildOverrideNameRegister
"""
)
} ?: throw SpoofAppVersionFingerprint.exception
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SpoofAppVersionPatch"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt
deleted file mode 100644
index 41aa7c70e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.layout.spoofappversion.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class SpoofAppVersionCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/fingerprints/SpoofAppVersionFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/fingerprints/SpoofAppVersionFingerprint.kt
similarity index 90%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/fingerprints/SpoofAppVersionFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/fingerprints/SpoofAppVersionFingerprint.kt
index 901f34d45..c9250e91a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/fingerprints/SpoofAppVersionFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/fingerprints/SpoofAppVersionFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.spoofappversion.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.spoofappversion.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableShortsOnStartupPatch.kt
similarity index 64%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableShortsOnStartupPatch.kt
index b4f11b481..4db654652 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableShortsOnStartupPatch.kt
@@ -1,28 +1,37 @@
-package app.revanced.patches.youtube.layout.startupshortsreset.patch
+package app.revanced.patches.youtube.layout.startupshortsreset
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.startupshortsreset.annotations.StartupShortsResetCompatibility
import app.revanced.patches.youtube.layout.startupshortsreset.fingerprints.UserWasInShortsFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Disable Shorts on startup")
-@Description("Disables playing YouTube Shorts when launching YouTube.")
-@StartupShortsResetCompatibility
-class DisableShortsOnStartupPatch : BytecodePatch(
- listOf(
- UserWasInShortsFingerprint
- )
+@Patch(
+ name = "Disable Shorts on startup",
+ description = "Disables playing YouTube Shorts when launching YouTube.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object DisableShortsOnStartupPatch : BytecodePatch(
+ setOf(UserWasInShortsFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt
deleted file mode 100644
index 845d13663..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.startupshortsreset.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class StartupShortsResetCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/patch/EnableTabletLayoutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/tablet/patch/EnableTabletLayoutPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch.kt
index 95bbc1c47..c99a12b7d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/patch/EnableTabletLayoutPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch.kt
@@ -1,28 +1,29 @@
-package app.revanced.patches.youtube.layout.tablet.patch
+package app.revanced.patches.youtube.layout.tablet
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.tablet.annotations.EnableTabletLayoutCompatibility
import app.revanced.patches.youtube.layout.tablet.fingerprints.GetFormFactorFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Enable tablet layout")
-@Description("Spoofs the device form factor to a tablet which enables the tablet layout.")
-@EnableTabletLayoutCompatibility
-class EnableTabletLayoutPatch : BytecodePatch(listOf(GetFormFactorFingerprint)) {
+@Patch(
+ name = "Enable tablet layout",
+ description = "Spoofs the device form factor to a tablet which enables the tablet layout.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
+)
+@Suppress("unused")
+object EnableTabletLayoutPatch : BytecodePatch(
+ setOf(GetFormFactorFingerprint)
+) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/annotations/EnableTabletLayoutCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/annotations/EnableTabletLayoutCompatibility.kt
deleted file mode 100644
index 430281f60..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/annotations/EnableTabletLayoutCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.tablet.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class EnableTabletLayoutCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt
index 9e4cfe8dd..774ccd352 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt
@@ -1,36 +1,47 @@
-package app.revanced.patches.youtube.layout.tabletminiplayer.patch
+package app.revanced.patches.youtube.layout.tabletminiplayer
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerDimensionsCalculatorParentFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Tablet mini player")
-@Description("Enables the tablet mini player layout.")
-@TabletMiniPlayerCompatibility
-class TabletMiniPlayerPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Tablet mini player",
+ description = "Enables the tablet mini player layout.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", arrayOf(
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ )
+ )
+ ]
+)
+@Suppress("unused")
+object TabletMiniPlayerPatch : BytecodePatch(
+ setOf(
MiniPlayerDimensionsCalculatorParentFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint,
MiniPlayerOverrideFingerprint
@@ -47,7 +58,8 @@ class TabletMiniPlayerPatch : BytecodePatch(
)
// First resolve the fingerprints via the parent fingerprint.
- MiniPlayerDimensionsCalculatorParentFingerprint.result ?: throw MiniPlayerDimensionsCalculatorParentFingerprint.exception
+ MiniPlayerDimensionsCalculatorParentFingerprint.result
+ ?: throw MiniPlayerDimensionsCalculatorParentFingerprint.exception
val miniPlayerClass = MiniPlayerDimensionsCalculatorParentFingerprint.result!!.classDef
/*
@@ -98,32 +110,30 @@ class TabletMiniPlayerPatch : BytecodePatch(
}
// Helper methods.
- private companion object {
- fun MethodFingerprint.addProxyCall(): Triple {
- val (method, scanIndex, parameterRegister) = this.unwrap()
- method.insertOverride(scanIndex, parameterRegister)
+ private fun MethodFingerprint.addProxyCall(): Triple {
+ val (method, scanIndex, parameterRegister) = this.unwrap()
+ method.insertOverride(scanIndex, parameterRegister)
- return Triple(method, scanIndex, parameterRegister)
- }
+ return Triple(method, scanIndex, parameterRegister)
+ }
- fun MutableMethod.insertOverride(index: Int, overrideRegister: Int) {
- this.addInstructions(
- index,
- """
+ private fun MutableMethod.insertOverride(index: Int, overrideRegister: Int) {
+ this.addInstructions(
+ index,
+ """
invoke-static {v$overrideRegister}, Lapp/revanced/integrations/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z
move-result v$overrideRegister
"""
- )
- }
+ )
+ }
- fun MethodFingerprint.unwrap(): Triple {
- val result = this.result!!
- val scanIndex = result.scanResult.patternScanResult!!.endIndex
- val method = result.mutableMethod
- val instructions = method.implementation!!.instructions
- val parameterRegister = (instructions[scanIndex] as OneRegisterInstruction).registerA
+ fun MethodFingerprint.unwrap(): Triple {
+ val result = this.result!!
+ val scanIndex = result.scanResult.patternScanResult!!.endIndex
+ val method = result.mutableMethod
+ val instructions = method.implementation!!.instructions
+ val parameterRegister = (instructions[scanIndex] as OneRegisterInstruction).registerA
- return Triple(method, scanIndex, parameterRegister)
- }
+ return Triple(method, scanIndex, parameterRegister)
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt
deleted file mode 100644
index 2bc544b04..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.tabletminiplayer.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class TabletMiniPlayerCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt
new file mode 100644
index 000000000..2d96f8fe8
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt
@@ -0,0 +1,41 @@
+package app.revanced.patches.youtube.layout.theme
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.layout.theme.fingerprints.LithoThemeFingerprint
+
+@Patch(
+ description = "Adds a hook to set color of Litho components.",
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube"),
+ ]
+)
+object LithoColorHookPatch : BytecodePatch(setOf(LithoThemeFingerprint)) {
+ private var insertionIndex : Int = -1
+ private lateinit var colorRegister : String
+ private lateinit var insertionMethod : MutableMethod
+
+ internal fun lithoColorOverrideHook(targetMethodClass: String, targetMethodName: String) {
+ insertionMethod.addInstructions(
+ insertionIndex,
+ """
+ invoke-static {$colorRegister}, $targetMethodClass->$targetMethodName(I)I
+ move-result $colorRegister
+ """
+ )
+ insertionIndex += 2
+ }
+
+ override fun execute(context: BytecodeContext) {
+ LithoThemeFingerprint.result?.let {
+ insertionIndex = it.scanResult.patternScanResult!!.endIndex - 1
+ colorRegister = "p1"
+ insertionMethod = it.mutableMethod
+ } ?: throw LithoThemeFingerprint.exception
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt
new file mode 100644
index 000000000..680a8d93a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt
@@ -0,0 +1,40 @@
+package app.revanced.patches.youtube.layout.theme
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
+import app.revanced.patches.youtube.layout.seekbar.SeekbarColorBytecodePatch
+
+@Patch(
+ name = "Theme",
+ description = "Applies a custom theme.",
+ dependencies = [LithoColorHookPatch::class, SeekbarColorBytecodePatch::class, ThemeResourcePatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube")
+ ]
+)
+@Suppress("unused")
+object ThemeBytecodePatch : BytecodePatch() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
+
+ internal val darkThemeBackgroundColor by stringPatchOption(
+ key = "darkThemeBackgroundColor",
+ default = "@android:color/black",
+ title = "Background color for the dark theme",
+ description = "The background color of the dark theme. Can be a hex color or a resource reference.",
+ )
+
+ internal val lightThemeBackgroundColor by stringPatchOption(
+ key = "lightThemeBackgroundColor",
+ default = "@android:color/white",
+ title = "Background color for the light theme",
+ description = "The background color of the light theme. Can be a hex color or a resource reference.",
+ )
+
+ override fun execute(context: BytecodeContext) {
+ LithoColorHookPatch.lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getValue")
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeResourcePatch.kt
similarity index 84%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeResourcePatch.kt
index cf96bbdf6..6406f4900 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeResourcePatch.kt
@@ -1,22 +1,26 @@
-package app.revanced.patches.youtube.layout.theme.resource
+package app.revanced.patches.youtube.layout.theme
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.shared.settings.preference.impl.TextPreference
-import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
-import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
-import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.layout.seekbar.SeekbarPreferencesPatch
+import app.revanced.patches.youtube.layout.theme.ThemeBytecodePatch.darkThemeBackgroundColor
+import app.revanced.patches.youtube.layout.theme.ThemeBytecodePatch.lightThemeBackgroundColor
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import org.w3c.dom.Element
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class, SeekbarPreferencesPatch::class])
-class ThemeResourcePatch : ResourcePatch {
+@Patch(
+ dependencies = [SettingsPatch::class, ResourceMappingPatch::class, SeekbarPreferencesPatch::class]
+)
+object ThemeResourcePatch : ResourcePatch() {
+ private const val SPLASH_BACKGROUND_COLOR = "revanced_splash_background_color"
+
override fun execute(context: ResourceContext) {
SeekbarPreferencesPatch.addPreferences(
SwitchPreference(
@@ -107,8 +111,4 @@ class ThemeResourcePatch : ResourcePatch {
})
}
}
-
- private companion object {
- private const val SPLASH_BACKGROUND_COLOR = "revanced_splash_background_color"
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt
deleted file mode 100644
index 0ca6ded20..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.theme.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ThemeCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/LithoColorHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/LithoColorHookPatch.kt
deleted file mode 100644
index c253da789..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/LithoColorHookPatch.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package app.revanced.patches.youtube.layout.theme.bytecode.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.LithoThemeFingerprint
-
-@Name("Litho color hook")
-@Description("Adds a hook to set color of Litho components.")
-@ThemeCompatibility
-class LithoColorHookPatch : BytecodePatch(listOf(LithoThemeFingerprint)) {
- override fun execute(context: BytecodeContext) {
- LithoThemeFingerprint.result?.let {
- insertionIndex = it.scanResult.patternScanResult!!.endIndex - 1
- colorRegister = "p1"
- insertionMethod = it.mutableMethod
- } ?: throw LithoThemeFingerprint.exception
- }
- companion object {
- private var insertionIndex : Int = -1
- private lateinit var colorRegister : String
- private lateinit var insertionMethod : MutableMethod
-
- internal fun lithoColorOverrideHook(targetMethodClass: String, targetMethodName: String) {
- insertionMethod.addInstructions(
- insertionIndex,
- """
- invoke-static {$colorRegister}, $targetMethodClass->$targetMethodName(I)I
- move-result $colorRegister
- """
- )
- insertionIndex += 2
- }
- }
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
deleted file mode 100644
index eb2c81c0d..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package app.revanced.patches.youtube.layout.theme.bytecode.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.patch.*
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
-import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
-import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
-
-@Patch
-@Name("Theme")
-@Description("Applies a custom theme.")
-@DependsOn([LithoColorHookPatch::class, SeekbarColorBytecodePatch::class, ThemeResourcePatch::class])
-@ThemeCompatibility
-class ThemeBytecodePatch : BytecodePatch() {
-
- override fun execute(context: BytecodeContext) {
- LithoColorHookPatch.lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getValue")
- }
-
- companion object : OptionsContainer() {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
-
- var darkThemeBackgroundColor: String? by option(
- PatchOption.StringOption(
- key = "darkThemeBackgroundColor",
- default = "@android:color/black",
- title = "Background color for the dark theme",
- description = "The background color of the dark theme. Can be a hex color or a resource reference.",
- )
- )
-
- var lightThemeBackgroundColor: String? by option(
- PatchOption.StringOption(
- key = "lightThemeBackgroundColor",
- default = "@android:color/white",
- title = "Background color for the light theme",
- description = "The background color of the light theme. Can be a hex color or a resource reference.",
- )
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/LithoThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt
similarity index 92%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/LithoThemeFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt
index 9d2d301ca..e76f50e99 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/LithoThemeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.theme.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/patch/AlternativeThumbnailsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt
similarity index 60%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/patch/AlternativeThumbnailsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt
index b84166011..6a97db107 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/patch/AlternativeThumbnailsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt
@@ -1,30 +1,86 @@
-package app.revanced.patches.youtube.layout.thumbnails.patch
+package app.revanced.patches.youtube.layout.thumbnails
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.*
-import app.revanced.patches.youtube.layout.thumbnails.annotations.AlternativeThumbnailsCompatibility
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.*
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Name("Alternative thumbnails")
-@AlternativeThumbnailsCompatibility
-@Description("Adds options to replace video thumbnails with still image captures of the video.")
-class AlternativeThumbnailsPatch : BytecodePatch(
- listOf(MessageDigestImageUrlParentFingerprint, CronetURLRequestCallbackOnResponseStartedFingerprint)
+@Patch(
+ name = "Alternative thumbnails",
+ description = "Adds options to replace video thumbnails with still image captures of the video.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object AlternativeThumbnailsPatch : BytecodePatch(
+ setOf(MessageDigestImageUrlParentFingerprint, CronetURLRequestCallbackOnResponseStartedFingerprint)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/AlternativeThumbnailsPatch;"
+
+ private lateinit var loadImageUrlMethod: MutableMethod
+ private var loadImageUrlIndex = 0
+
+ private lateinit var loadImageSuccessCallbackMethod: MutableMethod
+ private var loadImageSuccessCallbackIndex = 0
+
+ private lateinit var loadImageErrorCallbackMethod: MutableMethod
+ private var loadImageErrorCallbackIndex = 0
+
+ /**
+ * @param highPriority If the hook should be called before all other hooks.
+ */
+ private fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean) {
+ loadImageUrlMethod.addInstructions(
+ if (highPriority) 0 else loadImageUrlIndex, """
+ invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object p1
+ """
+ )
+ loadImageUrlIndex += 2
+ }
+
+ /**
+ * If a connection completed, which includes normal 200 responses but also includes
+ * status 404 and other error like http responses.
+ */
+ private fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
+ loadImageSuccessCallbackMethod.addInstruction(
+ loadImageSuccessCallbackIndex++,
+ "invoke-static { p2 }, $targetMethodClass->handleCronetSuccess(Lorg/chromium/net/UrlResponseInfo;)V"
+ )
+ }
+
+ /**
+ * If a connection outright failed to complete any connection.
+ */
+ fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
+ loadImageErrorCallbackMethod.addInstruction(
+ loadImageErrorCallbackIndex++,
+ "invoke-static { p2, p3 }, $targetMethodClass->handleCronetFailure(Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V"
+ )
+ }
+
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -60,12 +116,18 @@ class AlternativeThumbnailsPatch : BytecodePatch(
SwitchPreference(
"revanced_alt_thumbnail_fast_quality",
StringResource("revanced_alt_thumbnail_fast_quality_title", "Use fast alternative thumbnails"),
- StringResource("revanced_alt_thumbnail_fast_quality_summary_on", "Using medium quality stills. Thumbnails will load faster, but live streams, unreleased, or very old videos may show blank thumbnails"),
+ StringResource(
+ "revanced_alt_thumbnail_fast_quality_summary_on",
+ "Using medium quality stills. Thumbnails will load faster, but live streams, unreleased, or very old videos may show blank thumbnails"
+ ),
StringResource("revanced_alt_thumbnail_fast_quality_summary_off", "Using high quality stills")
),
NonInteractivePreference(
StringResource("revanced_alt_thumbnail_about_title", "About"),
- StringResource("revanced_alt_thumbnail_about_summary", "Alternative thumbnails are still images from the beginning/middle/end of each video. No external API is used, as these images are built into YouTube")
+ StringResource(
+ "revanced_alt_thumbnail_about_summary",
+ "Alternative thumbnails are still images from the beginning/middle/end of each video. No external API is used, as these images are built into YouTube"
+ )
)
),
StringResource("revanced_alt_thumbnails_preference_screen_summary", "Video thumbnail settings")
@@ -101,53 +163,4 @@ class AlternativeThumbnailsPatch : BytecodePatch(
loadImageErrorCallbackMethod = mutableMethod
} ?: throw CronetURLRequestCallbackOnFailureFingerprint.exception
}
-
- internal companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/AlternativeThumbnailsPatch;"
-
- private lateinit var loadImageUrlMethod: MutableMethod
- private var loadImageUrlIndex = 0
-
- private lateinit var loadImageSuccessCallbackMethod: MutableMethod
- private var loadImageSuccessCallbackIndex = 0
-
- private lateinit var loadImageErrorCallbackMethod: MutableMethod
- private var loadImageErrorCallbackIndex = 0
-
- /**
- * @param highPriority If the hook should be called before all other hooks.
- */
- fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean) {
- loadImageUrlMethod.addInstructions(
- if (highPriority) 0 else loadImageUrlIndex, """
- invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
- move-result-object p1
- """
- )
- loadImageUrlIndex += 2
- }
-
- /**
- * If a connection completed, which includes normal 200 responses but also includes
- * status 404 and other error like http responses.
- */
- fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
- loadImageSuccessCallbackMethod.addInstruction(
- loadImageSuccessCallbackIndex++,
- "invoke-static { p2 }, $targetMethodClass->handleCronetSuccess(Lorg/chromium/net/UrlResponseInfo;)V"
- )
- }
-
- /**
- * If a connection outright failed to complete any connection.
- */
- fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
- loadImageErrorCallbackMethod.addInstruction(
- loadImageErrorCallbackIndex++,
- "invoke-static { p2, p3 }, $targetMethodClass->handleCronetFailure(Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V"
- )
- }
-
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/annotations/AlternativeThumbnailsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/annotations/AlternativeThumbnailsCompatibility.kt
deleted file mode 100644
index aa26a419b..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/annotations/AlternativeThumbnailsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.thumbnails.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AlternativeThumbnailsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt
similarity index 77%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt
index dfdacc246..1238fdb2e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt
@@ -1,32 +1,43 @@
-package app.revanced.patches.youtube.misc.autorepeat.patch
+package app.revanced.patches.youtube.misc.autorepeat
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@DependsOn([IntegrationsPatch::class])
-@Name("Always autorepeat")
-@Description("Always repeats the playing video again.")
-@AutoRepeatCompatibility
-class AutoRepeatPatch : BytecodePatch(
- listOf(
- AutoRepeatParentFingerprint
- )
+
+@Patch(
+ name = "Always autorepeat",
+ description = "Always repeats the playing video again.",
+ dependencies = [IntegrationsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object AutoRepeatPatch : BytecodePatch(
+ setOf(AutoRepeatParentFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt
deleted file mode 100644
index 812c6a414..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.autorepeat.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class AutoRepeatCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/BottomSheetHookPatch.kt
similarity index 100%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/BottomSheetHookPatch.kt
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/BottomSheetHookResourcePatch.kt
similarity index 100%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderParentFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/BottomSheetHookResourcePatch.kt
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt
index c60cbdc6d..e69de29bb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt
@@ -1,13 +0,0 @@
-package app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookResourcePatch
-import app.revanced.util.patch.LiteralValueFingerprint
-import com.android.tools.smali.dexlib2.AccessFlags
-
-object CreateBottomSheetFingerprint : LiteralValueFingerprint(
- accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
- parameters = listOf("L"),
- returnType = "Landroid/widget/LinearLayout;",
- literal = BottomSheetHookResourcePatch.bottomSheetMargins
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt
deleted file mode 100644
index 2084360ae..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package app.revanced.patches.youtube.misc.bottomsheet.hook.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints.CreateBottomSheetFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-
-@DependsOn([IntegrationsPatch::class, BottomSheetHookResourcePatch::class])
-class BottomSheetHookPatch : BytecodePatch(
- listOf(CreateBottomSheetFingerprint)
-) {
- override fun execute(context: BytecodeContext) {
- CreateBottomSheetFingerprint.result?.let {
- it.mutableMethod.apply {
- val returnLinearLayoutIndex = implementation!!.instructions.lastIndex
- val linearLayoutRegister = getInstruction(returnLinearLayoutIndex).registerA
-
- addHook = { classDescriptor ->
- addInstruction(
- returnLinearLayoutIndex,
- "invoke-static { v$linearLayoutRegister }, " +
- "${classDescriptor}->" +
- "onFlyoutMenuCreate(Landroid/widget/LinearLayout;)V"
- )
- }
- }
- } ?: throw CreateBottomSheetFingerprint.exception
- }
-
- internal companion object {
- internal lateinit var addHook: (String) -> Unit
- private set
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt
deleted file mode 100644
index 14b434d6a..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package app.revanced.patches.youtube.misc.bottomsheet.hook.patch
-
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-
-@DependsOn([ResourceMappingPatch::class])
-class BottomSheetHookResourcePatch : ResourcePatch {
- override fun execute(context: ResourceContext) {
- bottomSheetMargins = ResourceMappingPatch.resourceMappings.find { it.name == "bottom_sheet_margins" }?.id
- ?: throw PatchException("Could not find resource")
- }
-
- internal companion object {
- var bottomSheetMargins = -1L
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/DebuggingPatch.kt
similarity index 81%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/debugging/DebuggingPatch.kt
index 1a1e45dd8..8898b76eb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/DebuggingPatch.kt
@@ -1,23 +1,22 @@
-package app.revanced.patches.youtube.misc.debugging.patch
+package app.revanced.patches.youtube.misc.debugging
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.debugging.annotations.DebuggingCompatibility
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
-@Patch
-@Name("Enable debugging")
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-@Description("Adds debugging options.")
-@DebuggingCompatibility
-class DebuggingPatch : ResourcePatch {
+@Patch(
+ name = "Enable debugging",
+ description = "Adds debugging options.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
+)
+@Suppress("unused")
+object DebuggingPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
app.revanced.patches.shared.settings.preference.impl.PreferenceScreen(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt
deleted file mode 100644
index c905ea588..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.debugging.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class DebuggingCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/patch/FixBackToExitGesturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/patch/FixBackToExitGesturePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt
index 19265655b..281b56bbf 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/patch/FixBackToExitGesturePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt
@@ -1,25 +1,24 @@
-package app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch
+package app.revanced.patches.youtube.misc.fix.backtoexitgesture
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation.FixBackToExitGestureCompatibility
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.OnBackPressedFingerprint
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewScrollingFingerprint
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewTopScrollingFingerprint
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewTopScrollingParentFingerprint
-@Description("Fixes the swipe back to exit gesture.")
-@FixBackToExitGestureCompatibility
-class FixBackToExitGesturePatch : BytecodePatch(
- listOf(
+@Patch(description = "Fixes the swipe back to exit gesture.")
+@Suppress("unused")
+object FixBackToExitGesturePatch : BytecodePatch(
+ setOf(
RecyclerViewTopScrollingParentFingerprint,
RecyclerViewScrollingFingerprint,
- OnBackPressedFingerprint,
+ OnBackPressedFingerprint
)
) {
override fun execute(context: BytecodeContext) {
@@ -44,30 +43,28 @@ class FixBackToExitGesturePatch : BytecodePatch(
).forEach { (fingerprint, target) -> fingerprint.injectCall(target) }
}
- private companion object {
- /**
- * A reference to a method from the integrations for [FixBackToExitGesturePatch].
- *
- * @param register The method registers.
- * @param methodName The method name.
- * @param parameterTypes The parameters of the method.
- */
- data class IntegrationsMethod(
- val register: String = "", val methodName: String, val parameterTypes: String = ""
- ) {
- override fun toString() =
- "invoke-static {$register}, Lapp/revanced/integrations/patches/FixBackToExitGesturePatch;->$methodName($parameterTypes)V"
- }
+ /**
+ * Inject a call to a method from the integrations.
+ *
+ * @param targetMethod The target method to call.
+ */
+ fun MethodFingerprint.injectCall(targetMethod: IntegrationsMethod) = result?.apply {
+ mutableMethod.addInstruction(
+ scanResult.patternScanResult!!.endIndex, targetMethod.toString()
+ )
+ } ?: throw this.exception
- /**
- * Inject a call to a method from the integrations.
- *
- * @param targetMethod The target method to call.
- */
- fun MethodFingerprint.injectCall(targetMethod: IntegrationsMethod) = result?.apply {
- mutableMethod.addInstruction(
- scanResult.patternScanResult!!.endIndex, targetMethod.toString()
- )
- } ?: throw this.exception
+ /**
+ * A reference to a method from the integrations for [FixBackToExitGesturePatch].
+ *
+ * @param register The method registers.
+ * @param methodName The method name.
+ * @param parameterTypes The parameters of the method.
+ */
+ data class IntegrationsMethod(
+ val register: String = "", val methodName: String, val parameterTypes: String = ""
+ ) {
+ override fun toString() =
+ "invoke-static {$register}, Lapp/revanced/integrations/patches/FixBackToExitGesturePatch;->$methodName($parameterTypes)V"
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt
deleted file mode 100644
index 22073dc1e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class FixBackToExitGestureCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/ClientSpoofPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt
similarity index 55%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/ClientSpoofPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt
index 5d8f76736..2bf64166b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/ClientSpoofPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt
@@ -1,26 +1,40 @@
-package app.revanced.patches.youtube.misc.fix.playback.patch
+package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.misc.fix.playback.annotations.ClientSpoofCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.UserAgentHeaderBuilderFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
-@Patch
-@Name("Client spoof")
-@Description("Spoofs the client to allow playback.")
-@ClientSpoofCompatibility
-@DependsOn([SpoofSignatureVerificationPatch::class])
-class ClientSpoofPatch : BytecodePatch(
- listOf(UserAgentHeaderBuilderFingerprint)
+
+@Patch(
+ name = "Client spoof",
+ description = "Spoofs the client to allow playback.",
+ dependencies = [SpoofSignaturePatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+object ClientSpoofPatch : BytecodePatch(
+ setOf(UserAgentHeaderBuilderFingerprint)
) {
+ private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
+
override fun execute(context: BytecodeContext) {
UserAgentHeaderBuilderFingerprint.result?.let { result ->
val insertIndex = result.scanResult.patternScanResult!!.endIndex
@@ -32,8 +46,4 @@ class ClientSpoofPatch : BytecodePatch(
} ?: throw UserAgentHeaderBuilderFingerprint.exception
}
-
- private companion object {
- private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt
new file mode 100644
index 000000000..1d1b8bb20
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt
@@ -0,0 +1,178 @@
+package app.revanced.patches.youtube.misc.fix.playback
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.smali.ExternalLabel
+import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
+import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
+import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch(
+ description = "Spoofs the signature to prevent playback issues.",
+ dependencies = [
+ SettingsPatch::class,
+ PlayerTypeHookPatch::class,
+ PlayerResponseMethodHookPatch::class,
+ ]
+)
+object SpoofSignaturePatch : BytecodePatch(
+ setOf(
+ PlayerResponseModelImplFingerprint,
+ StoryboardThumbnailParentFingerprint,
+ StoryboardRendererSpecFingerprint,
+ StoryboardRendererInitFingerprint
+ )
+) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/spoof/SpoofSignaturePatch;"
+
+ override fun execute(context: BytecodeContext) {
+ SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ PreferenceScreen(
+ key = "revanced_spoof_signature_verification",
+ title = StringResource(
+ "revanced_spoof_signature_verification_title",
+ "Spoof app signature"
+ ),
+ preferences = listOf(
+ SwitchPreference(
+ "revanced_spoof_signature_verification_enabled",
+ StringResource("revanced_spoof_signature_verification_enabled_title", "Spoof app signature"),
+ StringResource(
+ "revanced_spoof_signature_verification_enabled_summary_on",
+ "App signature spoofed\\n\\n"
+ + "Side effects include:\\n"
+ + "• Enhanced bitrate is not available\\n"
+ + "• Videos cannot be downloaded\\n"
+ + "• No seekbar thumbnails for paid videos"
+ ),
+ StringResource(
+ "revanced_spoof_signature_verification_enabled_summary_off",
+ "App signature not spoofed\\n\\nVideo playback may not work"
+ ),
+ StringResource(
+ "revanced_spoof_signature_verification_enabled_user_dialog_message",
+ "Turning off this setting will cause video playback issues."
+ )
+ ),
+ SwitchPreference(
+ "revanced_spoof_signature_in_feed_enabled",
+ StringResource("revanced_spoof_signature_in_feed_enabled_title", "Spoof app signature in feed"),
+ StringResource(
+ "revanced_spoof_signature_in_feed_enabled_summary_on",
+ "App signature spoofed\\n\\n"
+ + "Side effects include:\\n"
+ + "• Feed videos are missing subtitles\\n"
+ + "• Automatically played feed videos will show up in your watch history"
+ ),
+ StringResource(
+ "revanced_spoof_signature_in_feed_enabled_summary_off",
+ "App signature not spoofed for feed videos\\n\\n"
+ + "Feed videos will play for less than 1 minute before encountering playback issues"
+ )
+ )
+ )
+ )
+ )
+
+ // Hook the player parameters.
+ PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.ProtoBufferParameter(
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;"
+ )
+
+ // Force the seekbar time and chapters to always show up.
+ // This is used only if the storyboard spec fetch fails, or when viewing paid videos.
+ StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef ->
+ StoryboardThumbnailFingerprint.also {
+ it.resolve(
+ context,
+ classDef
+ )
+ }.result?.let {
+ val endIndex = it.scanResult.patternScanResult!!.endIndex
+ // Replace existing instruction to preserve control flow label.
+ // The replaced return instruction always returns false
+ // (it is the 'no thumbnails found' control path),
+ // so there is no need to pass the existing return value to integrations.
+ it.mutableMethod.replaceInstruction(
+ endIndex,
+ """
+ invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarThumbnailOverrideValue()Z
+ """
+ )
+ // Since this is end of the method must replace one line then add the rest.
+ it.mutableMethod.addInstructions(
+ endIndex + 1,
+ """
+ move-result v0
+ return v0
+ """
+ )
+ } ?: throw StoryboardThumbnailFingerprint.exception
+ }
+
+ /**
+ * Hook StoryBoard renderer url
+ */
+ PlayerResponseModelImplFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex
+ val getStoryBoardRegister = getInstruction(getStoryBoardIndex).registerA
+
+ addInstructions(
+ getStoryBoardIndex,
+ """
+ invoke-static { v$getStoryBoardRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v$getStoryBoardRegister
+ """
+ )
+ }
+ } ?: throw PlayerResponseModelImplFingerprint.exception
+
+ StoryboardRendererSpecFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val storyBoardUrlParams = 0
+
+ addInstructionsWithLabels(
+ 0,
+ """
+ if-nez p$storyBoardUrlParams, :ignore
+ invoke-static { p$storyBoardUrlParams }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object p$storyBoardUrlParams
+ """,
+ ExternalLabel("ignore", getInstruction(0))
+ )
+ }
+ } ?: throw StoryboardRendererSpecFingerprint.exception
+
+ // Hook recommended value
+ StoryboardRendererInitFingerprint.result?.let {
+ val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
+
+ val originalValueRegister = it.mutableMethod
+ .getInstruction(moveOriginalRecommendedValueIndex).registerA
+
+ it.mutableMethod.apply {
+ addInstructions(
+ moveOriginalRecommendedValueIndex + 1,
+ """
+ invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
+ move-result v$originalValueRegister
+ """
+ )
+ }
+ } ?: throw StoryboardRendererInitFingerprint.exception
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/annotations/ClientSpoofCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/annotations/ClientSpoofCompatibility.kt
deleted file mode 100644
index 476bba5a5..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/annotations/ClientSpoofCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.playback.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ClientSpoofCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/PlayerResponseModelImplFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/PlayerResponseModelImplFingerprint.kt
new file mode 100644
index 000000000..9dd4fa353
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/PlayerResponseModelImplFingerprint.kt
@@ -0,0 +1,23 @@
+package app.revanced.patches.youtube.misc.fix.playback.fingerprints
+
+import app.revanced.extensions.containsConstantInstructionValue
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.Opcode
+
+object PlayerResponseModelImplFingerprint : MethodFingerprint(
+ returnType = "Ljava/lang/String;",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ parameters = emptyList(),
+ opcodes = listOf(
+ Opcode.RETURN_OBJECT,
+ Opcode.CONST_4,
+ Opcode.RETURN_OBJECT
+ ),
+ customFingerprint = handler@{ methodDef, _ ->
+ if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;")) return@handler false
+
+ methodDef.containsConstantInstructionValue(55735497)
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/ScrubbedPreviewLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/ScrubbedPreviewLayoutFingerprint.kt
deleted file mode 100644
index aa3375e38..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/ScrubbedPreviewLayoutFingerprint.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.playback.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationResourcePatch
-import app.revanced.util.patch.LiteralValueFingerprint
-import com.android.tools.smali.dexlib2.AccessFlags
-import com.android.tools.smali.dexlib2.Opcode
-
-object ScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
- accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
- returnType = "V",
- parameters = listOf("Landroid/content/Context;", "Landroid/util/AttributeSet;", "I", "I"),
- opcodes = listOf(
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CHECK_CAST,
- Opcode.IPUT_OBJECT, // preview imageview
- ),
- // This resource is used in ~ 40 different locations, but this method has a distinct list of parameters to match to.
- literal = SpoofSignatureVerificationResourcePatch.scrubbedPreviewThumbnailResourceId
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/ProtobufParameterBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/StoryboardRendererInitFingerprint.kt
similarity index 52%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/ProtobufParameterBuilderFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/StoryboardRendererInitFingerprint.kt
index 46568f1f4..9dca47f81 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/ProtobufParameterBuilderFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/StoryboardRendererInitFingerprint.kt
@@ -3,11 +3,13 @@ package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
-object ProtobufParameterBuilderFingerprint : MethodFingerprint(
+object StoryboardRendererInitFingerprint : MethodFingerprint(
+ strings = listOf("#-1#"),
opcodes = listOf(
- Opcode.INVOKE_VIRTUAL_RANGE,
+ Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
- Opcode.IPUT_OBJECT
- ),
- strings = listOf("Unexpected empty videoId.", "Prefetch request are disabled.")
-)
\ No newline at end of file
+ Opcode.IPUT_OBJECT,
+ Opcode.INVOKE_INTERFACE,
+ Opcode.MOVE_RESULT
+ )
+)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/StoryboardRendererSpecFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/StoryboardRendererSpecFingerprint.kt
new file mode 100644
index 000000000..c6030b910
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/StoryboardRendererSpecFingerprint.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.youtube.misc.fix.playback.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+object StoryboardRendererSpecFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ returnType = "L",
+ parameters = listOf("Ljava/lang/String;", "J"),
+ strings = listOf("\\|"),
+)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt
deleted file mode 100644
index a7b74c007..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.playback.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ProtobufParameterBuilderFingerprint
-import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ScrubbedPreviewLayoutFingerprint
-import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailFingerprint
-import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailParentFingerprint
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
-
-@Name("Spoof signature verification")
-@Description("Spoofs the client to prevent playback issues.")
-@DependsOn([
- SpoofSignatureVerificationResourcePatch::class,
- IntegrationsPatch::class,
- PlayerTypeHookPatch::class
-])
-class SpoofSignatureVerificationPatch : BytecodePatch(
- listOf(
- ProtobufParameterBuilderFingerprint,
- StoryboardThumbnailParentFingerprint,
- ScrubbedPreviewLayoutFingerprint,
- )
-) {
- override fun execute(context: BytecodeContext) {
-
- // hook parameter
- ProtobufParameterBuilderFingerprint.result?.let {
- val setParamMethod = context
- .toMethodWalker(it.method)
- .nextMethod(it.scanResult.patternScanResult!!.startIndex, true).getMethod() as MutableMethod
-
- setParamMethod.apply {
- val protobufParameterRegister = 3
-
- addInstructions(
- 0,
- """
- invoke-static {p$protobufParameterRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideProtobufParameter(Ljava/lang/String;)Ljava/lang/String;
- move-result-object p$protobufParameterRegister
- """
- )
- }
- } ?: throw ProtobufParameterBuilderFingerprint.exception
-
-
- // When signature spoofing is enabled, the seekbar when tapped does not show
- // the video time, chapter names, or the video thumbnail.
- // Changing the value returned of this method forces all of these to show up,
- // except the thumbnails are blank, which is handled with the patch below.
- StoryboardThumbnailParentFingerprint.result ?: throw StoryboardThumbnailParentFingerprint.exception
- StoryboardThumbnailFingerprint.resolve(context, StoryboardThumbnailParentFingerprint.result!!.classDef)
- StoryboardThumbnailFingerprint.result?.apply {
- val endIndex = scanResult.patternScanResult!!.endIndex
- // Replace existing instruction to preserve control flow label.
- // The replaced return instruction always returns false
- // (it is the 'no thumbnails found' control path),
- // so there is no need to pass the existing return value to integrations.
- mutableMethod.replaceInstruction(
- endIndex,
- """
- invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarThumbnailOverrideValue()Z
- """
- )
- // Since this is end of the method must replace one line then add the rest.
- mutableMethod.addInstructions(
- endIndex + 1,
- """
- move-result v0
- return v0
- """
- )
- } ?: throw StoryboardThumbnailFingerprint.exception
-
-
- // Seekbar thumbnail now show up but are always a blank image.
- // Additional changes are needed to force the client to generate the thumbnails (assuming it's possible),
- // but for now hide the empty thumbnail.
- ScrubbedPreviewLayoutFingerprint.result?.apply {
- val endIndex = scanResult.patternScanResult!!.endIndex
- mutableMethod.apply {
- val imageViewFieldName = getInstruction(endIndex).reference
- addInstructions(
- implementation!!.instructions.lastIndex,
- """
- iget-object v0, p0, $imageViewFieldName # copy imageview field to a register
- invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->seekbarImageViewCreated(Landroid/widget/ImageView;)V
- """
- )
- }
- } ?: throw ScrubbedPreviewLayoutFingerprint.exception
- }
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SpoofSignatureVerificationPatch;"
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationResourcePatch.kt
deleted file mode 100644
index 56a9f7bea..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationResourcePatch.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package app.revanced.patches.youtube.misc.fix.playback.patch
-
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class SpoofSignatureVerificationResourcePatch : ResourcePatch {
-
- override fun execute(context: ResourceContext) {
- SettingsPatch.PreferenceScreen.MISC.addPreferences(
- SwitchPreference(
- "revanced_spoof_signature_verification",
- StringResource("revanced_spoof_signature_verification_title", "Spoof app signature"),
- StringResource("revanced_spoof_signature_verification_summary_on",
- "App signature spoofed\\n\\n"
- + "Side effects include:\\n"
- + "• Ambient mode may not work\\n"
- + "• Downloading videos may not work\\n"
- + "• Seekbar thumbnails are always hidden"),
- StringResource("revanced_spoof_signature_verification_summary_off", "App signature not spoofed\\n\\nVideo playback may not work"),
- StringResource("revanced_spoof_signature_verification_user_dialog_message",
- "Turning off this setting will cause video playback issues.")
- )
- )
-
- scrubbedPreviewThumbnailResourceId = ResourceMappingPatch.resourceMappings.single {
- it.type == "id" && it.name == "thumbnail"
- }.id
- }
-
- companion object {
- var scrubbedPreviewThumbnailResourceId: Long = -1
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/IntegrationsPatch.kt
similarity index 53%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/integrations/IntegrationsPatch.kt
index 492264e90..cdabc4d5d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/IntegrationsPatch.kt
@@ -1,15 +1,13 @@
-package app.revanced.patches.youtube.misc.integrations.patch
+package app.revanced.patches.youtube.misc.integrations
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.patch.annotations.RequiresIntegrations
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch
import app.revanced.patches.youtube.misc.integrations.fingerprints.*
-@Name("Integrations")
-@RequiresIntegrations
-class IntegrationsPatch : AbstractIntegrationsPatch(
+@Patch(requiresIntegrations = true)
+object IntegrationsPatch : AbstractIntegrationsPatch(
"Lapp/revanced/integrations/utils/ReVancedUtils;",
- listOf(
+ setOf(
ApplicationInitFingerprint,
StandalonePlayerActivityFingerprint,
RemoteEmbeddedPlayerFingerprint,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt
index e391444cc..173887a0a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt
index 7adb101ca..2c1427327 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt
@@ -1,6 +1,6 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
/**
* Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
index aa75270ee..19c53ed24 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt
index 790bc6c8f..2ca241bd3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt
index 554167946..d69910247 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt
index a7ef3632e..bcc7a1baa 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt
index bb9958204..99fc9acfe 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt
new file mode 100644
index 000000000..b164b1582
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt
@@ -0,0 +1,70 @@
+package app.revanced.patches.youtube.misc.links
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.links.fingerprints.OpenLinksDirectlyPrimaryFingerprint
+import app.revanced.patches.youtube.misc.links.fingerprints.OpenLinksDirectlySecondaryFingerprint
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
+
+@Patch(
+ name = "Bypass URL redirects",
+ description = "Bypass URL redirects and open the original URL directly.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+object BypassURLRedirectsPatch : BytecodePatch(
+ setOf(OpenLinksDirectlyPrimaryFingerprint, OpenLinksDirectlySecondaryFingerprint)
+) {
+ override fun execute(context: BytecodeContext) {
+ SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ SwitchPreference(
+ "revanced_bypass_url_redirects",
+ StringResource("revanced_bypass_url_redirects_title", "Bypass URL redirects"),
+ StringResource("revanced_bypass_url_redirects_summary_on", "URL redirects are bypassed"),
+ StringResource("revanced_bypass_url_redirects_summary_off", "URL redirects are not bypassed"),
+ )
+ )
+
+ arrayOf(
+ OpenLinksDirectlyPrimaryFingerprint,
+ OpenLinksDirectlySecondaryFingerprint
+ ).map {
+ it.result ?: throw it.exception
+ }.forEach { result ->
+ result.mutableMethod.apply {
+ val insertIndex = result.scanResult.patternScanResult!!.startIndex
+ val uriStringRegister = getInstruction(insertIndex).registerC
+
+ replaceInstruction(
+ insertIndex,
+ "invoke-static {v$uriStringRegister}," +
+ "Lapp/revanced/integrations/patches/BypassURLRedirectsPatch;" +
+ "->" +
+ "parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;"
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/patch/OpenLinksExternallyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt
similarity index 74%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/links/patch/OpenLinksExternallyPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt
index 347b5ba41..fecf51010 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/patch/OpenLinksExternallyPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt
@@ -1,15 +1,13 @@
-package app.revanced.patches.youtube.misc.links.patch
+package app.revanced.patches.youtube.misc.links
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.links.annotations.OpenLinksExternallyCompatibility
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.patch.AbstractTransformInstructionsPatch
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
@@ -18,11 +16,26 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
-@Patch
-@Name("Open links externally")
-@Description("Open links outside of the app directly in your browser.")
-@OpenLinksExternallyCompatibility
-class OpenLinksExternallyPatch : AbstractTransformInstructionsPatch>(
+@Patch(
+ name = "Open links externally",
+ description = "Open links outside of the app directly in your browser.",
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object OpenLinksExternallyPatch : AbstractTransformInstructionsPatch>(
) {
override fun filterMap(
classDef: ClassDef, method: Method, instruction: Instruction, instructionIndex: Int
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/annotations/OpenLinksExternallyCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/annotations/OpenLinksExternallyCompatibility.kt
deleted file mode 100644
index 1dd405c09..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/annotations/OpenLinksExternallyCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.links.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class OpenLinksExternallyCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/fingerprints/IsUserSuperMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/fingerprints/OpenLinksDirectlyPrimaryFingerprint.kt
similarity index 52%
rename from src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/fingerprints/IsUserSuperMethodFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/links/fingerprints/OpenLinksDirectlyPrimaryFingerprint.kt
index 8ee88fdce..3cdfe2f41 100644
--- a/src/main/kotlin/app/revanced/patches/duolingo/unlocksuper/fingerprints/IsUserSuperMethodFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/fingerprints/OpenLinksDirectlyPrimaryFingerprint.kt
@@ -1,14 +1,20 @@
-package app.revanced.patches.duolingo.unlocksuper.fingerprints
+package app.revanced.patches.youtube.misc.links.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
-object IsUserSuperMethodFingerprint : MethodFingerprint(
+object OpenLinksDirectlyPrimaryFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Object",
- parameters = listOf("Ljava/lang/Object"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
- strings = listOf("user"),
- opcodes = listOf(Opcode.IGET_BOOLEAN),
+ parameters = listOf("Ljava/lang/Object"),
+ opcodes = listOf(
+ Opcode.INVOKE_STATIC,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.RETURN_OBJECT,
+ Opcode.CHECK_CAST,
+ Opcode.SGET,
+ Opcode.SGET_OBJECT
+ )
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/fingerprints/OpenLinksDirectlySecondaryFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/fingerprints/OpenLinksDirectlySecondaryFingerprint.kt
new file mode 100644
index 000000000..cdb55bc0f
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/fingerprints/OpenLinksDirectlySecondaryFingerprint.kt
@@ -0,0 +1,17 @@
+package app.revanced.patches.youtube.misc.links.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.Opcode
+
+object OpenLinksDirectlySecondaryFingerprint : MethodFingerprint(
+ returnType = "Landroid/net/Uri",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ parameters = listOf("Ljava/lang/String"),
+ opcodes = listOf(
+ Opcode.INVOKE_STATIC,
+ Opcode.MOVE_RESULT_OBJECT
+ ),
+ strings = listOf("://")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt
index 99b2474e2..07ec2eaa7 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt
@@ -1,7 +1,6 @@
-package app.revanced.patches.youtube.misc.litho.filter.patch
+package app.revanced.patches.youtube.misc.litho.filter
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -12,9 +11,9 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@@ -22,11 +21,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import java.io.Closeable
-@DependsOn([IntegrationsPatch::class])
-@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.")
-class LithoFilterPatch : BytecodePatch(
- listOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint)
+@Patch(
+ description = "Hooks the method which parses the bytes into a ComponentContext to filter components.",
+ dependencies = [IntegrationsPatch::class]
+)
+@Suppress("unused")
+object LithoFilterPatch : BytecodePatch(
+ setOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint)
), Closeable {
+ private val MethodFingerprint.patternScanResult
+ get() = result!!.scanResult.patternScanResult!!
+
+ private val MethodFingerprint.patternScanEndIndex
+ get() = patternScanResult.endIndex
+
+ private val Instruction.descriptor
+ get() = (this as ReferenceInstruction).reference.toString()
+
+ const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/LithoFilterPatch;"
+
+ internal lateinit var addFilter: (String) -> Unit
+ private set
+
+ private var filterCount = 0
+
/**
* The following patch inserts a hook into the method that parses the bytes into a ComponentContext.
* This method contains a StringBuilder object that represents the pathBuilder of the component.
@@ -85,7 +103,7 @@ class LithoFilterPatch : BytecodePatch(
val emptyComponentFieldIndex = builderMethodIndex + 2
bytesToComponentContextMethod.mutableMethod.apply {
- val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex
+ val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex + 1
// region Get free registers that this patch uses.
// Registers are overwritten right after they are used in this patch, therefore free to clobber.
@@ -162,22 +180,4 @@ class LithoFilterPatch : BytecodePatch(
override fun close() = LithoFilterFingerprint.result!!
.mutableMethod.replaceInstruction(0, "const/16 v0, $filterCount")
-
- companion object {
- private val MethodFingerprint.patternScanResult
- get() = result!!.scanResult.patternScanResult!!
-
- private val MethodFingerprint.patternScanEndIndex
- get() = patternScanResult.endIndex
-
- private val Instruction.descriptor
- get() = (this as ReferenceInstruction).reference.toString()
-
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/LithoFilterPatch;"
-
- internal lateinit var addFilter: (String) -> Unit
- private set
-
- private var filterCount = 0
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt
index 5fa5401dc..62916db69 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt
@@ -5,9 +5,9 @@ import com.android.tools.smali.dexlib2.Opcode
object ComponentContextParserFingerprint : MethodFingerprint(
opcodes = listOf(
+ Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_OBJECT,
- Opcode.NEW_INSTANCE
),
strings = listOf("Component was not found %s because it was removed due to duplicate converter bindings.")
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt
similarity index 66%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt
index 59296187a..01af68664 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt
@@ -1,34 +1,42 @@
-package app.revanced.patches.youtube.misc.microg.patch.bytecode
+package app.revanced.patches.youtube.misc.microg
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.fingerprints.WatchWhileActivityFingerprint
-import app.revanced.patches.youtube.layout.buttons.cast.patch.HideCastButtonPatch
-import app.revanced.patches.youtube.misc.fix.playback.patch.ClientSpoofPatch
-import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
+import app.revanced.patches.youtube.layout.buttons.cast.HideCastButtonPatch
+import app.revanced.patches.youtube.misc.fix.playback.ClientSpoofPatch
import app.revanced.patches.youtube.misc.microg.fingerprints.*
-import app.revanced.patches.youtube.misc.microg.patch.resource.MicroGResourcePatch
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
import app.revanced.util.microg.MicroGBytecodeHelper
-@Patch
-@DependsOn(
- [
+@Patch(
+ name = "Vanced MicroG support",
+ description = "Allows YouTube to run without root and under a different package name with Vanced MicroG.",
+ dependencies = [
MicroGResourcePatch::class,
HideCastButtonPatch::class,
ClientSpoofPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
]
)
-@Name("Vanced MicroG support")
-@Description("Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.")
-@MicroGPatchCompatibility
-class MicroGBytecodePatch : BytecodePatch(
- listOf(
+@Suppress("unused")
+object MicroGBytecodePatch : BytecodePatch(
+ setOf(
ServiceCheckFingerprint,
GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt
similarity index 82%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt
index 0c07e4ab7..43f057572 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt
@@ -1,8 +1,8 @@
-package app.revanced.patches.youtube.misc.microg.patch.resource
+package app.revanced.patches.youtube.misc.microg
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
@@ -10,14 +10,13 @@ import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NA
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.microg.Constants.MICROG_VENDOR
import app.revanced.util.microg.MicroGManifestHelper
import app.revanced.util.microg.MicroGResourceHelper
-@DependsOn([SettingsResourcePatch::class])
-class MicroGResourcePatch : ResourcePatch {
+@Patch(dependencies = [SettingsPatch::class])
+object MicroGResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.addPreference(
Preference(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt
deleted file mode 100644
index 479c201ca..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.microg.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class MicroGPatchCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt
index 7c3cd333f..eb94ba06c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt
@@ -1,47 +1,64 @@
-package app.revanced.patches.youtube.misc.minimizedplayback.patch
+package app.revanced.patches.youtube.misc.minimizedplayback
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.NonInteractivePreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackSettingsParentFingerprint
-import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-@Patch
-@Name("Minimized playback")
-@Description("Enables minimized and background playback.")
-@DependsOn([IntegrationsPatch::class, PlayerTypeHookPatch::class, SettingsPatch::class])
-@MinimizedPlaybackCompatibility
-class MinimizedPlaybackPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Minimized playback",
+ description = "Enables minimized and background playback.",
+ dependencies = [IntegrationsPatch::class, PlayerTypeHookPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object MinimizedPlaybackPatch : BytecodePatch(
+ setOf(
MinimizedPlaybackManagerFingerprint,
MinimizedPlaybackSettingsParentFingerprint,
KidsMinimizedPlaybackPolicyControllerFingerprint
)
) {
+ const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;"
+
override fun execute(context: BytecodeContext) {
// TODO: remove this empty preference sometime after mid 2023
SettingsPatch.PreferenceScreen.MISC.addPreferences(
NonInteractivePreference(
StringResource("revanced_minimized_playback_enabled_title", "Minimized playback"),
- StringResource("revanced_minimized_playback_summary_on", "This setting can be found in Settings -> Background")
+ StringResource(
+ "revanced_minimized_playback_summary_on",
+ "This setting can be found in Settings -> Background"
+ )
)
)
@@ -58,7 +75,10 @@ class MinimizedPlaybackPatch : BytecodePatch(
// Enable minimized playback option in YouTube settings
MinimizedPlaybackSettingsParentFingerprint.result ?: throw MinimizedPlaybackSettingsParentFingerprint.exception
- MinimizedPlaybackSettingsFingerprint.resolve(context, MinimizedPlaybackSettingsParentFingerprint.result!!.classDef)
+ MinimizedPlaybackSettingsFingerprint.resolve(
+ context,
+ MinimizedPlaybackSettingsParentFingerprint.result!!.classDef
+ )
MinimizedPlaybackSettingsFingerprint.result?.apply {
val booleanCalls = method.implementation!!.instructions.withIndex()
.filter { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z" }
@@ -86,8 +106,4 @@ class MinimizedPlaybackPatch : BytecodePatch(
)
} ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
deleted file mode 100644
index 31f431b0a..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.minimizedplayback.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class MinimizedPlaybackCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch.kt
new file mode 100644
index 000000000..c602faa48
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch.kt
@@ -0,0 +1,75 @@
+package app.revanced.patches.youtube.misc.playercontrols
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.DomFileEditor
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
+import java.io.Closeable
+
+@Patch(dependencies = [ResourceMappingPatch::class])
+object BottomControlsResourcePatch : ResourcePatch(), Closeable {
+ internal var bottomUiContainerResourceId: Long = -1
+
+ internal const val TARGET_RESOURCE_NAME = "youtube_controls_bottom_ui_container.xml"
+ private const val TARGET_RESOURCE = "res/layout/$TARGET_RESOURCE_NAME"
+
+ private lateinit var resourceContext: ResourceContext
+ private lateinit var targetXmlEditor: DomFileEditor
+
+ // The element to which to add the new elements to
+ private var lastLeftOf = "fullscreen_button"
+
+ override fun execute(context: ResourceContext) {
+ resourceContext = context
+ targetXmlEditor = context.xmlEditor[TARGET_RESOURCE]
+
+ bottomUiContainerResourceId = ResourceMappingPatch.resourceMappings
+ .single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id
+ }
+
+ /**
+ * Add new controls to the bottom of the YouTube player.
+ * @param hostYouTubeControlsBottomUiResourceName The hosting resource name containing the elements.
+ */
+ internal fun addControls(hostYouTubeControlsBottomUiResourceName: String) {
+ val sourceXmlEditor =
+ resourceContext.xmlEditor[this::class.java.classLoader.getResourceAsStream(
+ hostYouTubeControlsBottomUiResourceName
+ )!!]
+
+ val targetElement =
+ "android.support.constraint.ConstraintLayout"
+
+ val hostElements = sourceXmlEditor.file.getElementsByTagName(targetElement).item(0).childNodes
+
+ val destinationResourceFile = targetXmlEditor.file
+ val destinationElement =
+ destinationResourceFile.getElementsByTagName(targetElement).item(0)
+
+ for (index in 1 until hostElements.length) {
+ val element = hostElements.item(index).cloneNode(true)
+
+ // if the element has no attributes theres no point to adding it to the destination
+ if (!element.hasAttributes()) continue
+
+ // set the elements lastLeftOf attribute to the lastLeftOf value
+ val namespace = "@+id"
+ element.attributes.getNamedItem("yt:layout_constraintRight_toLeftOf").nodeValue =
+ "$namespace/$lastLeftOf"
+
+ // set lastLeftOf attribute to the current element
+ val nameSpaceLength = 5
+ lastLeftOf = element.attributes.getNamedItem("android:id").nodeValue.substring(nameSpaceLength)
+
+ // copy the element
+ destinationResourceFile.adoptNode(element)
+ destinationElement.appendChild(element)
+ }
+ sourceXmlEditor.close()
+ }
+
+ override fun close() {
+ targetXmlEditor.close()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsBytecodePatch.kt
new file mode 100644
index 000000000..f3962f82e
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsBytecodePatch.kt
@@ -0,0 +1,66 @@
+package app.revanced.patches.youtube.misc.playercontrols
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
+import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint
+import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
+import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch(
+ description = "Manages the code for the player controls of the YouTube player.",
+ dependencies = [BottomControlsResourcePatch::class],
+)
+object PlayerControlsBytecodePatch : BytecodePatch(
+ setOf(LayoutConstructorFingerprint, BottomControlsInflateFingerprint)
+) {
+ lateinit var showPlayerControlsFingerprintResult: MethodFingerprintResult
+
+ private var moveToRegisterInstructionIndex: Int = 0
+ private var viewRegister: Int = 0
+ private lateinit var inflateFingerprintResult: MethodFingerprintResult
+
+ override fun execute(context: BytecodeContext) {
+ LayoutConstructorFingerprint.result?.let {
+ if (!PlayerControlsVisibilityFingerprint.resolve(context, it.classDef))
+ throw LayoutConstructorFingerprint.exception
+ } ?: throw LayoutConstructorFingerprint.exception
+
+ showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!!
+
+ inflateFingerprintResult = BottomControlsInflateFingerprint.result!!.also {
+ moveToRegisterInstructionIndex = it.scanResult.patternScanResult!!.endIndex
+ viewRegister =
+ (it.mutableMethod.implementation!!.instructions[moveToRegisterInstructionIndex] as OneRegisterInstruction).registerA
+ }
+ }
+
+ /**
+ * Injects the code to change the visibility of controls.
+ * @param descriptor The descriptor of the method which should be called.
+ */
+ fun injectVisibilityCheckCall(descriptor: String) {
+ showPlayerControlsFingerprintResult.mutableMethod.addInstruction(
+ 0,
+ """
+ invoke-static {p1}, $descriptor
+ """
+ )
+ }
+
+ /**
+ * Injects the code to initialize the controls.
+ * @param descriptor The descriptor of the method which should be calleed.
+ */
+ fun initializeControl(descriptor: String) {
+ inflateFingerprintResult!!.mutableMethod.addInstruction(
+ moveToRegisterInstructionIndex + 1,
+ "invoke-static {v$viewRegister}, $descriptor"
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt
deleted file mode 100644
index 6178b01f0..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.playercontrols.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerControlsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt
deleted file mode 100644
index 095a510de..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package app.revanced.patches.youtube.misc.playercontrols.bytecode.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
-import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
-import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint
-import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
-import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-
-@Name("Player controls bytecode patch")
-@DependsOn([BottomControlsResourcePatch::class])
-@Description("Manages the code for the player controls of the YouTube player.")
-@PlayerControlsCompatibility
-class PlayerControlsBytecodePatch : BytecodePatch(
- listOf(
- LayoutConstructorFingerprint,
- BottomControlsInflateFingerprint
- )
-) {
- override fun execute(context: BytecodeContext) {
- LayoutConstructorFingerprint.result?.let {
- if (!PlayerControlsVisibilityFingerprint.resolve(context, it.classDef))
- throw LayoutConstructorFingerprint.exception
- } ?: throw LayoutConstructorFingerprint.exception
-
- showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!!
- inflateFingerprintResult = BottomControlsInflateFingerprint.result!!
- }
-
- internal companion object {
-
- lateinit var showPlayerControlsFingerprintResult: MethodFingerprintResult
-
- private var inflateFingerprintResult: MethodFingerprintResult? = null
- set(fingerprint) {
- field = fingerprint!!.also {
- moveToRegisterInstructionIndex = it.scanResult.patternScanResult!!.endIndex
- viewRegister =
- (it.mutableMethod.implementation!!.instructions[moveToRegisterInstructionIndex] as OneRegisterInstruction).registerA
- }
- }
-
- private var moveToRegisterInstructionIndex: Int = 0
- private var viewRegister: Int = 0
-
- /**
- * Injects the code to change the visibility of controls.
- * @param descriptor The descriptor of the method which should be called.
- */
- fun injectVisibilityCheckCall(descriptor: String) {
- showPlayerControlsFingerprintResult.mutableMethod.addInstruction(
- 0,
- """
- invoke-static {p1}, $descriptor
- """
- )
- }
-
- /**
- * Injects the code to initialize the controls.
- * @param descriptor The descriptor of the method which should be calleed.
- */
- fun initializeControl(descriptor: String) {
- inflateFingerprintResult!!.mutableMethod.addInstruction(
- moveToRegisterInstructionIndex + 1,
- "invoke-static {v$viewRegister}, $descriptor"
- )
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt
index 6f340c2d4..b4e3256c4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt
@@ -1,8 +1,8 @@
package app.revanced.patches.youtube.misc.playercontrols.fingerprints
import app.revanced.patcher.extensions.or
+import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -15,5 +15,5 @@ object BottomControlsInflateFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
- literal = BottomControlsResourcePatch.bottomUiContainerResourceId
+ literalSupplier = { BottomControlsResourcePatch.bottomUiContainerResourceId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt
deleted file mode 100644
index 9d57a1129..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-package app.revanced.patches.youtube.misc.playercontrols.resource.patch
-
-import app.revanced.patcher.util.DomFileEditor
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-import java.io.Closeable
-
-@DependsOn([ResourceMappingPatch::class])
-class BottomControlsResourcePatch : ResourcePatch, Closeable {
- override fun execute(context: ResourceContext) {
- resourceContext = context
- targetXmlEditor = context.xmlEditor[TARGET_RESOURCE]
-
- bottomUiContainerResourceId = ResourceMappingPatch.resourceMappings
- .single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id
- }
-
- companion object {
- internal var bottomUiContainerResourceId : Long = -1
-
- internal const val TARGET_RESOURCE_NAME = "youtube_controls_bottom_ui_container.xml"
- private const val TARGET_RESOURCE = "res/layout/$TARGET_RESOURCE_NAME"
-
- private lateinit var resourceContext: ResourceContext
- private lateinit var targetXmlEditor: DomFileEditor
-
- // The element to which to add the new elements to
- private var lastLeftOf = "fullscreen_button"
-
- /**
- * Add new controls to the bottom of the YouTube player.
- * @param hostYouTubeControlsBottomUiResourceName The hosting resource name containing the elements.
- */
- internal fun addControls(hostYouTubeControlsBottomUiResourceName: String) {
- val sourceXmlEditor =
- resourceContext.xmlEditor[this::class.java.classLoader.getResourceAsStream(
- hostYouTubeControlsBottomUiResourceName
- )!!]
-
- val targetElement =
- "android.support.constraint.ConstraintLayout"
-
- val hostElements = sourceXmlEditor.file.getElementsByTagName(targetElement).item(0).childNodes
-
- val destinationResourceFile = this.targetXmlEditor.file
- val destinationElement =
- destinationResourceFile.getElementsByTagName(targetElement).item(0)
-
- for (index in 1 until hostElements.length) {
- val element = hostElements.item(index).cloneNode(true)
-
- // if the element has no attributes theres no point to adding it to the destination
- if (!element.hasAttributes()) continue
-
- // set the elements lastLeftOf attribute to the lastLeftOf value
- val namespace = "@+id"
- element.attributes.getNamedItem("yt:layout_constraintRight_toLeftOf").nodeValue =
- "$namespace/$lastLeftOf"
-
- // set lastLeftOf attribute to the current element
- val nameSpaceLength = 5
- lastLeftOf = element.attributes.getNamedItem("android:id").nodeValue.substring(nameSpaceLength)
-
- // copy the element
- destinationResourceFile.adoptNode(element)
- destinationElement.appendChild(element)
- }
- sourceXmlEditor.close()
- }
- }
-
- override fun close() {
- targetXmlEditor.close()
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
similarity index 50%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
index 406c694e8..c4e35e13b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
@@ -1,23 +1,30 @@
-package app.revanced.patches.youtube.misc.playeroverlay.patch
+package app.revanced.patches.youtube.misc.playeroverlay
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.playeroverlay.annotation.PlayerOverlaysHookCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint
-@Name("Player overlays hook")
-@Description("Hook for adding custom overlays to the video player.")
-@PlayerOverlaysHookCompatibility
-@DependsOn([IntegrationsPatch::class])
-class PlayerOverlaysHookPatch : BytecodePatch(
- listOf(
- PlayerOverlaysOnFinishInflateFingerprint
- )
+@Patch(
+ description = "Hook for adding custom overlays to the video player.",
+ dependencies = [IntegrationsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage("com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39"
+ ])
+ ]
+)
+@Suppress("unused")
+object PlayerOverlaysHookPatch : BytecodePatch(
+ setOf(PlayerOverlaysOnFinishInflateFingerprint)
) {
override fun execute(context: BytecodeContext) {
// hook YouTubePlayerOverlaysLayout.onFinishInflate()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt
deleted file mode 100644
index b6b4ce0e1..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.playeroverlay.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerOverlaysHookCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt
index c64ddfccd..9c7586c87 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt
@@ -1,25 +1,27 @@
-package app.revanced.patches.youtube.misc.playertype.patch
+package app.revanced.patches.youtube.misc.playertype
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.fingerprint.PlayerTypeFingerprint
import app.revanced.patches.youtube.misc.playertype.fingerprint.VideoStateFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
-@Name("Player type hook")
-@Description("Hook to get the current player type and video playback state.")
-@DependsOn([IntegrationsPatch::class])
-class PlayerTypeHookPatch : BytecodePatch(
- listOf(PlayerTypeFingerprint, VideoStateFingerprint)
+@Patch(
+ description = "Hook to get the current player type and video playback state.",
+ dependencies = [IntegrationsPatch::class]
+)
+object PlayerTypeHookPatch : BytecodePatch(
+ setOf(PlayerTypeFingerprint, VideoStateFingerprint)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/PlayerTypeHookPatch;"
+
override fun execute(context: BytecodeContext) {
PlayerTypeFingerprint.result?.mutableMethod?.addInstruction(
0,
@@ -41,10 +43,4 @@ class PlayerTypeHookPatch : BytecodePatch(
}
} ?: throw VideoStateFingerprint.exception
}
-
- companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/PlayerTypeHookPatch;"
- }
-
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt
deleted file mode 100644
index 70d2f8a08..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.playertype.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerTypeHookCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt
new file mode 100644
index 000000000..9d77d2d85
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt
@@ -0,0 +1,36 @@
+package app.revanced.patches.youtube.misc.recyclerviewtree.hook
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.recyclerviewtree.hook.fingerprints.RecyclerViewTreeObserverFingerprint
+
+@Patch(
+ dependencies = [IntegrationsPatch::class]
+)
+object RecyclerViewTreeHookPatch : BytecodePatch(
+ setOf(RecyclerViewTreeObserverFingerprint)
+) {
+ internal lateinit var addHook: (String) -> Unit
+ private set
+
+ override fun execute(context: BytecodeContext) {
+
+ RecyclerViewTreeObserverFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val insertIndex = it.scanResult.patternScanResult!!.startIndex + 5
+ val recyclerViewParameter = 2
+
+ addHook = { classDescriptor ->
+ addInstruction(
+ insertIndex,
+ "invoke-static/range { p$recyclerViewParameter .. p$recyclerViewParameter }, $classDescriptor->onFlyoutMenuCreate(Landroid/support/v7/widget/RecyclerView;)V"
+ )
+ }
+ }
+ } ?: throw RecyclerViewTreeObserverFingerprint.exception
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt
new file mode 100644
index 000000000..89f871962
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt
@@ -0,0 +1,21 @@
+package app.revanced.patches.youtube.misc.recyclerviewtree.hook.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.Opcode
+
+object RecyclerViewTreeObserverFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ opcodes = listOf(
+ Opcode.NEW_INSTANCE,
+ Opcode.INVOKE_DIRECT,
+ Opcode.IPUT_OBJECT,
+ Opcode.IGET_BOOLEAN,
+ Opcode.IF_NEZ,
+ Opcode.INVOKE_VIRTUAL_RANGE,
+ Opcode.MOVE_RESULT_OBJECT
+ ),
+ strings = listOf("LithoRVSLCBinder")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt
similarity index 60%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt
index 6f3db49fd..03c966861 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt
@@ -1,39 +1,42 @@
-package app.revanced.patches.youtube.misc.settings.bytecode.patch
+package app.revanced.patches.youtube.misc.settings
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
-import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.SetThemeFingerprint
-import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.fingerprints.LicenseActivityFingerprint
+import app.revanced.patches.youtube.misc.settings.fingerprints.SetThemeFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.io.Closeable
-@DependsOn([IntegrationsPatch::class, SettingsResourcePatch::class])
-@Name("Settings")
-@Description("Adds settings for ReVanced to YouTube.")
-class SettingsPatch : BytecodePatch(
- listOf(LicenseActivityFingerprint, SetThemeFingerprint)
+@Patch(
+ description = "Adds settings for ReVanced to YouTube.",
+ dependencies = [IntegrationsPatch::class, SettingsResourcePatch::class]
+)
+object SettingsPatch : BytecodePatch(
+ setOf(LicenseActivityFingerprint, SetThemeFingerprint)
), Closeable {
+ private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations"
+ private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;"
+ private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;"
+ private const val SET_THEME_METHOD_NAME = "setTheme"
+
override fun execute(context: BytecodeContext) {
// TODO: Remove this when it is only required at one place.
fun getSetThemeInstructionString(
- registers: String = "v0",
- classDescriptor: String = THEME_HELPER_DESCRIPTOR,
- methodName: String = SET_THEME_METHOD_NAME,
- parameters: String = "Ljava/lang/Object;"
+ registers: String = "v0",
+ classDescriptor: String = THEME_HELPER_DESCRIPTOR,
+ methodName: String = SET_THEME_METHOD_NAME,
+ parameters: String = "Ljava/lang/Object;"
) = "invoke-static { $registers }, $classDescriptor->$methodName($parameters)V"
SetThemeFingerprint.result?.mutableMethod?.let { setThemeMethod ->
@@ -64,10 +67,10 @@ class SettingsPatch : BytecodePatch(
LicenseActivityFingerprint.result!!.apply licenseActivity@{
mutableMethod.apply {
fun buildSettingsActivityInvokeString(
- registers: String = "p0",
- classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR,
- methodName: String = "initializeSettings",
- parameters: String = "Landroid/app/Activity;"
+ registers: String = "p0",
+ classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR,
+ methodName: String = "initializeSettings",
+ parameters: String = "Landroid/app/Activity;"
) = getSetThemeInstructionString(registers, classDescriptor, methodName, parameters)
// initialize the settings
@@ -88,34 +91,27 @@ class SettingsPatch : BytecodePatch(
}
- internal companion object {
- private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations"
- private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;"
- private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;"
- private const val SET_THEME_METHOD_NAME = "setTheme"
+ fun addString(identifier: String, value: String, formatted: Boolean = true) =
+ SettingsResourcePatch.addString(identifier, value, formatted)
- fun addString(identifier: String, value: String, formatted: Boolean = true) =
- SettingsResourcePatch.addString(identifier, value, formatted)
+ fun addPreferenceScreen(preferenceScreen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) =
+ SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
- fun addPreferenceScreen(preferenceScreen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) =
- SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
+ fun addPreference(preference: Preference) = SettingsResourcePatch.addPreference(preference)
- fun addPreference(preference: Preference) = SettingsResourcePatch.addPreference(preference)
-
- fun renameIntentsTargetPackage(newPackage: String) {
- SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
- }
-
- /**
- * Creates an intent to open ReVanced settings of the given name
- */
- fun createReVancedSettingsIntent(settingsName: String) = Preference.Intent(
- "com.google.android.youtube",
- settingsName,
- "com.google.android.libraries.social.licenses.LicenseActivity"
- )
+ fun renameIntentsTargetPackage(newPackage: String) {
+ SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
}
+ /**
+ * Creates an intent to open ReVanced settings of the given name
+ */
+ fun createReVancedSettingsIntent(settingsName: String) = Preference.Intent(
+ "com.google.android.youtube",
+ settingsName,
+ "com.google.android.libraries.social.licenses.LicenseActivity"
+ )
+
/**
* Preference screens patches should add their settings to.
*/
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsResourcePatch.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsResourcePatch.kt
index e2a447c05..848e3ab3c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsResourcePatch.kt
@@ -1,24 +1,39 @@
-package app.revanced.patches.youtube.misc.settings.resource.patch
+package app.revanced.patches.youtube.misc.settings
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.DomFileEditor
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
+import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch
import app.revanced.patches.shared.settings.preference.addPreference
import app.revanced.patches.shared.settings.preference.impl.*
-import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
import org.w3c.dom.Element
import org.w3c.dom.Node
-@DependsOn([ResourceMappingPatch::class])
-class SettingsResourcePatch : AbstractSettingsResourcePatch(
+@Patch(
+ dependencies = [ResourceMappingPatch::class]
+)
+object SettingsResourcePatch : AbstractSettingsResourcePatch(
"revanced_prefs",
"settings"
) {
+ // Used for a fingerprint from SettingsPatch.
+ internal var appearanceStringId = -1L
+
+ // if this is not null, all intents will be renamed to this
+ internal var overrideIntentsTargetPackage: String? = null
+
+ private var preferencesNode: Node? = null
+
+ private var preferencesEditor: DomFileEditor? = null
+ set(value) {
+ field = value
+ preferencesNode = value.getNode("PreferenceScreen")
+ }
+
override fun execute(context: ResourceContext) {
super.execute(context)
@@ -88,57 +103,6 @@ class SettingsResourcePatch : AbstractSettingsResourcePatch(
context.mergeStrings("settings/host/values/strings.xml")
}
-
- internal companion object {
- // Used for a fingerprint from SettingsPatch.
- internal var appearanceStringId = -1L
-
- // if this is not null, all intents will be renamed to this
- var overrideIntentsTargetPackage: String? = null
-
- private var preferencesNode: Node? = null
-
- private var preferencesEditor: DomFileEditor? = null
- set(value) {
- field = value
- preferencesNode = value.getNode("PreferenceScreen")
- }
-
- /* Companion delegates */
-
- /**
- * Add a preference fragment to the main preferences.
- *
- * @param preference The preference to add.
- */
- fun addPreference(preference: Preference) =
- preferencesNode!!.addPreference(preference) { it.include() }
-
- /**
- * Add a new string to the resources.
- *
- * @param identifier The key of the string.
- * @param value The value of the string.
- * @throws IllegalArgumentException if the string already exists.
- */
- fun addString(identifier: String, value: String, formatted: Boolean) =
- AbstractSettingsResourcePatch.addString(identifier, value, formatted)
-
- /**
- * Add an array to the resources.
- *
- * @param arrayResource The array resource to add.
- */
- fun addArray(arrayResource: ArrayResource) = AbstractSettingsResourcePatch.addArray(arrayResource)
-
- /**
- * Add a preference to the settings.
- *
- * @param preferenceScreen The name of the preference screen.
- */
- fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = addPreference(preferenceScreen)
- }
-
override fun close() {
super.close()
@@ -169,4 +133,36 @@ class SettingsResourcePatch : AbstractSettingsResourcePatch(
preferencesEditor?.close()
}
+
+ /**
+ * Add a preference fragment to the main preferences.
+ *
+ * @param preference The preference to add.
+ */
+ internal fun addPreference(preference: Preference) =
+ preferencesNode!!.addPreference(preference) { it.include() }
+
+ /**
+ * Add a new string to the resources.
+ *
+ * @param identifier The key of the string.
+ * @param value The value of the string.
+ * @throws IllegalArgumentException if the string already exists.
+ */
+ internal fun addString(identifier: String, value: String, formatted: Boolean) =
+ AbstractSettingsResourcePatch.addString(identifier, value, formatted)
+
+ /**
+ * Add an array to the resources.
+ *
+ * @param arrayResource The array resource to add.
+ */
+ internal fun addArray(arrayResource: ArrayResource) = AbstractSettingsResourcePatch.addArray(arrayResource)
+
+ /**
+ * Add a preference to the settings.
+ *
+ * @param preferenceScreen The name of the preference screen.
+ */
+ internal fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = addPreference(preferenceScreen)
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/fingerprints/LicenseActivityFingerprint.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/settings/fingerprints/LicenseActivityFingerprint.kt
index ab6fea8f1..52e3d4a98 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/fingerprints/LicenseActivityFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
+package app.revanced.patches.youtube.misc.settings.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/SetThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/fingerprints/SetThemeFingerprint.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/SetThemeFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/settings/fingerprints/SetThemeFingerprint.kt
index f4e81b847..2a2a6ce9a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/SetThemeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/fingerprints/SetThemeFingerprint.kt
@@ -1,8 +1,8 @@
-package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
+package app.revanced.patches.youtube.misc.settings.fingerprints
import app.revanced.patcher.extensions.or
+import app.revanced.patches.youtube.misc.settings.SettingsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
-import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -11,5 +11,5 @@ object SetThemeFingerprint : LiteralValueFingerprint(
returnType = "L",
parameters = listOf(),
opcodes = listOf(Opcode.RETURN_OBJECT),
- literal = SettingsResourcePatch.appearanceStringId
+ literalSupplier = { SettingsResourcePatch.appearanceStringId }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt
index ad801b437..3c14f81a8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt
@@ -1,27 +1,26 @@
-package app.revanced.patches.youtube.misc.zoomhaptics.patch
+package app.revanced.patches.youtube.misc.zoomhaptics
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.zoomhaptics.annotations.ZoomHapticsCompatibility
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.misc.zoomhaptics.fingerprints.ZoomHapticsFingerprint
-@Patch
-@Name("Disable zoom haptics")
-@Description("Disables haptics when zooming.")
-@DependsOn([SettingsPatch::class])
-@ZoomHapticsCompatibility
-class ZoomHapticsPatch : BytecodePatch(
- listOf(ZoomHapticsFingerprint)
+@Patch(
+ name = "Disable zoom haptics",
+ description = "Disables haptics when zooming.",
+ dependencies = [SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
+)
+@Suppress("unused")
+object ZoomHapticsPatch : BytecodePatch(
+ setOf(ZoomHapticsFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/annotations/ZoomHapticsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/annotations/ZoomHapticsCompatibility.kt
deleted file mode 100644
index 9b6a02306..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/annotations/ZoomHapticsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.zoomhaptics.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class ZoomHapticsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/SeekbarFingerprint.kt
similarity index 75%
rename from src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/SeekbarFingerprint.kt
index 572ec2193..bf465afe5 100644
--- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/SeekbarFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.shared.fingerprints
+package app.revanced.patches.youtube.shared.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/patch/HDRBrightnessPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/patch/HDRBrightnessPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt
index be339f03a..c92a743a8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/patch/HDRBrightnessPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt
@@ -1,29 +1,40 @@
-package app.revanced.patches.youtube.video.hdrbrightness.patch
+package app.revanced.patches.youtube.video.hdrbrightness
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.video.hdrbrightness.annotations.HDRBrightnessCompatibility
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.video.hdrbrightness.fingerprints.HDRBrightnessFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
-@Patch
-@Name("HDR auto brightness")
-@Description("Makes the brightness of HDR videos follow the system default.")
-@HDRBrightnessCompatibility
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
-class HDRBrightnessPatch : BytecodePatch(
- listOf(HDRBrightnessFingerprint)
+@Patch(
+ name = "HDR auto brightness",
+ description = "Makes the brightness of HDR videos follow the system default.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.16.37",
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object HDRBrightnessPatch : BytecodePatch(
+ setOf(HDRBrightnessFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/annotations/HDRBrightnessCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/annotations/HDRBrightnessCompatibility.kt
deleted file mode 100644
index 7d104ee5c..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/annotations/HDRBrightnessCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.video.hdrbrightness.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HDRBrightnessCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/patch/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt
similarity index 59%
rename from src/main/kotlin/app/revanced/patches/youtube/video/information/patch/VideoInformationPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt
index ea744ef5b..2aee32fe0 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/information/patch/VideoInformationPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt
@@ -1,8 +1,6 @@
-package app.revanced.patches.youtube.video.information.patch
+package app.revanced.patches.youtube.video.information
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -10,14 +8,12 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.video.information.annotation.VideoInformationCompatibility
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.video.information.fingerprints.*
-import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackSpeedPatch
-import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.BuilderInstruction
@@ -29,18 +25,35 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
import com.android.tools.smali.dexlib2.util.MethodUtil
-@Name("Video information")
-@Description("Hooks YouTube to get information about the current playing video.")
-@VideoInformationCompatibility
-@DependsOn([IntegrationsPatch::class, VideoIdPatch::class])
-class VideoInformationPatch : BytecodePatch(
- listOf(
+@Patch(
+ description = "Hooks YouTube to get information about the current playing video.",
+ dependencies = [IntegrationsPatch::class, VideoIdPatch::class]
+)
+object VideoInformationPatch : BytecodePatch(
+ setOf(
PlayerInitFingerprint,
CreateVideoPlayerSeekbarFingerprint,
PlayerControllerSetTimeReferenceFingerprint,
- OnPlaybackSpeedItemClickFingerprint,
+ OnPlaybackSpeedItemClickFingerprint
)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/VideoInformation;"
+
+ private lateinit var playerInitMethod: MutableMethod
+ private var playerInitInsertIndex = 4
+
+ private lateinit var timeMethod: MutableMethod
+ private var timeInitInsertIndex = 2
+
+ private lateinit var speedSelectionInsertMethod: MutableMethod
+ private var speedSelectionInsertIndex = 0
+ private var speedSelectionValueRegister = 0
+
+ // Used by other patches.
+ internal lateinit var setPlaybackSpeedContainerClassFieldReference: String
+ internal lateinit var setPlaybackSpeedClassFieldReference: String
+ internal lateinit var setPlaybackSpeedMethodReference: String
+
override fun execute(context: BytecodeContext) {
with(PlayerInitFingerprint.result!!) {
playerInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) }
@@ -96,11 +109,13 @@ class VideoInformationPatch : BytecodePatch(
}
/*
- * Inject call for video id
+ * Inject call for video ids
*/
val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V"
- VideoIdPatch.injectCall(videoIdMethodDescriptor)
- VideoIdPatch.injectCallBackgroundPlay(videoIdMethodDescriptor)
+ VideoIdPatch.hookVideoId(videoIdMethodDescriptor)
+ VideoIdPatch.hookBackgroundPlayVideoId(videoIdMethodDescriptor)
+ VideoIdPatch.hookPlayerResponseVideoId(
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;)V")
/*
* Set the video time method
@@ -138,72 +153,51 @@ class VideoInformationPatch : BytecodePatch(
userSelectedPlaybackSpeedHook(INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed")
}
- companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/VideoInformation;"
+ private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
+ addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
- private lateinit var playerInitMethod: MutableMethod
- private var playerInitInsertIndex = 4
+ private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
+ insert(insertIndex, "p1, p2", descriptor)
- private lateinit var timeMethod: MutableMethod
- private var timeInitInsertIndex = 2
+ /**
+ * Hook the player controller. Called when a video is opened or the current video is changed.
+ *
+ * Note: This hook is called very early and is called before the video id, video time, video length,
+ * and many other data fields are set.
+ *
+ * @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
+ * @param targetMethodName The name of the static method to invoke when the player controller is created.
+ */
+ internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
+ playerInitMethod.insert(
+ playerInitInsertIndex++,
+ "v0",
+ "$targetMethodClass->$targetMethodName(Ljava/lang/Object;)V"
+ )
- private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
- addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
+ /**
+ * Hook the video time.
+ * The hook is usually called once per second.
+ *
+ * @param targetMethodClass The descriptor for the static method to invoke when the player controller is created.
+ * @param targetMethodName The name of the static method to invoke when the player controller is created.
+ */
+ internal fun videoTimeHook(targetMethodClass: String, targetMethodName: String) =
+ timeMethod.insertTimeHook(
+ timeInitInsertIndex++,
+ "$targetMethodClass->$targetMethodName(J)V"
+ )
- private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
- insert(insertIndex, "p1, p2", descriptor)
+ private fun getReference(instructions: List, offset: Int, opcode: Opcode) =
+ (instructions[instructions.indexOfFirst { it.opcode == opcode } + offset] as ReferenceInstruction)
+ .reference.toString()
- /**
- * Hook the player controller. Called when a video is opened or the current video is changed.
- *
- * Note: This hook is called very early and is called before the video id, video time, video length,
- * and many other data fields are set.
- *
- * @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
- * @param targetMethodName The name of the static method to invoke when the player controller is created.
- */
- internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
- playerInitMethod.insert(
- playerInitInsertIndex++,
- "v0",
- "$targetMethodClass->$targetMethodName(Ljava/lang/Object;)V"
- )
-
- /**
- * Hook the video time.
- * The hook is usually called once per second.
- *
- * @param targetMethodClass The descriptor for the static method to invoke when the player controller is created.
- * @param targetMethodName The name of the static method to invoke when the player controller is created.
- */
- internal fun videoTimeHook(targetMethodClass: String, targetMethodName: String) =
- timeMethod.insertTimeHook(
- timeInitInsertIndex++,
- "$targetMethodClass->$targetMethodName(J)V"
- )
-
- private fun getReference(instructions: List, offset: Int, opcode: Opcode) =
- (instructions[instructions.indexOfFirst { it.opcode == opcode } + offset] as ReferenceInstruction)
- .reference.toString()
-
- private lateinit var speedSelectionInsertMethod: MutableMethod
- private var speedSelectionInsertIndex = 0
- private var speedSelectionValueRegister = 0
-
- /**
- * Hook the video speed selected by the user.
- */
- internal fun userSelectedPlaybackSpeedHook(targetMethodClass: String, targetMethodName: String) =
- speedSelectionInsertMethod.addInstruction(
+ /**
+ * Hook the video speed selected by the user.
+ */
+ internal fun userSelectedPlaybackSpeedHook(targetMethodClass: String, targetMethodName: String) =
+ speedSelectionInsertMethod.addInstruction(
speedSelectionInsertIndex++,
"invoke-static {v$speedSelectionValueRegister}, $targetMethodClass->$targetMethodName(F)V"
)
-
- /**
- * Used by [RememberPlaybackSpeedPatch]
- */
- internal lateinit var setPlaybackSpeedContainerClassFieldReference: String
- internal lateinit var setPlaybackSpeedClassFieldReference: String
- internal lateinit var setPlaybackSpeedMethodReference: String
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/annotation/VideoInformationCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/annotation/VideoInformationCompatibility.kt
deleted file mode 100644
index 46cc4a5e0..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/information/annotation/VideoInformationCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.video.information.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class VideoInformationCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt
new file mode 100644
index 000000000..a08531bb1
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt
@@ -0,0 +1,64 @@
+package app.revanced.patches.youtube.video.playerresponse
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint
+import java.io.Closeable
+
+@Patch(
+ dependencies = [IntegrationsPatch::class],
+)
+object PlayerResponseMethodHookPatch :
+ BytecodePatch(setOf(PlayerParameterBuilderFingerprint)),
+ Closeable,
+ MutableSet by mutableSetOf() {
+ private const val VIDEO_ID_PARAMETER = 1
+ private const val PROTO_BUFFER_PARAMETER_PARAMETER = 3
+
+ private lateinit var playerResponseMethod: MutableMethod
+
+ override fun execute(context: BytecodeContext) {
+ playerResponseMethod = PlayerParameterBuilderFingerprint.result?.mutableMethod
+ ?: throw PlayerParameterBuilderFingerprint.exception
+ }
+
+ override fun close() {
+ fun hookVideoId(hook: Hook) = playerResponseMethod.addInstruction(
+ 0, "invoke-static {p$VIDEO_ID_PARAMETER}, $hook"
+ )
+
+ fun hookProtoBufferParameter(hook: Hook) = playerResponseMethod.addInstructions(
+ 0,
+ """
+ invoke-static {p$PROTO_BUFFER_PARAMETER_PARAMETER}, $hook
+ move-result-object p$PROTO_BUFFER_PARAMETER_PARAMETER
+ """
+ )
+
+ // Reverse the order in order to preserve insertion order of the hooks.
+ val beforeVideoIdHooks = filterIsInstance().asReversed()
+ val videoIdHooks = filterIsInstance().asReversed()
+ val afterVideoIdHooks = filterIsInstance().asReversed()
+
+ // Add the hooks in this specific order as they insert instructions at the beginning of the method.
+ afterVideoIdHooks.forEach(::hookProtoBufferParameter)
+ videoIdHooks.forEach(::hookVideoId)
+ beforeVideoIdHooks.forEach(::hookProtoBufferParameter)
+ }
+
+ internal abstract class Hook(private val methodDescriptor: String) {
+ internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor)
+
+ internal class ProtoBufferParameter(methodDescriptor: String) : Hook(methodDescriptor)
+ internal class ProtoBufferParameterBeforeVideoId(methodDescriptor: String) : Hook(methodDescriptor)
+
+ override fun toString() = methodDescriptor
+ }
+}
+
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/fingerprint/PlayerParameterBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/fingerprint/PlayerParameterBuilderFingerprint.kt
new file mode 100644
index 000000000..38f7fb32d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/fingerprint/PlayerParameterBuilderFingerprint.kt
@@ -0,0 +1,25 @@
+package app.revanced.patches.youtube.video.playerresponse.fingerprint
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+object PlayerParameterBuilderFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ returnType = "L",
+ parameters = listOf(
+ "Ljava/lang/String;", // VideoId.
+ "[B",
+ "Ljava/lang/String;", // Player parameters proto buffer.
+ "Ljava/lang/String;",
+ "I",
+ "I",
+ "Ljava/util/Set;",
+ "Ljava/lang/String;",
+ "Ljava/lang/String;",
+ "L",
+ "Z",
+ "Z",
+ "Z"
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt
similarity index 90%
rename from src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt
index a90246bd7..d9008763f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt
@@ -1,8 +1,6 @@
-package app.revanced.patches.youtube.video.quality.patch
+package app.revanced.patches.youtube.video.quality
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -10,16 +8,15 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
-import app.revanced.patches.youtube.video.quality.annotations.RememberVideoQualityCompatibility
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.patches.youtube.video.quality.fingerprints.NewVideoQualityChangedFingerprint
import app.revanced.patches.youtube.video.quality.fingerprints.SetQualityByIndexMethodClassFieldReferenceFingerprint
import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualityItemOnClickParentFingerprint
@@ -28,18 +25,34 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
-@Patch
-@DependsOn([IntegrationsPatch::class, VideoInformationPatch::class, SettingsPatch::class])
-@Name("Remember video quality")
-@Description("Adds the ability to remember the video quality you chose in the video quality flyout.")
-@RememberVideoQualityCompatibility
-class RememberVideoQualityPatch : BytecodePatch(
- listOf(
+@Patch(
+ name = "Remember video quality",
+ description = "Adds the ability to remember the video quality you chose in the video quality flyout.",
+ dependencies = [IntegrationsPatch::class, VideoInformationPatch::class, SettingsPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.19.35",
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object RememberVideoQualityPatch : BytecodePatch(
+ setOf(
VideoQualitySetterFingerprint,
VideoQualityItemOnClickParentFingerprint,
NewVideoQualityChangedFingerprint
)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;"
+
override fun execute(context: BytecodeContext) {
// This is bloated as each value has it's own String key/value
// ideally the entries would be raw values (and not a key to a String resource)
@@ -110,7 +123,6 @@ class RememberVideoQualityPatch : BytecodePatch(
* It also hooks the method which is called when the video quality to set is determined.
* Conveniently, at this point the video quality is overridden to the remembered playback speed.
*/
-
VideoInformationPatch.onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "newVideoStarted")
@@ -188,11 +200,5 @@ class RememberVideoQualityPatch : BytecodePatch(
)
}
} ?: throw NewVideoQualityChangedFingerprint.exception
-
- }
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;"
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/annotations/RememberVideoQualityCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/annotations/RememberVideoQualityCompatibility.kt
deleted file mode 100644
index 96834b575..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/annotations/RememberVideoQualityCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.video.quality.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class RememberVideoQualityCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
index aa76503fa..551f2ae4a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
@@ -11,7 +11,7 @@ object SetQualityByIndexMethodClassFieldReferenceFingerprint : MethodFingerprint
parameters = listOf("L"),
opcodes = listOf(
Opcode.IGET_OBJECT,
- Opcode.INVOKE_INTERFACE,
- Opcode.RETURN_VOID
+ Opcode.IPUT_OBJECT,
+ Opcode.IGET_OBJECT,
)
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeed.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeed.kt
deleted file mode 100644
index 895e43fa8..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeed.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package app.revanced.patches.youtube.video.speed
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.video.speed.custom.patch.CustomPlaybackSpeedPatch
-import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackSpeedPatch
-
-@Patch
-@Name("Playback speed")
-@Description("Adds custom playback speeds and ability to remember the playback speed you chose in the video playback speed flyout.")
-@DependsOn([CustomPlaybackSpeedPatch::class, RememberPlaybackSpeedPatch::class])
-@PlaybackSpeedCompatibility
-class PlaybackSpeed : BytecodePatch() {
- override fun execute(context: BytecodeContext) { // All patches this patch depends on succeed.
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedCompatibility.kt
deleted file mode 100644
index 6a91ac7b8..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.video.speed
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class PlaybackSpeedCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt
new file mode 100644
index 000000000..8b621518b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt
@@ -0,0 +1,32 @@
+package app.revanced.patches.youtube.video.speed
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.video.speed.custom.CustomPlaybackSpeedPatch
+import app.revanced.patches.youtube.video.speed.remember.RememberPlaybackSpeedPatch
+
+@Patch(
+ name = "Playback speed",
+ description = "Adds custom playback speeds and ability " +
+ "to remember the playback speed you chose in the video playback speed flyout.",
+ dependencies = [CustomPlaybackSpeedPatch::class, RememberPlaybackSpeedPatch::class],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube", [
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object PlaybackSpeedPatch : BytecodePatch() {
+ override fun execute(context: BytecodeContext) {
+ // All patches this patch depends on succeed.
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt
index befcebc3b..73fe7e0c4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt
@@ -1,8 +1,6 @@
-package app.revanced.patches.youtube.video.speed.custom.patch
+package app.revanced.patches.youtube.video.speed.custom
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -12,15 +10,15 @@ import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
-import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookPatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.recyclerviewtree.hook.RecyclerViewTreeHookPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.video.speed.custom.fingerprints.*
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
@@ -30,17 +28,23 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField
-@Name("Custom playback speed")
-@Description("Adds custom playback speed options.")
-@DependsOn([IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, BottomSheetHookPatch::class])
-class CustomPlaybackSpeedPatch : BytecodePatch(
- listOf(
+@Patch(
+ description = "Adds custom playback speed options.",
+ dependencies = [IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, RecyclerViewTreeHookPatch::class]
+)
+object CustomPlaybackSpeedPatch : BytecodePatch(
+ setOf(
SpeedArrayGeneratorFingerprint,
SpeedLimiterFingerprint,
GetOldPlaybackSpeedsFingerprint,
ShowOldPlaybackSpeedMenuIntegrationsFingerprint
)
) {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch;"
+
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
@@ -116,20 +120,19 @@ class CustomPlaybackSpeedPatch : BytecodePatch(
val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA
val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA
- // edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x
limiterMethod.replaceInstruction(
limiterMinConstIndex,
- "sget v$limiterMinConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->minPlaybackSpeed:F"
+ "const/high16 v$limiterMinConstDestination, 0x0"
)
limiterMethod.replaceInstruction(
limiterMaxConstIndex,
- "sget v$limiterMaxConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->maxPlaybackSpeed:F"
+ "const/high16 v$limiterMaxConstDestination, 0x41200000 # 10.0f"
)
// region Force old video quality menu.
// This is necessary, because there is no known way of adding custom playback speeds to the new menu.
- BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
+ RecyclerViewTreeHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
// Required to check if the playback speed menu is currently shown.
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
@@ -176,13 +179,4 @@ class CustomPlaybackSpeedPatch : BytecodePatch(
// endregion
}
-
- private companion object {
- private const val FILTER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch;"
-
- private const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch;"
-
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt
similarity index 80%
rename from src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt
index 5b274d461..94dde1eb0 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt
@@ -1,33 +1,33 @@
-package app.revanced.patches.youtube.video.speed.remember.patch
+package app.revanced.patches.youtube.video.speed.remember
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
-import app.revanced.patches.youtube.video.speed.custom.patch.CustomPlaybackSpeedPatch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+import app.revanced.patches.youtube.video.information.VideoInformationPatch
+import app.revanced.patches.youtube.video.speed.custom.CustomPlaybackSpeedPatch
import app.revanced.patches.youtube.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
-@Name("Remember playback speed")
-@Description("Adds the ability to remember the playback speed you chose in the playback speed flyout.")
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomPlaybackSpeedPatch::class])
-class RememberPlaybackSpeedPatch : BytecodePatch(
- listOf(
- InitializePlaybackSpeedValuesFingerprint
- )
-) {
+@Patch(
+ description = "Adds the ability to remember the playback speed you chose in the playback speed flyout.",
+ dependencies = [IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomPlaybackSpeedPatch::class]
+)
+object RememberPlaybackSpeedPatch : BytecodePatch(
+ setOf(InitializePlaybackSpeedValuesFingerprint)
+){
+ const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch;"
+
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
SwitchPreference(
@@ -105,9 +105,4 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
)
} ?: throw InitializePlaybackSpeedValuesFingerprint.exception
}
-
- private companion object {
- const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch;"
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt
new file mode 100644
index 000000000..f72040747
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt
@@ -0,0 +1,128 @@
+package app.revanced.patches.youtube.video.videoid
+
+import app.revanced.extensions.exception
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
+import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
+import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
+import app.revanced.patches.youtube.video.videoid.fingerprint.VideoIdFingerprint
+import app.revanced.patches.youtube.video.videoid.fingerprint.VideoIdFingerprintBackgroundPlay
+import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch(
+ description = "Hooks to detect when the video id changes",
+ dependencies = [IntegrationsPatch::class, PlayerResponseMethodHookPatch::class],
+)
+object VideoIdPatch : BytecodePatch(
+ setOf(
+ VideoIdFingerprint,
+ VideoIdFingerprintBackgroundPlay
+ )
+) {
+ private var videoIdRegister = 0
+ private var videoIdInsertIndex = 0
+ private lateinit var videoIdMethod: MutableMethod
+
+ private var backgroundPlaybackVideoIdRegister = 0
+ private var backgroundPlaybackInsertIndex = 0
+ private lateinit var backgroundPlaybackMethod: MutableMethod
+
+ override fun execute(context: BytecodeContext) {
+
+ /**
+ * Supplies the method and register index of the video id register.
+ *
+ * @param consumer Consumer that receives the method, insert index and video id register index.
+ */
+ fun MethodFingerprint.setFields(consumer: (MutableMethod, Int, Int) -> Unit) = result?.let { result ->
+ val videoIdRegisterIndex = result.scanResult.patternScanResult!!.endIndex
+
+ result.mutableMethod.let {
+ val videoIdRegister = it.getInstruction(videoIdRegisterIndex).registerA
+ val insertIndex = videoIdRegisterIndex + 1
+ consumer(it, insertIndex, videoIdRegister)
+
+ }
+ } ?: throw VideoIdFingerprint.exception
+
+ VideoIdFingerprint.setFields { method, index, register ->
+ videoIdMethod = method
+ videoIdInsertIndex = index
+ videoIdRegister = register
+ }
+
+ VideoIdFingerprintBackgroundPlay.setFields { method, insertIndex, videoIdRegister ->
+ backgroundPlaybackMethod = method
+ backgroundPlaybackInsertIndex = insertIndex
+ backgroundPlaybackVideoIdRegister = videoIdRegister
+ }
+ }
+
+ /**
+ * Hooks the new video id when the video changes.
+ *
+ * Supports all videos (regular videos and Shorts).
+ *
+ * _Does not function if playing in the background with no video visible_.
+ *
+ * Be aware, this can be called multiple times for the same video id.
+ *
+ * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
+ */
+ fun hookVideoId(
+ methodDescriptor: String
+ ) = videoIdMethod.addInstruction(
+ videoIdInsertIndex++,
+ "invoke-static {v$videoIdRegister}, $methodDescriptor"
+ )
+
+ /**
+ * Alternate hook that supports only regular videos, but hook supports changing to new video
+ * during background play when no video is visible.
+ *
+ * _Does not support Shorts_.
+ *
+ * Be aware, the hook can be called multiple times for the same video id.
+ *
+ * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
+ */
+ fun hookBackgroundPlayVideoId(
+ methodDescriptor: String
+ ) = backgroundPlaybackMethod.addInstruction(
+ backgroundPlaybackInsertIndex++, // move-result-object offset
+ "invoke-static {v$backgroundPlaybackVideoIdRegister}, $methodDescriptor"
+ )
+
+ /**
+ * Hooks the video id of every video when loaded.
+ * Supports all videos and functions in all situations.
+ *
+ * Hook is always called off the main thread.
+ *
+ * This hook is called as soon as the player response is parsed,
+ * and called before many other hooks are updated such as [PlayerTypeHookPatch].
+ *
+ * Note: The video id returned here may not be the current video that's being played.
+ * It's common for multiple Shorts to load at once in preparation
+ * for the user swiping to the next Short.
+ *
+ * For most use cases, you probably want to use
+ * [hookVideoId] or [hookBackgroundPlayVideoId] instead.
+ *
+ * Be aware, this can be called multiple times for the same video id.
+ *
+ * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
+ */
+ fun hookPlayerResponseVideoId(methodDescriptor: String) {
+ PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.VideoId(
+ methodDescriptor
+ )
+ }
+}
+
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/annotation/VideoIdCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/annotation/VideoIdCompatibility.kt
deleted file mode 100644
index b26c05ef0..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/annotation/VideoIdCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.video.videoid.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class VideoIdCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/patch/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/patch/VideoIdPatch.kt
deleted file mode 100644
index adf5a6153..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/patch/VideoIdPatch.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-package app.revanced.patches.youtube.video.videoid.patch
-
-import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.video.videoid.annotation.VideoIdCompatibility
-import app.revanced.patches.youtube.video.videoid.fingerprint.VideoIdFingerprint
-import app.revanced.patches.youtube.video.videoid.fingerprint.VideoIdFingerprintBackgroundPlay
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-
-@Name("Video id hook")
-@Description("Hooks to detect when the video id changes")
-@VideoIdCompatibility
-@DependsOn([IntegrationsPatch::class])
-class VideoIdPatch : BytecodePatch(
- listOf(VideoIdFingerprint, VideoIdFingerprintBackgroundPlay)
-) {
- override fun execute(context: BytecodeContext) {
- /**
- * Supplies the method and register index of the video id register.
- *
- * @param consumer Consumer that receives the method, insert index and video id register index.
- */
- fun MethodFingerprint.setFields(consumer: (MutableMethod, Int, Int) -> Unit) = result?.let { result ->
- val videoIdRegisterIndex = result.scanResult.patternScanResult!!.endIndex
-
- result.mutableMethod.let {
- val videoIdRegister = it.getInstruction(videoIdRegisterIndex).registerA
- val insertIndex = videoIdRegisterIndex + 1
- consumer(it, insertIndex, videoIdRegister)
-
- }
- } ?: throw VideoIdFingerprint.exception
-
- VideoIdFingerprint.setFields { method, insertIndex, videoIdRegister ->
- insertMethod = method
- VideoIdPatch.insertIndex = insertIndex
- VideoIdPatch.videoIdRegister = videoIdRegister
- }
-
- VideoIdFingerprintBackgroundPlay.setFields { method, insertIndex, videoIdRegister ->
- backgroundPlaybackMethod = method
- backgroundPlaybackInsertIndex = insertIndex
- backgroundPlaybackVideoIdRegister = videoIdRegister
- }
- }
-
- companion object {
- private var videoIdRegister = 0
- private var insertIndex = 0
- private lateinit var insertMethod: MutableMethod
-
- private var backgroundPlaybackVideoIdRegister = 0
- private var backgroundPlaybackInsertIndex = 0
- private lateinit var backgroundPlaybackMethod: MutableMethod
-
- /**
- * Adds an invoke-static instruction, called with the new id when the video changes.
- *
- * Supports all videos (regular videos, Shorts and Stories).
- *
- * _Does not function if playing in the background with no video visible_.
- *
- * Be aware, this can be called multiple times for the same video id.
- *
- * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
- */
- fun injectCall(
- methodDescriptor: String
- ) = insertMethod.addInstruction(
- // Keep injection calls in the order they're added:
- // Increment index. So if additional injection calls are added, those calls run after this injection call.
- insertIndex++,
- "invoke-static {v$videoIdRegister}, $methodDescriptor"
- )
-
- /**
- * Alternate hook that supports only regular videos, but hook supports changing to new video
- * during background play when no video is visible.
- *
- * _Does not support Shorts or Stories_.
- *
- * Be aware, the hook can be called multiple times for the same video id.
- *
- * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
- */
- fun injectCallBackgroundPlay(
- methodDescriptor: String
- ) = backgroundPlaybackMethod.addInstruction(
- backgroundPlaybackInsertIndex++, // move-result-object offset
- "invoke-static {v$backgroundPlaybackVideoIdRegister}, $methodDescriptor"
- )
- }
-}
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/OldVideoQualityMenuPatch.kt
similarity index 54%
rename from src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/OldVideoQualityMenuPatch.kt
index e10cca26f..602587c24 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/OldVideoQualityMenuPatch.kt
@@ -1,35 +1,52 @@
-package app.revanced.patches.youtube.video.videoqualitymenu.patch
+package app.revanced.patches.youtube.video.videoqualitymenu
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookPatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.video.videoqualitymenu.annotations.OldVideoQualityMenuCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
+import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
+import app.revanced.patches.youtube.misc.recyclerviewtree.hook.RecyclerViewTreeHookPatch
import app.revanced.patches.youtube.video.videoqualitymenu.fingerprints.VideoQualityMenuViewInflateFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-@Patch
-@DependsOn([
- IntegrationsPatch::class,
- OldVideoQualityMenuResourcePatch::class,
- LithoFilterPatch::class,
- BottomSheetHookPatch::class
-])
-@Name("Old video quality menu")
-@Description("Shows the old video quality with the advanced video quality options instead of the new one.")
-@OldVideoQualityMenuCompatibility
-class OldVideoQualityMenuPatch : BytecodePatch(
- listOf(VideoQualityMenuViewInflateFingerprint)
+@Patch(
+ name = "Old video quality menu",
+ description = "Shows the old video quality with the advanced video quality options instead of the new one.",
+ dependencies = [
+ IntegrationsPatch::class,
+ OldVideoQualityMenuResourcePatch::class,
+ LithoFilterPatch::class,
+ RecyclerViewTreeHookPatch::class
+ ],
+ compatiblePackages = [
+ CompatiblePackage(
+ "com.google.android.youtube",
+ [
+ "18.20.39",
+ "18.23.35",
+ "18.29.38",
+ "18.32.39",
+ "18.37.36"
+ ]
+ )
+ ]
+)
+@Suppress("unused")
+object OldVideoQualityMenuPatch : BytecodePatch(
+ setOf(VideoQualityMenuViewInflateFingerprint)
) {
+ private const val FILTER_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/VideoQualityMenuFilterPatch;"
+
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch;"
+
override fun execute(context: BytecodeContext) {
// region Patch for the old type of the video quality menu.
+ // Only used when spoofing to old app version.
VideoQualityMenuViewInflateFingerprint.result?.let {
it.mutableMethod.apply {
@@ -49,19 +66,11 @@ class OldVideoQualityMenuPatch : BytecodePatch(
// region Patch for the new type of the video quality menu.
- BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
+ RecyclerViewTreeHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
// Required to check if the video quality menu is currently shown in order to click on the "Advanced" item.
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// endregion
}
-
- private companion object {
- private const val FILTER_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/components/VideoQualityMenuFilterPatch;"
-
- private const val INTEGRATIONS_CLASS_DESCRIPTOR =
- "Lapp/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch;"
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/OldVideoQualityMenuResourcePatch.kt
similarity index 71%
rename from src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/OldVideoQualityMenuResourcePatch.kt
index 5c21965d0..9d7599d99 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/OldVideoQualityMenuResourcePatch.kt
@@ -1,16 +1,20 @@
-package app.revanced.patches.youtube.video.videoqualitymenu.patch
+package app.revanced.patches.youtube.video.videoqualitymenu
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
+
+@Patch(
+ dependencies = [SettingsPatch::class, ResourceMappingPatch::class]
+)
+object OldVideoQualityMenuResourcePatch : ResourcePatch() {
+ internal var videoQualityBottomSheetListFragmentTitle = -1L
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
-class OldVideoQualityMenuResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
SwitchPreference(
@@ -27,8 +31,4 @@ class OldVideoQualityMenuResourcePatch : ResourcePatch {
// Used for the old type of the video quality menu.
videoQualityBottomSheetListFragmentTitle = findResource("video_quality_bottom_sheet_list_fragment_title")
}
-
- internal companion object {
- var videoQualityBottomSheetListFragmentTitle = -1L
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/annotations/OldVideoQualityMenuCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/annotations/OldVideoQualityMenuCompatibility.kt
deleted file mode 100644
index 85c894882..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/annotations/OldVideoQualityMenuCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.video.videoqualitymenu.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class OldVideoQualityMenuCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuViewInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuViewInflateFingerprint.kt
index 989aa0deb..2b41427c7 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuViewInflateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuViewInflateFingerprint.kt
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.video.videoqualitymenu.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patches.youtube.video.videoqualitymenu.patch.OldVideoQualityMenuResourcePatch
+import app.revanced.patches.youtube.video.videoqualitymenu.OldVideoQualityMenuResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -26,5 +26,5 @@ object VideoQualityMenuViewInflateFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST
),
- literal = OldVideoQualityMenuResourcePatch.videoQualityBottomSheetListFragmentTitle
+ literalSupplier = { OldVideoQualityMenuResourcePatch.videoQualityBottomSheetListFragmentTitle }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/HideAdsPatch.kt
similarity index 74%
rename from src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/HideAdsPatch.kt
index bf96a8449..4402a1a53 100644
--- a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/HideAdsPatch.kt
@@ -1,28 +1,25 @@
-package app.revanced.patches.youtubevanced.ad.general.patch
+package app.revanced.patches.youtubevanced.ad.general
import app.revanced.extensions.exception
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
-import app.revanced.patches.youtubevanced.ad.general.annotations.HideAdsCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patches.shared.misc.fix.verticalscroll.VerticalScrollPatch
import app.revanced.patches.youtubevanced.ad.general.fingerprints.ContainsAdFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
-@Patch
-@Name("Hide ads")
-@Description("Removes general ads.")
-@DependsOn([VerticalScrollPatch::class])
-@HideAdsCompatibility
-class HideAdsPatch : BytecodePatch(
- listOf(
- ContainsAdFingerprint
- )
+@Patch(
+ name = "Hide ads",
+ description = "Removes general ads.",
+ dependencies = [VerticalScrollPatch::class],
+ compatiblePackages = [CompatiblePackage("com.vanced.android.youtube")]
+)
+@Suppress("unused")
+object HideAdsPatch : BytecodePatch(
+ setOf(ContainsAdFingerprint)
) {
override fun execute(context: BytecodeContext) {
ContainsAdFingerprint.result?.let { result ->
diff --git a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/annotations/HideAdsCompatibility.kt
deleted file mode 100644
index e7c85c582..000000000
--- a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/annotations/HideAdsCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtubevanced.ad.general.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.vanced.android.youtube")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/patch/UnlockPremiunPatch.kt b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt
similarity index 62%
rename from src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/patch/UnlockPremiunPatch.kt
rename to src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt
index 3c5aaf45d..5f8a7608e 100644
--- a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/patch/UnlockPremiunPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt
@@ -1,26 +1,22 @@
-package app.revanced.patches.yuka.misc.unlockpremium.patch
+package app.revanced.patches.yuka.misc.unlockpremium
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.yuka.misc.unlockpremium.annotations.UnlockPremiumCompatibility
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.yuka.misc.unlockpremium.fingerprints.IsPremiumFingerprint
import app.revanced.patches.yuka.misc.unlockpremium.fingerprints.YukaUserConstructorFingerprint
-@Patch
-@Name("Unlock premium")
-@Description("Unlocks premium features.")
-@UnlockPremiumCompatibility
-class UnlockPremiunPatch : BytecodePatch(
- listOf(
- YukaUserConstructorFingerprint
- )
+@Patch(
+ name = "Unlock premium",
+ compatiblePackages = [CompatiblePackage("io.yuka.android")]
+)
+@Suppress("unused")
+object UnlockPremiumPatch : BytecodePatch(
+ setOf(YukaUserConstructorFingerprint)
) {
-
override fun execute(context: BytecodeContext) {
IsPremiumFingerprint.resolve(context,YukaUserConstructorFingerprint.result!!.classDef)
val method = IsPremiumFingerprint.result!!.mutableMethod
@@ -32,5 +28,4 @@ class UnlockPremiunPatch : BytecodePatch(
"""
)
}
-
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/annotations/UnlockPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/annotations/UnlockPremiumCompatibility.kt
deleted file mode 100644
index caa0db41f..000000000
--- a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/annotations/UnlockPremiumCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.yuka.misc.unlockpremium.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("io.yuka.android")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class UnlockPremiumCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/util/patch/LiteralValueFingerprint.kt b/src/main/kotlin/app/revanced/util/patch/LiteralValueFingerprint.kt
index 86c3b98e5..e0cee8da2 100644
--- a/src/main/kotlin/app/revanced/util/patch/LiteralValueFingerprint.kt
+++ b/src/main/kotlin/app/revanced/util/patch/LiteralValueFingerprint.kt
@@ -10,7 +10,8 @@ abstract class LiteralValueFingerprint(
parameters: Iterable? = null,
opcodes: Iterable? = null,
strings: Iterable? = null,
- literal: Long
+ // Has to be a supplier because the fingerprint is created before patches can set literals.
+ literalSupplier: () -> Long
) : MethodFingerprint(
returnType = returnType,
accessFlags = accessFlags,
@@ -18,6 +19,6 @@ abstract class LiteralValueFingerprint(
opcodes = opcodes,
strings = strings,
customFingerprint = { methodDef, _ ->
- methodDef.containsConstantInstructionValue(literal)
+ methodDef.containsConstantInstructionValue(literalSupplier())
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt b/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt
index 0cb67a06f..f253b055c 100644
--- a/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt
+++ b/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt
@@ -3,7 +3,7 @@ package app.revanced.util.resources
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.util.DomFileEditor
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.SettingsPatch
import org.w3c.dom.Node
import java.nio.file.Files
import java.nio.file.StandardCopyOption
diff --git a/src/main/resources/sponsorblock/host/values/strings.xml b/src/main/resources/sponsorblock/host/values/strings.xml
index 7f63c88ca..cdda3bf06 100644
--- a/src/main/resources/sponsorblock/host/values/strings.xml
+++ b/src/main/resources/sponsorblock/host/values/strings.xml
@@ -53,7 +53,8 @@
API URL changed
Import/Export settings
Copy
- Your SponsorBlock JSON configuration that can be imported/exported to ReVanced and other SponsorBlock platforms. This includes your private user id. Be sure to share this wisely
+ Your SponsorBlock JSON configuration that can be imported/exported to ReVanced and other SponsorBlock platforms. %s
+ This includes your private user id. Be sure to share this wisely
Settings imported successfully
Failed to import: %s
Failed to export: %s