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