diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0f70b809..b186d92f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,80 @@
+# [2.178.0-dev.9](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.8...v2.178.0-dev.9) (2023-06-21)
+
+
+### Features
+
+* **twitch:** 15.4.1 support ([#2462](https://github.com/revanced/revanced-patches/issues/2462)) ([826ed49](https://github.com/revanced/revanced-patches/commit/826ed49c7ca5a00e383b743f88f75dbfc00adb43))
+
+# [2.178.0-dev.8](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.7...v2.178.0-dev.8) (2023-06-20)
+
+
+### Bug Fixes
+
+* **boostforreddit:** use correct options ([ec39732](https://github.com/revanced/revanced-patches/commit/ec39732a05f7c4c3360b8ba42fe50fd60952e6ac))
+
+# [2.178.0-dev.7](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.6...v2.178.0-dev.7) (2023-06-19)
+
+
+### Features
+
+* **youtube-music:** remove version compatibility constraints ([276af14](https://github.com/revanced/revanced-patches/commit/276af1415a4d354c62fe6259b6559bca1fa84f08))
+
+# [2.178.0-dev.6](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.5...v2.178.0-dev.6) (2023-06-18)
+
+
+### Bug Fixes
+
+* **youtube/hide-album-cards:** call correct integrations method ([0dbffaa](https://github.com/revanced/revanced-patches/commit/0dbffaae7d6dcb7050a9ea6e3c771839bcfdfbe1))
+
+# [2.178.0-dev.5](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.4...v2.178.0-dev.5) (2023-06-18)
+
+
+### Features
+
+* **youtube/hide-layout-components:** separate hiding expandable chips and chapters ([3fb1ce9](https://github.com/revanced/revanced-patches/commit/3fb1ce9f9af150b784e42aaf5b419bb123c08375))
+
+# [2.178.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.3...v2.178.0-dev.4) (2023-06-18)
+
+
+### Features
+
+* **boostforreddit:** add `change-oauth-client-id` patch ([3dbc4bd](https://github.com/revanced/revanced-patches/commit/3dbc4bd49df1656893ef69c68550a2deb6a92cb7))
+
+# [2.178.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.2...v2.178.0-dev.3) (2023-06-17)
+
+
+### Bug Fixes
+
+* **youtube/comments:** add missing filter ([#2423](https://github.com/revanced/revanced-patches/issues/2423)) ([cab04b3](https://github.com/revanced/revanced-patches/commit/cab04b3a56cfc5bf00b7c6fcf6f86ab75aa5d4fd))
+
+# [2.178.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.1...v2.178.0-dev.2) (2023-06-16)
+
+
+### Bug Fixes
+
+* **googlerecorder/remove-device-restrictions:** add missing app constraint ([#2438](https://github.com/revanced/revanced-patches/issues/2438)) ([d5efe26](https://github.com/revanced/revanced-patches/commit/d5efe26f8959cde75dd3865ec3c2df4b05210e4a))
+
+# [2.178.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.177.1-dev.2...v2.178.0-dev.1) (2023-06-16)
+
+
+### Features
+
+* **google-recorder:** add `remove-device-restrictions` patch ([ef96ed1](https://github.com/revanced/revanced-patches/commit/ef96ed124e12091dde34124eabd8be9f2bb9280c))
+
+## [2.177.1-dev.2](https://github.com/revanced/revanced-patches/compare/v2.177.1-dev.1...v2.177.1-dev.2) (2023-06-14)
+
+
+### Bug Fixes
+
+* **youtube:** separate `hide-ads` to `hide-layout-components` patch ([7e0417f](https://github.com/revanced/revanced-patches/commit/7e0417f6728fa7b79a9d8cbcfd3ccba484a5567d))
+
+## [2.177.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.177.0...v2.177.1-dev.1) (2023-06-14)
+
+
+### Bug Fixes
+
+* don't include all Litho patches, when not included ([fc69491](https://github.com/revanced/revanced-patches/commit/fc69491dfe4b119d46dd3da27b556e55fe0cecfb))
+
# [2.177.0](https://github.com/revanced/revanced-patches/compare/v2.176.1...v2.177.0) (2023-06-12)
diff --git a/README.md b/README.md
index 6abfee19a..f20541792 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,6 @@ The official ReVanced Patches.
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
| `hide-ads` | Removes general ads. | 18.19.35 |
| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
-| `hide-artist-card` | Hides the artist card below the searchbar. | 18.19.35 |
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
@@ -36,6 +35,7 @@ The official ReVanced Patches.
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.19.35 |
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.19.35 |
| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
+| `hide-layout-components` | Hides general layout components. | 18.19.35 |
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
@@ -71,16 +71,15 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `background-play` | Enables playing music in the background. | all |
-| `bypass-certificate-checks` | Bypasses certificate checks which prevent YouTube Music from working on Android Auto. | 5.39.52 |
+| `bypass-certificate-checks` | Bypasses certificate checks which prevent YouTube Music from working on Android Auto. | all |
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | all |
| `compact-header` | Hides the music category bar at the top of the homepage. | all |
| `exclusive-audio-playback` | Enables the option to play music without video. | all |
-| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | 5.39.52 |
+| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | all |
| `minimized-playback-music` | Enables minimized playback on Kids music. | all |
-| `music-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | all |
| `music-video-ads` | Removes ads in the music player. | all |
-| `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | all |
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | all |
+| `vanced-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | all |
### [📦 `com.ss.android.ugc.trill`](https://play.google.com/store/apps/details?id=com.ss.android.ugc.trill)
@@ -120,13 +119,13 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `auto-claim-channel-points` | Automatically claim Channel Points. | all |
-| `block-audio-ads` | Blocks audio ads in streams and VODs. | 14.6.1 |
-| `block-embedded-ads` | Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker. | 14.6.1 |
-| `block-video-ads` | Blocks video ads in streams and VODs. | 14.6.1 |
+| `auto-claim-channel-points` | Automatically claim Channel Points. | 15.4.1 |
+| `block-audio-ads` | Blocks audio ads in streams and VODs. | 15.4.1 |
+| `block-embedded-ads` | Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker. | 15.4.1 |
+| `block-video-ads` | Blocks video ads in streams and VODs. | 15.4.1 |
| `debug-mode` | Enables Twitch's internal debugging mode. | all |
| `settings` | Adds settings menu to Twitch. | all |
-| `show-deleted-messages` | Shows deleted chat messages behind a clickable spoiler. | all |
+| `show-deleted-messages` | Shows deleted chat messages behind a clickable spoiler. | 15.4.1 |
### [📦 `com.twitter.android`](https://play.google.com/store/apps/details?id=com.twitter.android)
@@ -205,6 +204,14 @@ The official ReVanced Patches.
| `spoof-signature` | Spoofs the signature of the app. | all |
+### [📦 `com.rubenmayayo.reddit`](https://play.google.com/store/apps/details?id=com.rubenmayayo.reddit)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `change-oauth-client-id` | Changes the OAuth client ID in Boost for Reddit. | all |
+
+
### [📦 `com.laurencedawson.reddit_sync.pro`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync.pro)
@@ -293,6 +300,14 @@ The official ReVanced Patches.
| `remove-debugging-detection` | Removes the USB and wireless debugging checks. | all |
+### [📦 `com.google.android.apps.recorder`](https://play.google.com/store/apps/details?id=com.google.android.apps.recorder)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `remove-device-restrictions` | Removes restrictions from using the app on any device. | all |
+
+
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
@@ -325,6 +340,30 @@ The official ReVanced Patches.
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
+### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | all |
+
+
+### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | 4.6377 |
+
+
+### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | all |
+
+
### [📦 `com.vsco.cam`](https://play.google.com/store/apps/details?id=com.vsco.cam)
@@ -341,22 +380,6 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all pro features. | all |
-### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks premium features. | all |
-
-
-### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks pro features. | all |
-
-
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
@@ -365,22 +388,6 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all pro features. | all |
-### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks pro features. | 4.6377 |
-
-
-### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all pro features. | all |
-
-
### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
@@ -389,14 +396,6 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
-### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks pro features. | all |
-
-
### [📦 `com.wakdev.apps.nfctools.se`](https://play.google.com/store/apps/details?id=com.wakdev.apps.nfctools.se)
@@ -405,6 +404,22 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all pro features. | all |
+### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks all pro features. | all |
+
+
+### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks premium features. | all |
+
+
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
diff --git a/gradle.properties b/gradle.properties
index 341b337b6..7b44cb5b4 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
kotlin.code.style = official
-version = 2.177.0
+version = 2.178.0-dev.9
diff --git a/patches.json b/patches.json
index 540c9f224..ce04e4541 100644
--- a/patches.json
+++ b/patches.json
@@ -1 +1 @@
-[{"name":"always-autorepeat","description":"Always repeats the playing video again.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"auto-claim-channel-points","description":"Automatically claim Channel Points.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"background-play","description":"Enables playing music in the background.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"block-embedded-ads","description":"Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker.","version":"0.0.1","excluded":false,"options":[],"dependencies":["block-video-ads","integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"block-video-ads","description":"Blocks video ads in streams and VODs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"bypass-certificate-checks","description":"Bypasses certificate checks which prevent YouTube Music from working on Android Auto.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50","5.34.51","5.36.51","5.38.53","5.39.52","5.40.51","5.41.50","5.48.52"]}]},{"name":"change-oauth-client-id","description":"Changes the OAuth client ID.","version":"0.0.1","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The client ID to use for OAuth.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]},{"name":"com.laurencedawson.reddit_sync.pro","versions":[]}]},{"name":"change-package-name","description":"Changes the package name.","version":"0.0.1","excluded":true,"options":[{"key":"packageName","title":"Package name","description":"The name of the package to rename of the app.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"client-spoof","description":"Spoofs a patched client to allow playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["spoof-signature-verification"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"codecs-unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"compact-header","description":"Hides the music category bar at the top of the homepage.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["copy-video-url-resource","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"custom-branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","version":"0.0.1","excluded":false,"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-video-buffer","description":"Lets you change the buffers of videos.","version":"0.0.1","excluded":true,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"debug-mode","description":"Enables Twitch\u0027s internal debugging mode.","version":"0.0.1","excluded":true,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"disable-ads","description":"Disables ads in HexEditor.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.myprog.hexedit","versions":[]}]},{"name":"disable-ads","description":"Disables ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]}]},{"name":"disable-auto-captions","description":"Disable forced captions from being automatically enabled.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-fullscreen-panels","description":"Disables video description and comments panel in fullscreen view.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-login-requirement","description":"Do not force login.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"disable-player-popup-panels","description":"Disables panels from appearing automatically when going into fullscreen (playlist or live chat).","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-shorts-on-startup","description":"Disables playing YouTube Shorts when launching YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-switching-emoji-to-sticker-in-message-input-field","description":"Disables switching from emoji to sticker search mode in message input field","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"disable-typing-indicator","description":"Disables the indicator while typing a message","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"disable-zoom-haptics","description":"Disables haptics when zooming.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"enable-android-debugging","description":"Enables Android debugging capabilities.","version":"0.0.1","excluded":true,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"enable-debugging","description":"Adds debugging options.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings","enable-android-debugging"],"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.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.lite","versions":[]}]},{"name":"exclusive-audio-playback","description":"Enables the option to play music without video.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"export-all-activities","description":"Makes all app activities exportable.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"external-downloads","description":"Adds support to download and save YouTube videos using an external app.","version":"0.0.1","excluded":false,"options":[],"dependencies":["external-downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"feed-filter","description":"Filters tiktok videos: removing ads, removing livestreams.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["VerticalScrollPatch"],"compatiblePackages":[{"name":"com.vanced.android.youtube","versions":[]}]},{"name":"hide-ads","description":"Removes ads from Inshorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.nis.app","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["hide-get-premium","HideAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-ads","description":"Hides ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-ads","description":"Removes ads from the Reddit.","version":"0.0.2","excluded":false,"options":[],"dependencies":["hide-subreddit-banner","hide-comment-ads"],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-ads","description":"Removes ads from TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"hide-album-cards","description":"Hides the album cards below the artist description.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-album-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-artist-card","description":"Hides the artist card below the searchbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-autoplay-button","description":"Hides the autoplay button in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-breaking-news-shelf","description":"Hides the breaking news shelf on the homepage tab.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","breaking-news-shelf-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-captions-button","description":"Hides the captions button on video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-cast-button","description":"Hides the cast button in the video player.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","crowdfunding-box-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-email-address","description":"Hides the email address in the account switcher.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-email-address-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-endscreen-cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-endscreen-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-filter-bar","description":"Hides the filter bar in video feeds.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFilterBarResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-floating-microphone-button","description":"Hides the floating microphone button which appears in search.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFloatingMicrophoneButtonResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-get-premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50","5.34.51","5.36.51","5.38.53","5.39.52"]}]},{"name":"hide-inbox-ads","description":"Hides ads in inbox.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"hide-info-cards","description":"Hides info cards in videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","HideInfocardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-load-more-button","description":"Hides the button under videos that loads similar videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["hide-load-more-button-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-player-buttons","description":"Adds the option to hide video player previous and next buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-player-overlay","description":"Hides the dark background overlay from the player when player controls are visible.","version":"0.0.2","excluded":false,"options":[],"dependencies":["HidePlayerOverlayResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-premium-navbar","description":"Removes the premium tab from the navbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"hide-recommended-users","description":"Hides recommended users.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-seekbar","description":"Hides the seekbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","SeekbarColorBytecodePatch","SeekbarPreferencesPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-shorts-components","description":"Hides components from YouTube Shorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","LithoFilterPatch","HideShortsComponentsResourcePatch","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-timeline-ads","description":"Removes ads from the timeline.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":["275.0.0.27.98"]}]},{"name":"hide-timestamp","description":"Hides timestamp in video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-video-action-buttons","description":"Adds the options to hide action buttons under a video.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-views-stats","description":"Hides the view stats under tweets.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideViewsBytecodePatch"],"compatiblePackages":[{"name":"com.twitter.android","versions":["9.69.1-release.0","9.71.0-release.0"]}]},{"name":"hide-watch-in-vr","description":"Hides the option to watch in VR from the player settings flyout panel.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-watermark","description":"Hides creator\u0027s watermarks on videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"minimized-playback-music","description":"Enables minimized playback on Kids music.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-microg-support","description":"Allows YouTube Music ReVanced to run without root and under a different package name.","version":"0.0.2","excluded":false,"options":[],"dependencies":["music-microg-resource-patch"],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-video-ads","description":"Removes ads in the music player.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"old-quality-layout","description":"Enables the original video quality flyout in the video player settings.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","OldQualityLayoutResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"open-links-externally","description":"Open links outside of the app directly in your browser.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"playback-speed","description":"Enables the playback speed option for all videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"predictive-back-gesture","description":"Enables the predictive back gesture introduced on Android 13.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"premium-heading","description":"Shows premium branding on the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"premium-icon-reddit","description":"Unlocks premium Reddit app icons.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"pro-unlock","description":"Unlocks pro-only functions.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-information","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"remove-ads","description":"Removes all ads from the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.binarymode.android.irplus","versions":[]}]},{"name":"remove-badge-tab","description":"Removes the badge tab from the activity tab.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.sony.songpal.mdr","versions":[]}]},{"name":"remove-bootloader-detection","description":"Removes the check for an unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":[]}]},{"name":"remove-broadcasts-restriction","description":"Enables starting/stopping NetGuard via broadcasts.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"eu.faircode.netguard","versions":[]}]},{"name":"remove-debugging-detection","description":"Removes the USB and wireless debugging checks.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.scb.phone","versions":[]}]},{"name":"remove-notification-badge","description":"Removes the red notification badge from the activity tab.","version":"0.0.1","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.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":[]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions and unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"remove-screen-capture-restriction","description":"Removes the restriction of capturing audio from apps that normally wouldn\u0027t allow it.","version":"0.0.1","excluded":true,"options":[],"dependencies":["remove-screen-capture-restriction-resource-patch"],"compatiblePackages":[]},{"name":"remove-screenshot-restriction","description":"Removes the restriction of taking screenshots in apps that normally wouldn\u0027t allow it.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"return-youtube-dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","return-youtube-dislike-resource-patch","player-type-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"sanitize-sharing-links","description":"Removes (tracking) query parameters from the URLs when sharing links.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","EnableSeekbarTappingResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"settings","description":"Adds settings menu to Twitch.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"settings","description":"Adds ReVanced settings to TikTok.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-seekbar","description":"Shows progress bar for all video.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","video-information","player-type-hook","player-controls-bytecode-patch","sponsorblock-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"spoof-signature","description":"Spoofs the signature of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"spoof-wifi-connection","description":"Spoofs an existing Wi-Fi connection.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"spotify-theme","description":"Applies a custom theme.","version":"0.0.1","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.","version":"0.0.3","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","swipe-controls-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"tablet-mini-player","description":"Enables the tablet mini player layout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"tasteBuilder-remover","description":"Removes the \"Tell us which artists you like\" card from the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"theme","description":"Applies a custom theme.","version":"0.0.1","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-paid-widgets","description":"Unlocks paid widgets of the app","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.dci.dev.androidtwelvewidgets","versions":[]}]},{"name":"unlock-plus","description":"Unlocks plus features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["SignatureDetectionPatch"],"compatiblePackages":[{"name":"com.microblink.photomath","versions":["8.20.0"]}]},{"name":"unlock-premium","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"io.yuka.android","versions":[]}]},{"name":"unlock-prime","description":"Unlocks Nova Prime and all functions of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.teslacoilsw.launcher","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.vsco.cam","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"unlock-pro","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.candylink.openvpn","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","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 pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all professional features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":["3.4.9"]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.trakt.trakt","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.wakdev.apps.nfctools.se","versions":[]}]},{"name":"unlock-themes","description":"Unlocks all themes that are inaccessible until a certain level is reached.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ticktick.task","versions":[]}]},{"name":"unlock-trial","description":"Unlocks the trial version.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.dinglisch.android.taskerm","versions":[]}]},{"name":"upgrade-button-remover","description":"Removes the upgrade tab from the pivot bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"vanced-microg-support","description":"Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.","version":"0.0.1","excluded":false,"options":[],"dependencies":["microg-resource-patch","hide-cast-button","client-spoof"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"video-ads","description":"Removes ads in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"video-speed","description":"Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["custom-video-speed","remember-playback-speed"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"wide-searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]}]
\ No newline at end of file
+[{"name":"always-autorepeat","description":"Always repeats the playing video again.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"auto-claim-channel-points","description":"Automatically claim Channel Points.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1"]}]},{"name":"background-play","description":"Enables playing music in the background.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["block-video-ads","integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1"]}]},{"name":"block-video-ads","description":"Blocks video ads in streams and VODs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1"]}]},{"name":"bypass-certificate-checks","description":"Bypasses certificate checks which prevent YouTube Music from working on Android Auto.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"change-oauth-client-id","description":"Changes the OAuth client ID in Boost for Reddit.","version":"0.0.1","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":"change-oauth-client-id","description":"Changes the OAuth client ID.","version":"0.0.1","excluded":false,"options":[{"key":"client-id","title":"OAuth client ID","description":"The Reddit OAuth client ID.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]},{"name":"com.laurencedawson.reddit_sync.pro","versions":[]}]},{"name":"change-package-name","description":"Changes the package name.","version":"0.0.1","excluded":true,"options":[{"key":"packageName","title":"Package name","description":"The name of the package to rename of the app.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"client-spoof","description":"Spoofs a patched client to allow playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["spoof-signature-verification"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"codecs-unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"compact-header","description":"Hides the music category bar at the top of the homepage.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["copy-video-url-resource","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"custom-branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","version":"0.0.1","excluded":false,"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-video-buffer","description":"Lets you change the buffers of videos.","version":"0.0.1","excluded":true,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"debug-mode","description":"Enables Twitch\u0027s internal debugging mode.","version":"0.0.1","excluded":true,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"disable-ads","description":"Disables ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]}]},{"name":"disable-ads","description":"Disables ads in HexEditor.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.myprog.hexedit","versions":[]}]},{"name":"disable-auto-captions","description":"Disable forced captions from being automatically enabled.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-fullscreen-panels","description":"Disables video description and comments panel in fullscreen view.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-login-requirement","description":"Do not force login.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"disable-player-popup-panels","description":"Disables panels from appearing automatically when going into fullscreen (playlist or live chat).","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-shorts-on-startup","description":"Disables playing YouTube Shorts when launching YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-switching-emoji-to-sticker-in-message-input-field","description":"Disables switching from emoji to sticker search mode in message input field","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"disable-typing-indicator","description":"Disables the indicator while typing a message","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"disable-zoom-haptics","description":"Disables haptics when zooming.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"enable-android-debugging","description":"Enables Android debugging capabilities.","version":"0.0.1","excluded":true,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"enable-debugging","description":"Adds debugging options.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings","enable-android-debugging"],"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.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.lite","versions":[]}]},{"name":"exclusive-audio-playback","description":"Enables the option to play music without video.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"export-all-activities","description":"Makes all app activities exportable.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"external-downloads","description":"Adds support to download and save YouTube videos using an external app.","version":"0.0.1","excluded":false,"options":[],"dependencies":["external-downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"feed-filter","description":"Filters tiktok videos: removing ads, removing livestreams.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-ads","description":"Removes ads from TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"hide-ads","description":"Removes ads from the Reddit.","version":"0.0.2","excluded":false,"options":[],"dependencies":["hide-subreddit-banner","hide-comment-ads"],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-ads","description":"Hides ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["VerticalScrollPatch"],"compatiblePackages":[{"name":"com.vanced.android.youtube","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["hide-get-premium","HideAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-ads","description":"Removes ads from Inshorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.nis.app","versions":[]}]},{"name":"hide-album-cards","description":"Hides the album cards below the artist description.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-album-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-autoplay-button","description":"Hides the autoplay button in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-breaking-news-shelf","description":"Hides the breaking news shelf on the homepage tab.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","breaking-news-shelf-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-captions-button","description":"Hides the captions button on video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-cast-button","description":"Hides the cast button in the video player.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","crowdfunding-box-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-email-address","description":"Hides the email address in the account switcher.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-email-address-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-endscreen-cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-endscreen-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-filter-bar","description":"Hides the filter bar in video feeds.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFilterBarResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-floating-microphone-button","description":"Hides the floating microphone button which appears in search.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFloatingMicrophoneButtonResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-get-premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"hide-inbox-ads","description":"Hides ads in inbox.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"hide-info-cards","description":"Hides info cards in videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","HideInfocardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-layout-components","description":"Hides general layout components.","version":"0.0.1","excluded":false,"options":[],"dependencies":["LithoFilterPatch","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-load-more-button","description":"Hides the button under videos that loads similar videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["hide-load-more-button-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-player-buttons","description":"Adds the option to hide video player previous and next buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-player-overlay","description":"Hides the dark background overlay from the player when player controls are visible.","version":"0.0.2","excluded":false,"options":[],"dependencies":["HidePlayerOverlayResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-premium-navbar","description":"Removes the premium tab from the navbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"hide-recommended-users","description":"Hides recommended users.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-seekbar","description":"Hides the seekbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","SeekbarColorBytecodePatch","SeekbarPreferencesPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-shorts-components","description":"Hides components from YouTube Shorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","LithoFilterPatch","HideShortsComponentsResourcePatch","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-timeline-ads","description":"Removes ads from the timeline.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":["275.0.0.27.98"]}]},{"name":"hide-timestamp","description":"Hides timestamp in video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-video-action-buttons","description":"Adds the options to hide action buttons under a video.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-views-stats","description":"Hides the view stats under tweets.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideViewsBytecodePatch"],"compatiblePackages":[{"name":"com.twitter.android","versions":["9.69.1-release.0","9.71.0-release.0"]}]},{"name":"hide-watch-in-vr","description":"Hides the option to watch in VR from the player settings flyout panel.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-watermark","description":"Hides creator\u0027s watermarks on videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"minimized-playback-music","description":"Enables minimized playback on Kids music.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-video-ads","description":"Removes ads in the music player.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"old-quality-layout","description":"Enables the original video quality flyout in the video player settings.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","OldQualityLayoutResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"open-links-externally","description":"Open links outside of the app directly in your browser.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"playback-speed","description":"Enables the playback speed option for all videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"predictive-back-gesture","description":"Enables the predictive back gesture introduced on Android 13.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"premium-heading","description":"Shows premium branding on the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"premium-icon-reddit","description":"Unlocks premium Reddit app icons.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"pro-unlock","description":"Unlocks pro-only functions.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-information","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"remove-ads","description":"Removes all ads from the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.binarymode.android.irplus","versions":[]}]},{"name":"remove-badge-tab","description":"Removes the badge tab from the activity tab.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.sony.songpal.mdr","versions":[]}]},{"name":"remove-bootloader-detection","description":"Removes the check for an unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":[]}]},{"name":"remove-broadcasts-restriction","description":"Enables starting/stopping NetGuard via broadcasts.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"eu.faircode.netguard","versions":[]}]},{"name":"remove-debugging-detection","description":"Removes the USB and wireless debugging checks.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.scb.phone","versions":[]}]},{"name":"remove-device-restrictions","description":"Removes restrictions from using the app on any device.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.recorder","versions":[]}]},{"name":"remove-notification-badge","description":"Removes the red notification badge from the activity tab.","version":"0.0.1","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.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions and unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions.","version":"0.0.1","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.","version":"0.0.1","excluded":true,"options":[],"dependencies":["remove-screen-capture-restriction-resource-patch"],"compatiblePackages":[]},{"name":"remove-screenshot-restriction","description":"Removes the restriction of taking screenshots in apps that normally wouldn\u0027t allow it.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"return-youtube-dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","return-youtube-dislike-resource-patch","player-type-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"sanitize-sharing-links","description":"Removes (tracking) query parameters from the URLs when sharing links.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","EnableSeekbarTappingResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"settings","description":"Adds ReVanced settings to TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"settings","description":"Adds settings menu to Twitch.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-deleted-messages","description":"Shows deleted chat messages behind a clickable spoiler.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["15.4.1"]}]},{"name":"show-seekbar","description":"Shows progress bar for all video.","version":"0.0.1","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.","version":"0.0.1","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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","video-information","player-type-hook","player-controls-bytecode-patch","sponsorblock-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"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.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"spoof-signature","description":"Spoofs the signature of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"spoof-wifi-connection","description":"Spoofs an existing Wi-Fi connection.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"spotify-theme","description":"Applies a custom theme.","version":"0.0.1","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.","version":"0.0.3","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","swipe-controls-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"tablet-mini-player","description":"Enables the tablet mini player layout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"theme","description":"Applies a custom theme.","version":"0.0.1","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-paid-widgets","description":"Unlocks paid widgets of the app","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.dci.dev.androidtwelvewidgets","versions":[]}]},{"name":"unlock-plus","description":"Unlocks plus features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["SignatureDetectionPatch"],"compatiblePackages":[{"name":"com.microblink.photomath","versions":["8.20.0"]}]},{"name":"unlock-premium","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"io.yuka.android","versions":[]}]},{"name":"unlock-prime","description":"Unlocks Nova Prime and all functions of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.teslacoilsw.launcher","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.trakt.trakt","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","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 pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.vsco.cam","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all professional features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":["3.4.9"]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.wakdev.apps.nfctools.se","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"unlock-pro","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.candylink.openvpn","versions":[]}]},{"name":"unlock-themes","description":"Unlocks all themes that are inaccessible until a certain level is reached.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ticktick.task","versions":[]}]},{"name":"unlock-trial","description":"Unlocks the trial version.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.dinglisch.android.taskerm","versions":[]}]},{"name":"upgrade-button-remover","description":"Removes the upgrade tab from the pivot bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"vanced-microg-support","description":"Allows YouTube Music ReVanced to run without root and under a different package name.","version":"0.0.2","excluded":false,"options":[],"dependencies":["microg-resource-patch"],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"vanced-microg-support","description":"Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.","version":"0.0.1","excluded":false,"options":[],"dependencies":["microg-resource-patch","hide-cast-button","client-spoof"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"video-ads","description":"Removes ads in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"video-speed","description":"Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["custom-video-speed","remember-playback-speed"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"wide-searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]}]
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/fingereprints/OnApplicationCreateFingerprint.kt b/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/fingereprints/OnApplicationCreateFingerprint.kt
new file mode 100644
index 000000000..9eb26b8bd
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/fingereprints/OnApplicationCreateFingerprint.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.googlerecorder.restrictions.fingereprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object OnApplicationCreateFingerprint : MethodFingerprint(
+ strings = listOf("com.google.android.feature.PIXEL_2017_EXPERIENCE"),
+ customFingerprint = custom@{ methodDef, classDef ->
+ if (methodDef.name != "onCreate") return@custom false
+
+ classDef.type.endsWith("RecorderApplication;")
+ }
+)
diff --git a/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/patch/RemoveDeviceRestrictions.kt b/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/patch/RemoveDeviceRestrictions.kt
new file mode 100644
index 000000000..095d5db4a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/patch/RemoveDeviceRestrictions.kt
@@ -0,0 +1,45 @@
+package app.revanced.patches.googlerecorder.restrictions.patch
+
+import app.revanced.extensions.toErrorResult
+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.annotation.Version
+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.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.googlerecorder.restrictions.fingereprints.OnApplicationCreateFingerprint
+import org.jf.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")])
+@Version("0.0.1")
+class RemoveDeviceRestrictions : BytecodePatch(
+ listOf(OnApplicationCreateFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ OnApplicationCreateFingerprint.result?.let {
+ val featureStringIndex = it.scanResult.stringsScanResult!!.matches.first().index
+
+ it.mutableMethod.apply {
+ // Remove check for device restrictions.
+ removeInstructions(featureStringIndex - 2, 5)
+
+ val featureAvailableRegister = getInstruction(featureStringIndex).registerA
+
+ // Override "isPixelDevice()" to return true.
+ addInstruction(featureStringIndex, "const/4 v$featureAvailableRegister, 0x1")
+ }
+ } ?: return OnApplicationCreateFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
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/patch/MusicVideoAdsPatch.kt
index bd4d91107..5d5ae990a 100644
--- a/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt
@@ -10,19 +10,17 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
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.")
-@MusicVideoAdsCompatibility
+@MusicCompatibility
@Version("0.0.1")
class MusicVideoAdsPatch : BytecodePatch(
- listOf(
- ShowMusicVideoAdsConstructorFingerprint
- )
+ listOf(ShowMusicVideoAdsConstructorFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/annotations/MusicCompatibility.kt
similarity index 64%
rename from src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/music/annotations/MusicCompatibility.kt
index 0910b502d..5cd3b494c 100644
--- a/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/music/annotations/MusicCompatibility.kt
@@ -1,8 +1,8 @@
-package app.revanced.patches.music.ad.video.annotations
+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 MusicVideoAdsCompatibility
+internal annotation class MusicCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt
deleted file mode 100644
index cefdb7798..000000000
--- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.audio.codecs.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 CodecsUnlockCompatibility
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/patch/CodecsUnlockPatch.kt
index 9ff6916b8..29de5e3b9 100644
--- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt
@@ -10,7 +10,7 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.toInstruction
-import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
+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 org.jf.dexlib2.Opcode
@@ -18,7 +18,7 @@ import org.jf.dexlib2.Opcode
@Patch
@Name("codecs-unlock")
@Description("Adds more audio codec options. The new audio codecs usually result in better audio quality.")
-@CodecsUnlockCompatibility
+@MusicCompatibility
@Version("0.0.1")
class CodecsUnlockPatch : BytecodePatch(
listOf(
diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt
deleted file mode 100644
index ac0ec5ba3..000000000
--- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.audio.exclusiveaudio.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 ExclusiveAudioCompatibility
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/patch/ExclusiveAudioPatch.kt
index 4579235e0..531790c65 100644
--- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt
@@ -10,18 +10,16 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
+import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AudioOnlyEnablerFingerprint
@Patch
@Name("exclusive-audio-playback")
@Description("Enables the option to play music without video.")
-@ExclusiveAudioCompatibility
+@MusicCompatibility
@Version("0.0.1")
class ExclusiveAudioPatch : BytecodePatch(
- listOf(
- AudioOnlyEnablerFingerprint
- )
+ listOf(AudioOnlyEnablerFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
val method = AudioOnlyEnablerFingerprint.result!!.mutableMethod
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt
deleted file mode 100644
index 573e6452e..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.layout.compactheader.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 CompactHeaderCompatibility
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/patch/CompactHeaderPatch.kt
index 843c7e46f..d3a59bdb5 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt
@@ -9,19 +9,17 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.layout.compactheader.annotations.CompactHeaderCompatibility
+import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
@Patch(false)
@Name("compact-header")
@Description("Hides the music category bar at the top of the homepage.")
-@CompactHeaderCompatibility
+@MusicCompatibility
@Version("0.0.1")
class CompactHeaderPatch : BytecodePatch(
- listOf(
- CompactHeaderConstructorFingerprint
- )
+ listOf(CompactHeaderConstructorFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
val result = CompactHeaderConstructorFingerprint.result!!
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
deleted file mode 100644
index 7045f279e..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.layout.minimizedplayback.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 MinimizedPlaybackCompatibility
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
index e6239db7f..8e0b07d0c 100644
--- 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
@@ -9,18 +9,16 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
+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.")
-@MinimizedPlaybackCompatibility
+@MusicCompatibility
@Version("0.0.1")
class MinimizedPlaybackPatch : BytecodePatch(
- listOf(
- MinimizedPlaybackManagerFingerprint
- )
+ listOf(MinimizedPlaybackManagerFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstruction(
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt
deleted file mode 100644
index 134720211..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package app.revanced.patches.music.layout.premium.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.apps.youtube.music",
- arrayOf(
- "5.14.53",
- "5.16.51",
- "5.17.51",
- "5.21.52",
- "5.22.54",
- "5.23.50",
- "5.25.51",
- "5.25.52",
- "5.26.52",
- "5.27.51",
- "5.28.52",
- "5.29.52",
- "5.31.50",
- "5.34.51",
- "5.36.51",
- "5.38.53",
- "5.39.52"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideGetPremiumCompatibility
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/patch/HideGetPremiumPatch.kt
index b4f8c1a9d..d25a45524 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt
@@ -11,19 +11,17 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
+import app.revanced.patches.music.annotations.MusicCompatibility
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.")
-@HideGetPremiumCompatibility
+@MusicCompatibility
@Version("0.0.1")
class HideGetPremiumPatch : BytecodePatch(
- listOf(
- HideGetPremiumParentFingerprint
- )
+ listOf(HideGetPremiumParentFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
val parentResult = HideGetPremiumParentFingerprint.result!!
@@ -33,9 +31,10 @@ class HideGetPremiumPatch : BytecodePatch(
val parentMethod = parentResult.mutableMethod
parentMethod.replaceInstruction(
- startIndex, """
- const/4 v1, 0x0
- """
+ startIndex,
+ """
+ const/4 v1, 0x0
+ """
)
val result = HideGetPremiumFingerprint.result!!
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt
deleted file mode 100644
index ce2b14d87..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package app.revanced.patches.music.layout.tastebuilder.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-/**
- * -- Note 2022-08-05 --
- * Since 5.17.xx the tastebuilder component is dismissible, so this patch is less useful
- * also it is partly litho now
- */
-@Compatibility([Package("com.google.android.apps.youtube.music")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class RemoveTasteBuilderCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt
deleted file mode 100644
index e72193c6f..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package app.revanced.patches.music.layout.tastebuilder.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-
-
-@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
-object TasteBuilderConstructorFingerprint : MethodFingerprint(
- "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
- Opcode.INVOKE_DIRECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.NEW_INSTANCE,
- Opcode.INVOKE_DIRECT,
- Opcode.IPUT_OBJECT,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CONST,
- Opcode.CONST_4,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.IPUT_OBJECT,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CHECK_CAST,
- Opcode.NEW_INSTANCE,
- Opcode.INVOKE_DIRECT,
- Opcode.IPUT_OBJECT,
- Opcode.CONST
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt
deleted file mode 100644
index 5f1ef34b8..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package app.revanced.patches.music.layout.tastebuilder.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility
-import app.revanced.patches.music.layout.tastebuilder.fingerprints.TasteBuilderConstructorFingerprint
-import org.jf.dexlib2.iface.instruction.formats.Instruction22c
-
-@Patch
-@Name("tasteBuilder-remover")
-@Description("Removes the \"Tell us which artists you like\" card from the home screen.")
-@RemoveTasteBuilderCompatibility
-@Version("0.0.1")
-class RemoveTasteBuilderPatch : BytecodePatch(
- listOf(
- TasteBuilderConstructorFingerprint
- )
-) {
- override fun execute(context: BytecodeContext): PatchResult {
- val result = TasteBuilderConstructorFingerprint.result!!
- val method = result.mutableMethod
-
- val insertIndex = result.scanResult.patternScanResult!!.endIndex - 8
- val register = (method.implementation!!.instructions[insertIndex] as Instruction22c).registerA
- method.addInstructions(
- insertIndex,
- """
- const/16 v1, 0x8
- invoke-virtual {v${register}, v1}, Landroid/view/View;->setVisibility(I)V
- """
- )
-
- return PatchResultSuccess()
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt
deleted file mode 100644
index e68303061..000000000
--- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.layout.upgradebutton.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 RemoveUpgradeButtonCompatibility
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/patch/RemoveUpgradeButtonPatch.kt
index 1a134862d..111197d2a 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt
@@ -10,7 +10,7 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.toInstructions
-import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility
+import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction22t
@@ -21,12 +21,10 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
@Name("upgrade-button-remover")
@Description("Removes the upgrade tab from the pivot bar.")
-@RemoveUpgradeButtonCompatibility
+@MusicCompatibility
@Version("0.0.1")
class RemoveUpgradeButtonPatch : BytecodePatch(
- listOf(
- PivotBarConstructorFingerprint
- )
+ listOf(PivotBarConstructorFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
val result = PivotBarConstructorFingerprint.result!!
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/androidauto/annotations/BypassCertificateChecksCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/misc/androidauto/annotations/BypassCertificateChecksCompatibility.kt
deleted file mode 100644
index dbbd31992..000000000
--- a/src/main/kotlin/app/revanced/patches/music/misc/androidauto/annotations/BypassCertificateChecksCompatibility.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package app.revanced.patches.music.misc.androidauto.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.apps.youtube.music",
- arrayOf(
- "5.14.53",
- "5.16.51",
- "5.17.51",
- "5.21.52",
- "5.22.54",
- "5.23.50",
- "5.25.51",
- "5.25.52",
- "5.26.52",
- "5.27.51",
- "5.28.52",
- "5.29.52",
- "5.31.50",
- "5.34.51",
- "5.36.51",
- "5.38.53",
- "5.39.52",
- "5.40.51",
- "5.41.50",
- "5.48.52"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-@Retention(AnnotationRetention.RUNTIME)
-internal annotation class BypassCertificateChecksCompatibility
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/patch/BypassCertificateChecksPatch.kt
index e429b1187..69a93a872 100644
--- a/src/main/kotlin/app/revanced/patches/music/misc/androidauto/patch/BypassCertificateChecksPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/misc/androidauto/patch/BypassCertificateChecksPatch.kt
@@ -11,18 +11,16 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.misc.androidauto.annotations.BypassCertificateChecksCompatibility
+import app.revanced.patches.music.annotations.MusicCompatibility
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.")
-@BypassCertificateChecksCompatibility
+@MusicCompatibility
@Version("0.0.1")
class BypassCertificateChecksPatch : BytecodePatch(
- listOf(
- CheckCertificateFingerprint
- )
+ listOf(CheckCertificateFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
CheckCertificateFingerprint.result?.let { result ->
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt
deleted file mode 100644
index 8128a9af6..000000000
--- a/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.misc.microg.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility([Package("com.google.android.apps.youtube.music")])
-@Target(AnnotationTarget.CLASS)
-internal annotation class MusicMicroGPatchCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
index 7fca848f8..f34afb9b4 100644
--- a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
@@ -1,65 +1,65 @@
-package app.revanced.patches.music.misc.microg.patch.bytecode
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
-import app.revanced.patches.music.misc.microg.fingerprints.*
-import app.revanced.patches.music.misc.microg.patch.resource.MusicMicroGResourcePatch
-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([MusicMicroGResourcePatch::class])
-@Name("music-microg-support")
-@Description("Allows YouTube Music ReVanced to run without root and under a different package name.")
-@MusicMicroGPatchCompatibility
-@Version("0.0.2")
-class MusicMicroGBytecodePatch : BytecodePatch(
- listOf(
- ServiceCheckFingerprint,
- GooglePlayUtilityFingerprint,
- CastDynamiteModuleFingerprint,
- CastDynamiteModuleV2Fingerprint,
- CastContextFetchFingerprint,
- PrimeFingerprint,
- )
-) {
- // NOTE: the previous patch also replaced the following strings, but it seems like they are not needed:
- // - "com.google.android.gms.chimera.GmsIntentOperationService",
- // - "com.google.android.gms.phenotype.internal.IPhenotypeCallbacks",
- // - "com.google.android.gms.phenotype.internal.IPhenotypeService",
- // - "com.google.android.gms.phenotype.PACKAGE_NAME",
- // - "com.google.android.gms.phenotype.UPDATE",
- // - "com.google.android.gms.phenotype",
- override fun execute(context: BytecodeContext) =
- // apply common microG patch
- MicroGBytecodeHelper.patchBytecode(
- context,
- arrayOf(
- MicroGBytecodeHelper.packageNameTransform(
- Constants.PACKAGE_NAME,
- Constants.REVANCED_PACKAGE_NAME
- )
- ),
- MicroGBytecodeHelper.PrimeMethodTransformationData(
- PrimeFingerprint,
- MUSIC_PACKAGE_NAME,
- REVANCED_MUSIC_PACKAGE_NAME
- ),
- listOf(
- ServiceCheckFingerprint,
- GooglePlayUtilityFingerprint,
- CastDynamiteModuleFingerprint,
- CastDynamiteModuleV2Fingerprint,
- CastContextFetchFingerprint
- )
- ).let { PatchResultSuccess() }
-}
+package app.revanced.patches.music.misc.microg.patch.bytecode
+
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.music.annotations.MusicCompatibility
+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
+@Version("0.0.2")
+class MicroGBytecodePatch : BytecodePatch(
+ listOf(
+ ServiceCheckFingerprint,
+ GooglePlayUtilityFingerprint,
+ CastDynamiteModuleFingerprint,
+ CastDynamiteModuleV2Fingerprint,
+ CastContextFetchFingerprint,
+ PrimeFingerprint,
+ )
+) {
+ // NOTE: the previous patch also replaced the following strings, but it seems like they are not needed:
+ // - "com.google.android.gms.chimera.GmsIntentOperationService",
+ // - "com.google.android.gms.phenotype.internal.IPhenotypeCallbacks",
+ // - "com.google.android.gms.phenotype.internal.IPhenotypeService",
+ // - "com.google.android.gms.phenotype.PACKAGE_NAME",
+ // - "com.google.android.gms.phenotype.UPDATE",
+ // - "com.google.android.gms.phenotype",
+ override fun execute(context: BytecodeContext) =
+ // apply common microG patch
+ MicroGBytecodeHelper.patchBytecode(
+ context,
+ arrayOf(
+ MicroGBytecodeHelper.packageNameTransform(
+ Constants.PACKAGE_NAME,
+ Constants.REVANCED_PACKAGE_NAME
+ )
+ ),
+ MicroGBytecodeHelper.PrimeMethodTransformationData(
+ PrimeFingerprint,
+ MUSIC_PACKAGE_NAME,
+ REVANCED_MUSIC_PACKAGE_NAME
+ ),
+ listOf(
+ ServiceCheckFingerprint,
+ GooglePlayUtilityFingerprint,
+ CastDynamiteModuleFingerprint,
+ CastDynamiteModuleV2Fingerprint,
+ CastContextFetchFingerprint
+ )
+ ).let { PatchResultSuccess() }
+}
diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MicroGResourcePatch.kt
similarity index 88%
rename from src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MicroGResourcePatch.kt
index 19daba368..0644160e8 100644
--- a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MicroGResourcePatch.kt
@@ -7,7 +7,7 @@ import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
+import app.revanced.patches.music.annotations.MusicCompatibility
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
@@ -16,11 +16,11 @@ import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_S
import app.revanced.util.microg.MicroGManifestHelper
import app.revanced.util.microg.MicroGResourceHelper
-@Name("music-microg-resource-patch")
+@Name("microg-resource-patch")
@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.")
-@MusicMicroGPatchCompatibility
+@MusicCompatibility
@Version("0.0.2")
-class MusicMicroGResourcePatch : ResourcePatch {
+class MicroGResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
// update manifest
MicroGResourceHelper.patchManifest(
diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt
deleted file mode 100644
index 31dd505f3..000000000
--- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.music.premium.backgroundplay.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 BackgroundPlayCompatibility
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
index c1f39c9b5..868175eaa 100644
--- 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
@@ -9,18 +9,16 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility
+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.")
-@BackgroundPlayCompatibility
+@MusicCompatibility
@Version("0.0.1")
class BackgroundPlayPatch : BytecodePatch(
- listOf(
- BackgroundPlaybackDisableFingerprint
- )
+ listOf(BackgroundPlaybackDisableFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
BackgroundPlaybackDisableFingerprint.result!!.mutableMethod.addInstructions(
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractChangeOAuthClientIdPatch.kt
new file mode 100644
index 000000000..27bc8842a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractChangeOAuthClientIdPatch.kt
@@ -0,0 +1,56 @@
+package app.revanced.patches.reddit.customclients
+
+import android.os.Environment
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patcher.patch.*
+import java.io.File
+
+abstract class AbstractChangeOAuthClientIdPatch(
+ private val redirectUri: String,
+ private val options: ChangeOAuthClientIdOptionsContainer,
+ private val fingerprint: MethodFingerprint,
+) : BytecodePatch(listOf(fingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ if (options.clientId == null) {
+ // Test if on Android
+ try {
+ Class.forName("android.os.Environment")
+ } catch (e: ClassNotFoundException) {
+ return PatchResultError("No client ID provided")
+ }
+
+ File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also {
+ if (it.exists()) return@also
+
+ val error = """
+ In order to use this patch, you need to provide a client ID.
+ You can do this 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".
+ """.trimIndent()
+
+ return PatchResultError(error)
+ }.let { options.clientId = it.readText().trim() }
+ }
+
+ return fingerprint.patch(context)
+ }
+
+ abstract fun MethodFingerprint.patch(context: BytecodeContext): PatchResult
+
+ companion object Options {
+ open class ChangeOAuthClientIdOptionsContainer : OptionsContainer() {
+ var clientId by option(
+ PatchOption.StringOption(
+ "client-id",
+ null,
+ "OAuth client ID",
+ "The Reddit OAuth client ID."
+ )
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/GetClientIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/GetClientIdFingerprint.kt
new file mode 100644
index 000000000..c8ffa4bae
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/GetClientIdFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object GetClientIdFingerprint : MethodFingerprint(
+ customFingerprint = custom@{ methodDef, classDef ->
+ if (!classDef.type.endsWith("Credentials;")) return@custom false
+
+ methodDef.name == "getClientId"
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/ChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/ChangeOAuthClientIdPatch.kt
new file mode 100644
index 000000000..1f8004d1d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/ChangeOAuthClientIdPatch.kt
@@ -0,0 +1,37 @@
+package app.revanced.patches.reddit.customclients.boostforreddit.api.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.*
+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.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
+import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
+
+@Patch
+@Name("change-oauth-client-id")
+@Description("Changes the OAuth client ID in Boost for Reddit.")
+@Compatibility([Package("com.rubenmayayo.reddit")])
+@Version("0.0.1")
+class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
+ "http://rubenmayayo.com",
+ Options,
+ GetClientIdFingerprint
+) {
+ override fun MethodFingerprint.patch(context: BytecodeContext): PatchResult {
+ result?.mutableMethod?.addInstructions(
+ 0,
+ """
+ const-string v0, "$clientId"
+ return-object v0
+ """
+ ) ?: return toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+ companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
+}
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
index ff01b38cf..40c98bc2b 100644
--- a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.syncforreddit.ads.fingerprints
+package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt
index 2b15bf39f..e743602f2 100644
--- a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.syncforreddit.ads.patch
+package app.revanced.patches.reddit.customclients.syncforreddit.ads.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.*
@@ -9,8 +9,8 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
-import app.revanced.patches.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
+import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
+import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
@Patch
@Name("disable-ads")
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt
similarity index 69%
rename from src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt
index 8eceddfbf..0e517e1d3 100644
--- a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.syncforreddit.api.fingerprints
+package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt
similarity index 65%
rename from src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt
index a07208726..0d4fee94b 100644
--- a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.syncforreddit.api.fingerprints
+package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt
new file mode 100644
index 000000000..e7ceb004d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt
@@ -0,0 +1,68 @@
+package app.revanced.patches.reddit.customclients.syncforreddit.api.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.*
+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
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
+import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
+import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
+import org.jf.dexlib2.iface.reference.StringReference
+import java.util.*
+
+@Patch
+@Name("change-oauth-client-id")
+@Description("Changes the OAuth client ID.")
+@Compatibility([Package("com.laurencedawson.reddit_sync"), Package("com.laurencedawson.reddit_sync.pro")])
+@Version("0.0.1")
+class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
+ "http://redditsync/auth",
+ Options,
+ GetAuthorizationStringFingerprint,
+) {
+ override fun MethodFingerprint.patch(context: BytecodeContext): PatchResult {
+ result?.also { result ->
+ GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply {
+ val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
+ addInstructions(
+ 0,
+ """
+ const-string v0, "Basic $auth"
+ return-object v0
+ """
+ )
+ } ?: return GetBearerTokenFingerprint.toErrorResult()
+ }?.let {
+ val occurrenceIndex = it.scanResult.stringsScanResult!!.matches.first().index
+
+ it.mutableMethod.apply {
+ val authorizationStringInstruction = getInstruction(occurrenceIndex)
+ val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA
+ val reference = authorizationStringInstruction.reference as StringReference
+
+ val newAuthorizationUrl = reference.string.replace(
+ "client_id=.*?&".toRegex(),
+ "client_id=$clientId&"
+ )
+
+ replaceInstruction(
+ occurrenceIndex,
+ "const-string v$targetRegister, \"$newAuthorizationUrl\""
+ )
+ }
+ } ?: return toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+ companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
+}
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt
similarity index 100%
rename from src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
similarity index 92%
rename from src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
index feb02a06c..b0e63f681 100644
--- a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.syncforreddit.detection.piracy.patch
+package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt
deleted file mode 100644
index 2e81de61b..000000000
--- a/src/main/kotlin/app/revanced/patches/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-package app.revanced.patches.syncforreddit.api.patch
-
-import android.os.Environment
-import app.revanced.patcher.annotation.*
-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.*
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
-import app.revanced.patches.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
-import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
-import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-import org.jf.dexlib2.iface.reference.StringReference
-import java.io.File
-import java.util.*
-
-@Patch
-@Name("change-oauth-client-id")
-@Description("Changes the OAuth client ID.")
-@Compatibility(
- [
- Package("com.laurencedawson.reddit_sync"),
- Package("com.laurencedawson.reddit_sync.pro")
- ]
-)
-@Version("0.0.1")
-class ChangeOAuthClientIdPatch : BytecodePatch(
- listOf(GetAuthorizationStringFingerprint)
-) {
- override fun execute(context: BytecodeContext): PatchResult {
- if (clientId == null) {
- // Test if on Android
- try {
- Class.forName("android.os.Environment")
- } catch (e: ClassNotFoundException) {
- return PatchResultError("No client ID provided")
- }
-
- File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also {
- if (it.exists()) return@also
-
- val error = """
- In order to use this patch, you need to provide a client ID.
- You can do this 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 "http://redditsync/auth"
- """.trimIndent()
-
- return PatchResultError(error)
- }.let { clientId = it.readText().trim() }
- }
-
- GetAuthorizationStringFingerprint.result?.also { result ->
- GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply {
- val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
- addInstructions(
- 0,
- """
- const-string v0, "Basic $auth"
- return-object v0
- """
- )
- } ?: return PatchResultError("Could not find required method to patch.")
- }?.let {
- val occurrenceIndex = it.scanResult.stringsScanResult!!.matches.first().index
-
- it.mutableMethod.apply {
- val authorizationStringInstruction = getInstruction(occurrenceIndex)
- val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA
- val reference = authorizationStringInstruction.reference as StringReference
-
- val newAuthorizationUrl = reference.string.replace(
- "client_id=.*?&".toRegex(),
- "client_id=${clientId!!}&"
- )
-
- replaceInstruction(
- occurrenceIndex,
- "const-string v$targetRegister, \"$newAuthorizationUrl\""
- )
- }
- } ?: return PatchResultError("Could not find required method to patch.")
- return PatchResultSuccess()
- }
-
- companion object : OptionsContainer() {
- var clientId by option(
- PatchOption.StringOption(
- "client-id",
- null,
- "OAuth client ID",
- "The client ID to use for OAuth."
- )
- )
- }
-}
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
index 042c4c1d5..b0b80ec49 100644
--- 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
@@ -3,20 +3,7 @@ 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(
- "14.3.3",
- "14.4.0",
- "14.5.0",
- "14.5.2",
- "14.6.0",
- "14.6.1"
- )
- )
- ]
-)
+@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/annotations/EmbeddedAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/annotations/EmbeddedAdsCompatibility.kt
index 6f86e6411..95a60c5b4 100644
--- 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
@@ -3,20 +3,7 @@ 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(
- "14.3.3",
- "14.4.0",
- "14.5.0",
- "14.5.2",
- "14.6.0",
- "14.6.1"
- )
- )
- ]
-)
+@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1"))])
@Target(AnnotationTarget.CLASS)
internal annotation class EmbeddedAdsCompatibility
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
index 8bda487db..a8d1f4582 100644
--- 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
@@ -3,20 +3,7 @@ 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(
- "14.3.3",
- "14.4.0",
- "14.5.0",
- "14.5.2",
- "14.6.0",
- "14.6.1"
- )
- )
- ]
-)
+@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1"))])
@Target(AnnotationTarget.CLASS)
internal annotation class VideoAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt
index 31ea27485..c85dec197 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt
@@ -1,15 +1,12 @@
package app.revanced.patches.twitch.ad.video.fingerprints
-import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
object CheckAdEligibilityLambdaFingerprint : MethodFingerprint(
- "L",
- AccessFlags.PRIVATE or AccessFlags.FINAL or AccessFlags.STATIC,
- listOf("L", "L", "L"),
+ returnType = "Lio/reactivex/Single;",
+ parameters = listOf("L"),
customFingerprint = { method, _ ->
- method.definingClass.endsWith("AdEligibilityFetcher;") &&
- method.name.contains("shouldRequestAd")
+ method.definingClass.endsWith("/AdEligibilityFetcher;")
+ && method.name == "shouldRequestAd"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt
index f64ba6ffe..166e63b74 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt
@@ -1,10 +1,11 @@
package app.revanced.patches.twitch.ad.video.fingerprints
-
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ContentConfigShowAdsFingerprint : MethodFingerprint(
+ returnType = "Z",
+ parameters = listOf(),
customFingerprint = { method, _ ->
- method.definingClass.endsWith("ContentConfigData;") && method.name == "getShowAds"
+ method.definingClass.endsWith("/ContentConfigData;") && method.name == "getShowAds"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt
index 0f7b2454c..8987b2193 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt
@@ -3,6 +3,8 @@ package app.revanced.patches.twitch.ad.video.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object GetReadyToShowAdFingerprint : MethodFingerprint(
+ returnType = "Ltv/twitch/android/core/mvp/presenter/StateAndAction;",
+ parameters = listOf("L", "L"),
customFingerprint = { method, _ ->
method.definingClass.endsWith("/StreamDisplayAdsPresenter;") && method.name == "getReadyToShowAdOrAbort"
}
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/patch/VideoAdsPatch.kt
index 11096a21d..50bd3e1b3 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.twitch.ad.video.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -86,7 +87,7 @@ class VideoAdsPatch : AbstractAdPatch(
)
// Pretend our player is ineligible for all ads
- with(CheckAdEligibilityLambdaFingerprint.result!!) {
+ CheckAdEligibilityLambdaFingerprint.result?.apply {
mutableMethod.addInstructionsWithLabels(
0,
"""
@@ -98,9 +99,9 @@ class VideoAdsPatch : AbstractAdPatch(
""",
ExternalLabel(skipLabelName, mutableMethod.getInstruction(0))
)
- }
+ } ?: return CheckAdEligibilityLambdaFingerprint.toErrorResult()
- with(GetReadyToShowAdFingerprint.result!!) {
+ GetReadyToShowAdFingerprint.result?.apply {
val adFormatDeclined = "Ltv/twitch/android/shared/display/ads/theatre/StreamDisplayAdsPresenter\$Action\$AdFormatDeclined;"
mutableMethod.addInstructionsWithLabels(
0,
@@ -113,10 +114,10 @@ class VideoAdsPatch : AbstractAdPatch(
""",
ExternalLabel(skipLabelName, mutableMethod.getInstruction(0))
)
- }
+ } ?: return GetReadyToShowAdFingerprint.toErrorResult()
// Spoof showAds JSON field
- with(ContentConfigShowAdsFingerprint.result!!) {
+ ContentConfigShowAdsFingerprint.result?.apply {
mutableMethod.addInstructions(0, """
${createConditionInstructions()}
const/4 v0, 0
@@ -124,7 +125,7 @@ class VideoAdsPatch : AbstractAdPatch(
return v0
"""
)
- }
+ } ?: return ContentConfigShowAdsFingerprint.toErrorResult()
SettingsPatch.PreferenceScreen.ADS.CLIENT_SIDE.addPreferences(
SwitchPreference(
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
index 1a54cf917..7e864e55a 100644
--- 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
@@ -3,7 +3,7 @@ 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")])
+@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1"))])
@Target(AnnotationTarget.CLASS)
internal annotation class ShowDeletedMessagesCompatibility
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/patch/ShowDeletedMessagesPatch.kt
index 7d3b841c6..f5f713954 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.twitch.chat.antidelete.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -44,7 +45,7 @@ class ShowDeletedMessagesPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
// Spoiler mode: Force set hasModAccess member to true in constructor
- DeletedMessageClickableSpanCtorFingerprint.result!!.mutableMethod.apply {
+ DeletedMessageClickableSpanCtorFingerprint.result?.mutableMethod?.apply {
addInstructionsWithLabels(
implementation!!.instructions.lastIndex, /* place in front of return-void */
"""
@@ -54,14 +55,14 @@ class ShowDeletedMessagesPatch : BytecodePatch(
""",
ExternalLabel("no_spoiler", getInstruction(implementation!!.instructions.lastIndex))
)
- }
+ } ?: return DeletedMessageClickableSpanCtorFingerprint.toErrorResult()
// Spoiler mode: Disable setHasModAccess setter
- SetHasModAccessFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
-
+ SetHasModAccessFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
+ ?: return SetHasModAccessFingerprint.toErrorResult()
// Cross-out mode: Reformat span of deleted message
- ChatUtilCreateDeletedSpanFingerprint.result!!.mutableMethod.apply {
+ ChatUtilCreateDeletedSpanFingerprint.result?.mutableMethod?.apply {
addInstructionsWithLabels(
0,
"""
@@ -72,7 +73,7 @@ class ShowDeletedMessagesPatch : BytecodePatch(
""",
ExternalLabel("no_reformat", getInstruction(0))
)
- }
+ } ?: return ChatUtilCreateDeletedSpanFingerprint.toErrorResult()
SettingsPatch.PreferenceScreen.CHAT.GENERAL.addPreferences(
ListPreference(
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
index 30473cf3a..2efc511bf 100644
--- 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
@@ -3,6 +3,6 @@ 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")])
+@Compatibility([Package("tv.twitch.android.app", arrayOf("15.4.1"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoClaimChannelPointsCompatibility
\ No newline at end of file
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/patch/AutoClaimChannelPointsPatch.kt
index e77b2b580..4859299e6 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt
@@ -65,6 +65,7 @@ class AutoClaimChannelPointPatch : BytecodePatch(
ExternalLabel("auto_claim", getInstruction(lastIndex))
)
} ?: return CommunityPointsButtonViewDelegateFingerprint.toErrorResult()
+
return PatchResultSuccess()
}
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt
index 145bc06be..efb6effd1 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt
@@ -1,10 +1,9 @@
package app.revanced.patches.twitch.debug.fingerprints
-
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsDebugConfigEnabledFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
- methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "isDebugConfigEnabled"
+ methodDef.definingClass.endsWith("/BuildConfigUtil;") && methodDef.name == "isDebugConfigEnabled"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt
index ab50280a5..99894998a 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt
@@ -1,10 +1,9 @@
package app.revanced.patches.twitch.debug.fingerprints
-
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsOmVerificationEnabledFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
- methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "isOmVerificationEnabled"
+ methodDef.definingClass.endsWith("/BuildConfigUtil;") && methodDef.name == "isOmVerificationEnabled"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt
index e9a77cc3b..9c91695e0 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt
@@ -1,10 +1,9 @@
package app.revanced.patches.twitch.debug.fingerprints
-
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ShouldShowDebugOptionsFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
- methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "shouldShowDebugOptions"
+ methodDef.definingClass.endsWith("/BuildConfigUtil;") && methodDef.name == "shouldShowDebugOptions"
}
)
\ 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/patch/DebugModePatch.kt
index 749c07363..431687948 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.twitch.debug.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -38,18 +39,16 @@ class DebugModePatch : BytecodePatch(
IsOmVerificationEnabledFingerprint,
ShouldShowDebugOptionsFingerprint
).forEach {
- with(it.result!!) {
- with(mutableMethod) {
- addInstructions(
- 0,
- """
- invoke-static {}, Lapp/revanced/twitch/patches/DebugModePatch;->isDebugModeEnabled()Z
- move-result v0
- return v0
- """
- )
- }
- }
+ it.result?.mutableMethod?.apply {
+ addInstructions(
+ 0,
+ """
+ invoke-static {}, Lapp/revanced/twitch/patches/DebugModePatch;->isDebugModeEnabled()Z
+ move-result v0
+ return v0
+ """
+ )
+ } ?: return it.toErrorResult()
}
SettingsPatch.PreferenceScreen.MISC.OTHER.addPreferences(
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/bytecode/patch/SettingsPatch.kt
index ef114798b..767b5c8ec 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/bytecode/patch/SettingsPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.twitch.misc.settings.bytecode.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -45,7 +46,7 @@ class SettingsPatch : BytecodePatch(
) {
override fun execute(context: BytecodeContext): PatchResult {
// Hook onCreate to handle fragment creation
- with(SettingsActivityOnCreateFingerprint.result!!) {
+ SettingsActivityOnCreateFingerprint.result?.apply {
val insertIndex = mutableMethod.implementation!!.instructions.size - 2
mutableMethod.addInstructionsWithLabels(
insertIndex,
@@ -57,20 +58,20 @@ class SettingsPatch : BytecodePatch(
""",
ExternalLabel("no_rv_settings_init", mutableMethod.getInstruction(insertIndex))
)
- }
+ } ?: return SettingsActivityOnCreateFingerprint.toErrorResult()
// Create new menu item for settings menu
- with(SettingsMenuItemEnumFingerprint.result!!) {
+ SettingsMenuItemEnumFingerprint.result?.apply {
injectMenuItem(
REVANCED_SETTINGS_MENU_ITEM_NAME,
REVANCED_SETTINGS_MENU_ITEM_ID,
REVANCED_SETTINGS_MENU_ITEM_TITLE_RES,
REVANCED_SETTINGS_MENU_ITEM_ICON_RES
)
- }
+ } ?: return SettingsMenuItemEnumFingerprint.toErrorResult()
// Intercept settings menu creation and add new menu item
- with(MenuGroupsUpdatedFingerprint.result!!) {
+ MenuGroupsUpdatedFingerprint.result?.apply {
mutableMethod.addInstructions(
0,
"""
@@ -79,10 +80,10 @@ class SettingsPatch : BytecodePatch(
move-result-object p1
"""
)
- }
+ } ?: return MenuGroupsUpdatedFingerprint.toErrorResult()
// Intercept onclick events for the settings menu
- with(MenuGroupsOnClickFingerprint.result!!) {
+ MenuGroupsOnClickFingerprint.result?.apply {
val insertIndex = 0
mutableMethod.addInstructionsWithLabels(
insertIndex,
@@ -96,7 +97,7 @@ class SettingsPatch : BytecodePatch(
""",
ExternalLabel("no_rv_settings_onclick", mutableMethod.getInstruction(insertIndex))
)
- }
+ } ?: return MenuGroupsOnClickFingerprint.toErrorResult()
addString("revanced_settings", "ReVanced Settings", false)
addString("revanced_reboot_message", "Twitch needs to restart to apply your changes. Restart now?", false)
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/resource/patch/HideAdsResourcePatch.kt
index 22d812689..f039603d5 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/resource/patch/HideAdsResourcePatch.kt
@@ -7,14 +7,15 @@ import app.revanced.patcher.patch.PatchResultSuccess
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.*
+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
@DependsOn(
- dependencies = [
+ [
LithoFilterPatch::class,
SettingsPatch::class,
ResourceMappingPatch::class
@@ -23,185 +24,7 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.P
@HideAdsCompatibility
@Version("0.0.1")
class HideAdsResourcePatch : ResourcePatch {
-
override fun execute(context: ResourceContext): PatchResult {
- PreferenceScreen.LAYOUT.addPreferences(
- SwitchPreference(
- "revanced_hide_gray_separator",
- StringResource("revanced_hide_gray_separator_title", "Hide gray separator"),
- 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_channel_guidelines",
- StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
- StringResource(
- "revanced_hide_channel_guidelines_summary_on",
- "Channel guidelines are hidden"
- ),
- StringResource(
- "revanced_hide_channel_guidelines_summary_off",
- "Channel guidelines are shown"
- )
- ),
- SwitchPreference(
- "revanced_hide_chapter_teaser",
- StringResource(
- "revanced_hide_chapter_teaser_title",
- "Hide chapter teaser under videos"
- ),
- StringResource(
- "revanced_hide_chapter_teaser_summary_on",
- "Chapter teasers are hidden"
- ),
- StringResource(
- "revanced_hide_chapter_teaser_summary_off",
- "Chapter teasers are shown"
- )
- ),
- SwitchPreference(
- "revanced_hide_merchandise_banners",
- StringResource("revanced_hide_merchandise_banners_title", "Hide merchandise banners"),
- StringResource("revanced_hide_merchandise_banners_summary_on", "Merchandise banners are hidden"),
- StringResource("revanced_hide_merchandise_banners_summary_off", "Merchandise banners are shown")
- ),
- SwitchPreference(
- "revanced_hide_community_posts",
- StringResource("revanced_hide_community_posts_title", "Hide community posts"),
- StringResource("revanced_hide_community_posts_summary_on", "Community posts are hidden"),
- StringResource("revanced_hide_community_posts_summary_off", "Community posts are shown")
- ),
- SwitchPreference(
- "revanced_hide_compact_banner",
- StringResource("revanced_hide_compact_banner_title", "Hide compact banners"),
- StringResource("revanced_hide_compact_banner_summary_on", "Compact banners are hidden"),
- StringResource("revanced_hide_compact_banner_summary_off", "Compact banners are shown")
- ),
- SwitchPreference(
- "revanced_hide_products_banner",
- StringResource("revanced_hide_products_banner_title", "Hide banner to view products"),
- StringResource("revanced_hide_products_banner_summary_on", "Banner is hidden"),
- StringResource("revanced_hide_products_banner_summary_off", "Banner is shown")
- ),
- SwitchPreference(
- "revanced_hide_web_search_results",
- StringResource("revanced_hide_web_search_results_title", "Hide web search results"),
- StringResource("revanced_hide_web_search_results_summary_on", "Web search results are hidden"),
- StringResource("revanced_hide_web_search_results_summary_off", "Web search results are shown")
- ),
- SwitchPreference(
- "revanced_hide_movies_section",
- StringResource("revanced_hide_movies_section_title", "Hide movies section"),
- StringResource("revanced_hide_movies_section_summary_on", "Movies section is hidden"),
- StringResource("revanced_hide_movies_section_summary_off", "Movies section is shown")
- ),
- SwitchPreference(
- "revanced_hide_feed_survey",
- StringResource("revanced_hide_feed_survey_title", "Hide feed surveys"),
- StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
- StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
- ),
- SwitchPreference(
- "revanced_hide_community_guidelines",
- StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
- StringResource(
- "revanced_hide_community_guidelines_summary_on",
- "Community guidelines are hidden"
- ),
- StringResource(
- "revanced_hide_community_guidelines_summary_off",
- "Community guidelines are shown"
- )
- ),
- SwitchPreference(
- "revanced_hide_subscribers_community_guidelines",
- StringResource(
- "revanced_hide_subscribers_community_guidelines_title",
- "Hide subscribers community guidelines"
- ),
- StringResource(
- "revanced_hide_subscribers_community_guidelines_summary_on",
- "Subscribers community guidelines are hidden"
- ),
- StringResource(
- "revanced_hide_subscribers_community_guidelines_summary_off",
- "Subscribers community guidelines are shown"
- )
- ),
- SwitchPreference(
- "revanced_hide_channel_member_shelf",
- StringResource("revanced_hide_channel_member_shelf_title", "Hide channel member shelf"),
- StringResource(
- "revanced_hide_channel_member_shelf_summary_on",
- "Channel member shelf is hidden"
- ),
- StringResource(
- "revanced_hide_channel_member_shelf_summary_off",
- "Channel member shelf is shown"
- )
- ),
- SwitchPreference(
- "revanced_hide_emergency_box",
- StringResource("revanced_hide_emergency_box_title", "Hide emergency boxes"),
- StringResource("revanced_hide_emergency_box_summary_on", "Emergency boxes are hidden"),
- StringResource("revanced_hide_emergency_box_summary_off", "Emergency boxes are shown")
- ),
- SwitchPreference(
- "revanced_hide_info_panels",
- StringResource("revanced_hide_info_panels_title", "Hide info panels"),
- StringResource("revanced_hide_info_panels_summary_on", "Info panels are hidden"),
- StringResource("revanced_hide_info_panels_summary_off", "Info panels are shown")
- ),
- SwitchPreference(
- "revanced_hide_medical_panels",
- StringResource("revanced_hide_medical_panels_title", "Hide medical panels"),
- StringResource("revanced_hide_medical_panels_summary_on", "Medical panels are hidden"),
- StringResource("revanced_hide_medical_panels_summary_off", "Medical panels are shown")
- ),
- SwitchPreference(
- "revanced_hide_channel_bar",
- StringResource("revanced_hide_channel_bar_title", "Hide channel bar"),
- StringResource("revanced_hide_channel_bar_summary_on", "Channel bar is hidden"),
- StringResource("revanced_hide_channel_bar_summary_off", "Channel bar is shown")
- ),
- SwitchPreference(
- "revanced_hide_quick_actions",
- StringResource("revanced_hide_quick_actions_title", "Hide quick actions in fullscreen"),
- StringResource("revanced_hide_quick_actions_summary_on", "Quick actions are hidden"),
- StringResource("revanced_hide_quick_actions_summary_off", "Quick actions are shown")
- ),
- SwitchPreference(
- "revanced_hide_related_videos",
- StringResource("revanced_hide_related_videos_title", "Hide related videos in quick actions"),
- StringResource("revanced_hide_related_videos_summary_on", "Related videos are hidden"),
- StringResource("revanced_hide_related_videos_summary_off", "Related videos are shown")
- ),
- SwitchPreference(
- "revanced_hide_image_shelf",
- StringResource("revanced_hide_image_shelf", "Hide image shelf in search results"),
- 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"),
- StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
- StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
- ),
- SwitchPreference(
- "revanced_hide_mix_playlists",
- StringResource("revanced_hide_mix_playlists_title", "Hide mix playlists"),
- StringResource("revanced_hide_mix_playlists_summary_on", "Mix playlists are hidden"),
- StringResource("revanced_hide_mix_playlists_summary_off", "Mix playlists are shown")
- ),
- )
-
PreferenceScreen.ADS.addPreferences(
SwitchPreference(
"revanced_hide_general_ads",
@@ -227,38 +50,28 @@ class HideAdsResourcePatch : ResourcePatch {
StringResource("revanced_hide_self_sponsor_ads_summary_on", "Self sponsored cards are hidden"),
StringResource("revanced_hide_self_sponsor_ads_summary_off", "Self sponsored cards are shown")
),
- PreferenceScreen(
- "revanced_custom_filter_preference_screen",
- StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"),
- listOf(
- SwitchPreference(
- "revanced_custom_filter",
- StringResource(
- "revanced_custom_filter_title",
- "Enable custom filter"
- ),
- StringResource(
- "revanced_custom_filter_summary_on",
- "Custom filter is enabled"
- ),
- StringResource(
- "revanced_custom_filter_summary_off",
- "Custom filter is disabled"
- )
- ),
- // TODO: This should be a dynamic ListPreference, which does not exist yet
- TextPreference(
- "revanced_custom_filter_strings",
- StringResource("revanced_custom_filter_strings_title", "Custom filter"),
- StringResource(
- "revanced_custom_filter_strings_summary",
- "Filter components by their name separated by a comma"
- )
- )
- )
+ SwitchPreference(
+ "revanced_hide_products_banner",
+ StringResource("revanced_hide_products_banner_title", "Hide banner to view products"),
+ StringResource("revanced_hide_products_banner_summary_on", "Banner is hidden"),
+ StringResource("revanced_hide_products_banner_summary_off", "Banner is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_web_search_results",
+ StringResource("revanced_hide_web_search_results_title", "Hide web search results"),
+ StringResource("revanced_hide_web_search_results_summary_on", "Web search results are hidden"),
+ StringResource("revanced_hide_web_search_results_summary_off", "Web search results are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_merchandise_banners",
+ StringResource("revanced_hide_merchandise_banners_title", "Hide merchandise banners"),
+ StringResource("revanced_hide_merchandise_banners_summary_on", "Merchandise banners are hidden"),
+ StringResource("revanced_hide_merchandise_banners_summary_off", "Merchandise banners are shown")
)
)
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+
adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
return PatchResultSuccess()
@@ -266,5 +79,8 @@ class HideAdsResourcePatch : ResourcePatch {
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/layout/buttons/action/patch/HideButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt
index 073d9b05a..cbc27dd2c 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/patch/HideButtonsPatch.kt
@@ -66,6 +66,14 @@ class HideButtonsPatch : ResourcePatch {
StringResource("revanced_hide_buttons_preference_screen_summary", "Hide or show buttons under videos")
)
)
+
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+
return PatchResultSuccess()
}
+
+ 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/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt
index c02d16111..92ee6bb93 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/bytecode/patch/AlbumCardsPatch.kt
@@ -42,7 +42,7 @@ class AlbumCardsPatch : BytecodePatch(
"invoke-static {v$albumCardViewRegister}, " +
"Lapp/revanced/integrations/patches/HideAlbumCardsPatch;" +
"->" +
- "hideAlbumCards(Landroid/view/View;)V"
+ "hideAlbumCard(Landroid/view/View;)V"
)
}
} ?: return AlbumCardsFingerprint.toErrorResult()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt
deleted file mode 100644
index b3245b815..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.artistcards.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"))])
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideArtistCardCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt
deleted file mode 100644
index e4921df9e..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.artistcards.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
-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.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.artistcards.annotations.HideArtistCardCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-
-@Patch
-@DependsOn([ResourceMappingPatch::class, LithoFilterPatch::class])
-@Name("hide-artist-card")
-@Description("Hides the artist card below the searchbar.")
-@HideArtistCardCompatibility
-@Version("0.0.1")
-class HideArtistCardsPatch : ResourcePatch {
- override fun execute(context: ResourceContext): PatchResult {
- SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
- SwitchPreference(
- "revanced_hide_artist_cards",
- StringResource("revanced_hide_artist_cards_title", "Hide artist cards"),
- StringResource("revanced_hide_artist_cards_on", "Artist cards is hidden"),
- StringResource("revanced_hide_artist_cards_off", "Artist cards is shown")
- ),
- )
- return PatchResultSuccess()
- }
-}
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/patch/CommentsPatch.kt
index 5ebb44d14..e0e41e361 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/patch/CommentsPatch.kt
@@ -9,21 +9,23 @@ import app.revanced.patcher.patch.PatchResultSuccess
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.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
@Patch
@Name("comments")
@Description("Hides components related to comments.")
@HideCommentsCompatibility
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@DependsOn([SettingsPatch::class, LithoFilterPatch::class])
@Version("0.0.1")
class CommentsPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
"revanced_comments_preference_screen",
@@ -48,4 +50,8 @@ class CommentsPatch : ResourcePatch {
return PatchResultSuccess()
}
-}
\ No newline at end of file
+
+ private companion object {
+ const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/CommentsFilter;"
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/annotations/HideLayoutComponentsCompatibility.kt
similarity index 63%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/annotations/HideLayoutComponentsCompatibility.kt
index 7d483d276..926b97920 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/annotations/HideLayoutComponentsCompatibility.kt
@@ -1,9 +1,9 @@
-package app.revanced.patches.youtube.misc.litho.filter.annotation
+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.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
-internal annotation class LithoFilterCompatibility
+internal annotation class HideLayoutComponentsCompatibility
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/patch/HideLayoutComponentsPatch.kt
new file mode 100644
index 000000000..203d22ca5
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/patch/HideLayoutComponentsPatch.kt
@@ -0,0 +1,247 @@
+package app.revanced.patches.youtube.layout.hide.general.patch
+
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+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.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.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
+
+@Patch
+@Name("hide-layout-components")
+@Description("Hides general layout components.")
+@DependsOn([LithoFilterPatch::class, SettingsPatch::class])
+@HideLayoutComponentsCompatibility
+@Version("0.0.1")
+class HideLayoutComponentsPatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ PreferenceScreen.LAYOUT.addPreferences(
+ SwitchPreference(
+ "revanced_hide_gray_separator",
+ StringResource("revanced_hide_gray_separator_title", "Hide gray separator"),
+ 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_channel_guidelines",
+ StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
+ StringResource(
+ "revanced_hide_channel_guidelines_summary_on",
+ "Channel guidelines are hidden"
+ ),
+ StringResource(
+ "revanced_hide_channel_guidelines_summary_off",
+ "Channel guidelines are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_expandable_chip",
+ StringResource(
+ "revanced_hide_expandable_chip_title",
+ "Hide the expandable chip under videos"
+ ),
+ StringResource(
+ "revanced_hide_expandable_chip_summary_on",
+ "Expandable chips are hidden"
+ ),
+ StringResource(
+ "revanced_hide_expandable_chip_summary_off",
+ "Expandable chips are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_chapters",
+ StringResource(
+ "revanced_hide_chapters_title",
+ "Hide chapters in the video description"
+ ),
+ StringResource(
+ "revanced_hide_chapters_summary_on",
+ "Chapters are hidden"
+ ),
+ StringResource(
+ "revanced_hide_chapters_summary_off",
+ "Chapters are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_community_posts",
+ StringResource("revanced_hide_community_posts_title", "Hide community posts"),
+ StringResource("revanced_hide_community_posts_summary_on", "Community posts are hidden"),
+ StringResource("revanced_hide_community_posts_summary_off", "Community posts are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_compact_banner",
+ StringResource("revanced_hide_compact_banner_title", "Hide compact banners"),
+ StringResource("revanced_hide_compact_banner_summary_on", "Compact banners are hidden"),
+ StringResource("revanced_hide_compact_banner_summary_off", "Compact banners are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_movies_section",
+ StringResource("revanced_hide_movies_section_title", "Hide movies section"),
+ StringResource("revanced_hide_movies_section_summary_on", "Movies section is hidden"),
+ StringResource("revanced_hide_movies_section_summary_off", "Movies section is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_feed_survey",
+ StringResource("revanced_hide_feed_survey_title", "Hide feed surveys"),
+ StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
+ StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_community_guidelines",
+ StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
+ StringResource(
+ "revanced_hide_community_guidelines_summary_on",
+ "Community guidelines are hidden"
+ ),
+ StringResource(
+ "revanced_hide_community_guidelines_summary_off",
+ "Community guidelines are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_subscribers_community_guidelines",
+ StringResource(
+ "revanced_hide_subscribers_community_guidelines_title",
+ "Hide subscribers community guidelines"
+ ),
+ StringResource(
+ "revanced_hide_subscribers_community_guidelines_summary_on",
+ "Subscribers community guidelines are hidden"
+ ),
+ StringResource(
+ "revanced_hide_subscribers_community_guidelines_summary_off",
+ "Subscribers community guidelines are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_channel_member_shelf",
+ StringResource("revanced_hide_channel_member_shelf_title", "Hide channel member shelf"),
+ StringResource(
+ "revanced_hide_channel_member_shelf_summary_on",
+ "Channel member shelf is hidden"
+ ),
+ StringResource(
+ "revanced_hide_channel_member_shelf_summary_off",
+ "Channel member shelf is shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_emergency_box",
+ StringResource("revanced_hide_emergency_box_title", "Hide emergency boxes"),
+ StringResource("revanced_hide_emergency_box_summary_on", "Emergency boxes are hidden"),
+ StringResource("revanced_hide_emergency_box_summary_off", "Emergency boxes are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_info_panels",
+ StringResource("revanced_hide_info_panels_title", "Hide info panels"),
+ StringResource("revanced_hide_info_panels_summary_on", "Info panels are hidden"),
+ StringResource("revanced_hide_info_panels_summary_off", "Info panels are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_medical_panels",
+ StringResource("revanced_hide_medical_panels_title", "Hide medical panels"),
+ StringResource("revanced_hide_medical_panels_summary_on", "Medical panels are hidden"),
+ StringResource("revanced_hide_medical_panels_summary_off", "Medical panels are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_channel_bar",
+ StringResource("revanced_hide_channel_bar_title", "Hide channel bar"),
+ StringResource("revanced_hide_channel_bar_summary_on", "Channel bar is hidden"),
+ StringResource("revanced_hide_channel_bar_summary_off", "Channel bar is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_quick_actions",
+ StringResource("revanced_hide_quick_actions_title", "Hide quick actions in fullscreen"),
+ StringResource("revanced_hide_quick_actions_summary_on", "Quick actions are hidden"),
+ StringResource("revanced_hide_quick_actions_summary_off", "Quick actions are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_related_videos",
+ StringResource("revanced_hide_related_videos_title", "Hide related videos in quick actions"),
+ StringResource("revanced_hide_related_videos_summary_on", "Related videos are hidden"),
+ StringResource("revanced_hide_related_videos_summary_off", "Related videos are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_image_shelf",
+ StringResource("revanced_hide_image_shelf", "Hide image shelf in search results"),
+ 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"),
+ StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
+ StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_mix_playlists",
+ StringResource("revanced_hide_mix_playlists_title", "Hide mix playlists"),
+ StringResource("revanced_hide_mix_playlists_summary_on", "Mix playlists are hidden"),
+ StringResource("revanced_hide_mix_playlists_summary_off", "Mix playlists are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_artist_cards",
+ StringResource("revanced_hide_artist_cards_title", "Hide artist cards"),
+ StringResource("revanced_hide_artist_cards_on", "Artist cards is hidden"),
+ StringResource("revanced_hide_artist_cards_off", "Artist cards is shown")
+ ),
+ app.revanced.patches.shared.settings.preference.impl.PreferenceScreen(
+ "revanced_custom_filter_preference_screen",
+ StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"),
+ listOf(
+ SwitchPreference(
+ "revanced_custom_filter",
+ StringResource(
+ "revanced_custom_filter_title",
+ "Enable custom filter"
+ ),
+ StringResource(
+ "revanced_custom_filter_summary_on",
+ "Custom filter is enabled"
+ ),
+ StringResource(
+ "revanced_custom_filter_summary_off",
+ "Custom filter is disabled"
+ )
+ ),
+ // TODO: This should be a dynamic ListPreference, which does not exist yet
+ TextPreference(
+ "revanced_custom_filter_strings",
+ StringResource("revanced_custom_filter_strings_title", "Custom filter"),
+ StringResource(
+ "revanced_custom_filter_strings_summary",
+ "Filter components by their name separated by a comma"
+ )
+ )
+ )
+ )
+ )
+
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+
+ return PatchResultSuccess()
+ }
+
+ 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/shorts/bytecode/patch/HideShortsComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt
index 91fe39b84..451512be5 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/bytecode/patch/HideShortsComponentsPatch.kt
@@ -49,6 +49,8 @@ class HideShortsComponentsPatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
+ LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
+
// region Hide the Shorts shelf.
ReelConstructorFingerprint.result?.let {
@@ -59,7 +61,7 @@ class HideShortsComponentsPatch : BytecodePatch(
injectHideViewCall(
insertIndex,
viewRegister,
- CLASS_DESCRIPTOR,
+ FILTER_CLASS_DESCRIPTOR,
"hideShortsShelf"
)
}
@@ -89,7 +91,7 @@ class HideShortsComponentsPatch : BytecodePatch(
val viewRegister = getInstruction(checkCastIndex).registerA
addInstruction(
checkCastIndex + 1,
- "sput-object v$viewRegister, $CLASS_DESCRIPTOR->pivotBar:" +
+ "sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->pivotBar:" +
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
)
}
@@ -102,7 +104,7 @@ class HideShortsComponentsPatch : BytecodePatch(
throw RenderBottomNavigationBarFingerprint.toErrorResult()
RenderBottomNavigationBarFingerprint.result!!.mutableMethod.apply {
- addInstruction(0, "invoke-static { }, $CLASS_DESCRIPTOR->hideNavigationBar()V")
+ addInstruction(0, "invoke-static { }, $FILTER_CLASS_DESCRIPTOR->hideNavigationBar()V")
}
} ?: return RenderBottomNavigationBarParentFingerprint.toErrorResult()
@@ -115,7 +117,7 @@ class HideShortsComponentsPatch : BytecodePatch(
addInstruction(
insertIndex,
- "invoke-static { v$viewRegister }, $CLASS_DESCRIPTOR->" +
+ "invoke-static { v$viewRegister }, $FILTER_CLASS_DESCRIPTOR->" +
"hideNavigationBar(Landroid/view/View;)Landroid/view/View;"
)
}
@@ -127,7 +129,7 @@ class HideShortsComponentsPatch : BytecodePatch(
}
private companion object {
- private const val CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
+ 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"),
@@ -139,7 +141,7 @@ class HideShortsComponentsPatch : BytecodePatch(
val setIdIndex = referencedIndex + 1
val viewRegister = method.getInstruction(setIdIndex).registerC
- method.injectHideViewCall(setIdIndex, viewRegister, CLASS_DESCRIPTOR, methodName)
+ method.injectHideViewCall(setIdIndex, viewRegister, FILTER_CLASS_DESCRIPTOR, methodName)
}
}
}
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/bytecode/patch/SponsorBlockBytecodePatch.kt
index f070dc325..3c0efa65b 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/bytecode/patch/SponsorBlockBytecodePatch.kt
@@ -42,7 +42,7 @@ import org.jf.dexlib2.iface.reference.StringReference
@Patch
@DependsOn(
- dependencies = [
+ [
IntegrationsPatch::class,
VideoIdPatch::class,
// Required to skip segments on time.
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/LithoFilterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/LithoFilterFingerprint.kt
new file mode 100644
index 000000000..0d3760725
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/LithoFilterFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.youtube.misc.litho.filter.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object LithoFilterFingerprint : MethodFingerprint(
+ customFingerprint = custom@{ method, classDef ->
+ if (method.name != "") return@custom false
+
+ classDef.type.endsWith("LithoFilterPatch;")
+ }
+)
\ 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/patch/LithoFilterPatch.kt
index a93e35b30..2b709072d 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/patch/LithoFilterPatch.kt
@@ -4,8 +4,11 @@ import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Version
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.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
@@ -14,30 +17,28 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ComponentContextParserFingerprint
-import app.revanced.patches.youtube.misc.litho.filter.fingerprints.EmptyComponentBuilderFingerprint
-import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ProtobufBufferFingerprint
-import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ReadComponentIdentifierFingerprint
+import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
+import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
+import java.io.Closeable
@DependsOn([IntegrationsPatch::class])
@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.")
-@LithoFilterCompatibility
@Version("0.0.1")
class LithoFilterPatch : BytecodePatch(
- listOf(ComponentContextParserFingerprint)
-) {
+ listOf(ComponentContextParserFingerprint, LithoFilterFingerprint)
+), Closeable {
override fun execute(context: BytecodeContext): PatchResult {
ComponentContextParserFingerprint.result?.also {
arrayOf(
- EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint, ProtobufBufferFingerprint
+ EmptyComponentBuilderFingerprint,
+ ReadComponentIdentifierFingerprint,
+ ProtobufBufferFingerprint
).forEach { fingerprint ->
- if (!fingerprint.resolve(context, it.mutableMethod, it.mutableClass))
- return fingerprint.toErrorResult()
+ if (fingerprint.resolve(context, it.mutableMethod, it.mutableClass)) return@forEach
+ return fingerprint.toErrorResult()
}
}?.let { result ->
val builderMethodIndex = EmptyComponentBuilderFingerprint.patternScanEndIndex
@@ -45,16 +46,28 @@ class LithoFilterPatch : BytecodePatch(
result.mutableMethod.apply {
val insertHookIndex = result.scanResult.patternScanResult!!.endIndex
- val builderMethodDescriptor = getInstruction(builderMethodIndex).descriptor
- val emptyComponentFieldDescriptor = getInstruction(emptyComponentFieldIndex).descriptor
- // Register is overwritten right after it is used in this patch, therefore free to clobber.
- val free = getInstruction(insertHookIndex - 1).registerA
- val free2 = getInstruction(insertHookIndex).registerA
+
+ // region Get free registers that this patch uses
+ // Registers are overwritten right after they are used in this patch, therefore free to clobber.
+
+ val freeRegistersInstruction = getInstruction(insertHookIndex - 2)
+
+ // Later used to store the protobuf buffer object.
+ val free1 = getInstruction(insertHookIndex).registerA
+ // Later used to store the identifier of the component.
+ // This register currently holds a reference to the StringBuilder object
+ // that is required before clobbering.
+ val free2 = freeRegistersInstruction.registerC
@Suppress("UnnecessaryVariable")
- // The register, this patch clobbers, is previously used for the StringBuilder,
- // later on a new StringBuilder is instantiated on it.
- val stringBuilderRegister = free
+ val stringBuilderRegister = free2
+
+ // endregion
+
+ // region Get references that this patch needs
+
+ val builderMethodDescriptor = getInstruction(builderMethodIndex).descriptor
+ val emptyComponentFieldDescriptor = getInstruction(emptyComponentFieldIndex).descriptor
val identifierRegister =
getInstruction(ReadComponentIdentifierFingerprint.patternScanEndIndex).registerA
@@ -69,57 +82,87 @@ class LithoFilterPatch : BytecodePatch(
getInstruction(ProtobufBufferFingerprint.patternScanEndIndex - 1).descriptor
val protobufBufferFieldDescriptor = "$protobufBufferRefTypeDescriptor->b:Ljava/nio/ByteBuffer;"
+ // endregion
+
+ // region Patch the method
+
+ // Insert the instructions that are responsible
+ // to return an EmptyComponent instead of the original component if the filter method returns false.
addInstructionsWithLabels(
- insertHookIndex, // right after setting the component.pathBuilder field.
+ insertHookIndex,
"""
# Get the protobuf buffer object.
- move-object/from16 v$free2, p$protobufParameterNumber
- iget-object v$free2, v$free2, $protobufBufferRefTypeRefFieldDescriptor
- check-cast v$free2, $protobufBufferRefTypeDescriptor
+ move-object/from16 v$free1, p$protobufParameterNumber
+ iget-object v$free1, v$free1, $protobufBufferRefTypeRefFieldDescriptor
+ check-cast v$free1, $protobufBufferRefTypeDescriptor
# Register "free" now holds the protobuf buffer object
- iget-object v$free2, v$free2, $protobufBufferFieldDescriptor
-
+ iget-object v$free1, v$free1, $protobufBufferFieldDescriptor
+
# Invoke the filter method.
- invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free2 }, $FILTER_METHOD_DESCRIPTOR
- move-result v$free
+ invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free1 }, $FILTER_METHOD_DESCRIPTOR
+ move-result v$free1
- if-eqz v$free, :not_an_ad
-
- # If the filter method returned true, then return a replacement empty component.
-
- move-object/from16 v$free, p1
- invoke-static {v$free}, $builderMethodDescriptor
- move-result-object v$free
- iget-object v$free, v$free, $emptyComponentFieldDescriptor
- return-object v$free
+ if-eqz v$free1, :unfiltered
+
+ move-object/from16 v$free2, p1
+ invoke-static {v$free2}, $builderMethodDescriptor
+ move-result-object v$free2
+ iget-object v$free2, v$free2, $emptyComponentFieldDescriptor
+ return-object v$free2
""",
- ExternalLabel("not_an_ad", getInstruction(insertHookIndex))
+ // Used to jump over the instruction which block the component from being created.
+ ExternalLabel("unfiltered", getInstruction(insertHookIndex))
)
+ // endregion
}
} ?: return ComponentContextParserFingerprint.toErrorResult()
+ LithoFilterFingerprint.result?.mutableMethod?.apply {
+ removeInstructions(2, 4) // Remove dummy filter.
+
+ addFilter = { classDescriptor ->
+ addInstructions(
+ 2,
+ """
+ new-instance v1, $classDescriptor
+ invoke-direct {v1}, $classDescriptor->()V
+ const/4 v2, ${filterCount++}
+ aput-object v1, v0, v2
+ """
+ )
+ }
+ } ?: return LithoFilterFingerprint.toErrorResult()
+
return PatchResultSuccess()
}
- private companion object {
+ override fun close() = LithoFilterFingerprint.result!!
+ .mutableMethod.replaceInstruction(0, "const/4 v0, $filterCount")
+
+ companion object {
private val MethodFingerprint.patternScanResult
get() = result!!.scanResult.patternScanResult!!
- val MethodFingerprint.patternScanEndIndex
+ private val MethodFingerprint.patternScanEndIndex
get() = patternScanResult.endIndex
- val MethodFingerprint.patternScanStartIndex
+ private val MethodFingerprint.patternScanStartIndex
get() = patternScanResult.startIndex
- val Instruction.descriptor
+ private val Instruction.descriptor
get() = (this as ReferenceInstruction).reference.toString()
- const val FILTER_METHOD_DESCRIPTOR =
+ private const val FILTER_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/LithoFilterPatch;" +
"->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/nio/ByteBuffer;)Z"
+
+ internal lateinit var addFilter: (String) -> Unit
+ private set
+
+ private var filterCount = 0
}
}
\ No newline at end of file