diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95361be9..7f0a4aff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,128 @@
+# [2.175.0-dev.16](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.15...v2.175.0-dev.16) (2023-05-30)
+
+
+### Bug Fixes
+
+* **spoof-wifi-connection:** use updated instruction indices ([#2199](https://github.com/revanced/revanced-patches/issues/2199)) ([76fb700](https://github.com/revanced/revanced-patches/commit/76fb700884dae5b71a57f9530fad9d4a98ba0af0))
+
+# [2.175.0-dev.15](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.14...v2.175.0-dev.15) (2023-05-30)
+
+
+### Bug Fixes
+
+* **youtube/remember-video-quality:** fix typo in video resolutions ([#2323](https://github.com/revanced/revanced-patches/issues/2323)) ([a99cef8](https://github.com/revanced/revanced-patches/commit/a99cef87b40b67a5feb97999fb4f2925ea80b42e))
+
+# [2.175.0-dev.14](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.13...v2.175.0-dev.14) (2023-05-30)
+
+
+### Bug Fixes
+
+* **youtube/theme:** use dynamic background color for custom splash screen ([#2319](https://github.com/revanced/revanced-patches/issues/2319)) ([28594f3](https://github.com/revanced/revanced-patches/commit/28594f3eeaf99fa32ee57214ebbc4342529c6694))
+
+
+### Features
+
+* **tiktok:** remove compatibility version constraints ([#2306](https://github.com/revanced/revanced-patches/issues/2306)) ([a12c4bb](https://github.com/revanced/revanced-patches/commit/a12c4bb1610234d19b4ac86cd57bb09335566b68))
+
+# [2.175.0-dev.13](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.12...v2.175.0-dev.13) (2023-05-29)
+
+
+### Bug Fixes
+
+* **settings:** sort setting preferences using lowercase ([#2312](https://github.com/revanced/revanced-patches/issues/2312)) ([2743a95](https://github.com/revanced/revanced-patches/commit/2743a95b417a6023799035e30631e7b3a68bcc45))
+
+# [2.175.0-dev.12](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.11...v2.175.0-dev.12) (2023-05-29)
+
+
+### Bug Fixes
+
+* **youtube/integrations:** fix playback of embedded videos ([#2304](https://github.com/revanced/revanced-patches/issues/2304)) ([1dffbaf](https://github.com/revanced/revanced-patches/commit/1dffbaf0aa73f0f703516648d5cd935000fa2770))
+
+# [2.175.0-dev.11](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.10...v2.175.0-dev.11) (2023-05-28)
+
+
+### Features
+
+* **scbeasy:** add `remove-debugging-detection` patch ([#2287](https://github.com/revanced/revanced-patches/issues/2287)) ([53d91e3](https://github.com/revanced/revanced-patches/commit/53d91e32183663b0aa70994cc4e1d8ae5eb8c8e4))
+
+# [2.175.0-dev.10](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.9...v2.175.0-dev.10) (2023-05-27)
+
+
+### Features
+
+* **youtube/hide-shorts-components:** hide channel bar & sound button ([749c83d](https://github.com/revanced/revanced-patches/commit/749c83d068c2201ed6f29047d5428d1072924960))
+* **youtube/navigation-buttons:** use a better preference screen title ([5d7772b](https://github.com/revanced/revanced-patches/commit/5d7772be942c72e05644eca3f68d2bd6b9762d26))
+
+# [2.175.0-dev.9](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.8...v2.175.0-dev.9) (2023-05-27)
+
+
+### Features
+
+* **youtube/hide-seekbar:** more fine grained hiding of seekbar ([#2252](https://github.com/revanced/revanced-patches/issues/2252)) ([0f07bf4](https://github.com/revanced/revanced-patches/commit/0f07bf467a4aa06c9bcdf60a2498d88eea8c1429))
+
+# [2.175.0-dev.8](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.7...v2.175.0-dev.8) (2023-05-27)
+
+
+### Features
+
+* **youtube/hide-shorts-components:** hide shorts info panel ([#2278](https://github.com/revanced/revanced-patches/issues/2278)) ([a5b323d](https://github.com/revanced/revanced-patches/commit/a5b323d1d9e5b175c93f0b29732eb1123b83bab7))
+
+# [2.175.0-dev.7](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.6...v2.175.0-dev.7) (2023-05-26)
+
+
+### Features
+
+* **remove-screen-capture-restriction:** remove app constraint ([#2260](https://github.com/revanced/revanced-patches/issues/2260)) ([49ce47c](https://github.com/revanced/revanced-patches/commit/49ce47c3eed6a1626674d0f60ae0fdbe349e804b))
+
+# [2.175.0-dev.6](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.5...v2.175.0-dev.6) (2023-05-26)
+
+
+### Bug Fixes
+
+* **youtube/hide-shorts-components:** clarify settings switch ([#2276](https://github.com/revanced/revanced-patches/issues/2276)) ([3e6d052](https://github.com/revanced/revanced-patches/commit/3e6d0528b287ded401dacdcea698d4ec97b926ee))
+
+# [2.175.0-dev.5](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.4...v2.175.0-dev.5) (2023-05-26)
+
+
+### Features
+
+* **nfctoolsse:** add `unlock-pro` patch ([#2272](https://github.com/revanced/revanced-patches/issues/2272)) ([9789ad3](https://github.com/revanced/revanced-patches/commit/9789ad30ff82d9bb99e870dc8053775dc222a010))
+
+# [2.175.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.3...v2.175.0-dev.4) (2023-05-26)
+
+
+### Bug Fixes
+
+* **youtube/downloads:** rename patch to `external-downloads` ([#2274](https://github.com/revanced/revanced-patches/issues/2274)) ([4480911](https://github.com/revanced/revanced-patches/commit/4480911e0b056f2148616a0c2af6b4ab7c482c3b))
+
+# [2.175.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.2...v2.175.0-dev.3) (2023-05-25)
+
+
+### Bug Fixes
+
+* **youtube/hide-player-buttons:** fix previous/next button showing if previous video exists ([#2261](https://github.com/revanced/revanced-patches/issues/2261)) ([91d1aab](https://github.com/revanced/revanced-patches/commit/91d1aabd32be1607019bc443fb06284ca3343e9d))
+
+# [2.175.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.1...v2.175.0-dev.2) (2023-05-25)
+
+
+### Bug Fixes
+
+* **youtube/hide-info-cards:** fix hide-info-cards setting does not work ([#2246](https://github.com/revanced/revanced-patches/issues/2246)) ([72773ac](https://github.com/revanced/revanced-patches/commit/72773ac56987753fac6c0087d048b4378a3dd360))
+
+# [2.175.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.174.1-dev.1...v2.175.0-dev.1) (2023-05-24)
+
+
+### Features
+
+* **youtube/general-ads:** merge `hide-get-premium` patch into `general-ads` patch ([5195dd8](https://github.com/revanced/revanced-patches/commit/5195dd8936d63c482dbcb2cd0e7e9aab3c75954e))
+
+## [2.174.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.174.0...v2.174.1-dev.1) (2023-05-24)
+
+
+### Bug Fixes
+
+* **youtube/remove-player-controls-background:** use correct patch name and description ([8732a84](https://github.com/revanced/revanced-patches/commit/8732a84422087fca7e9e1635a0b1d8d2cbf034f4))
+
# [2.174.0](https://github.com/revanced/revanced-patches/compare/v2.173.0...v2.174.0) (2023-05-24)
diff --git a/README.md b/README.md
index ac0cf228..61dbc3ae 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,8 @@ The official ReVanced Patches.
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.19.35 |
| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
-| `downloads` | Adds a download button to the YouTube video player. | 18.19.35 |
| `enable-debugging` | Adds debugging options. | all |
+| `external-downloads` | Adds support to download and save YouTube videos using an external app. | 18.19.35 |
| `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 |
@@ -35,7 +35,6 @@ The official ReVanced Patches.
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.19.35 |
| `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-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.19.35 |
| `hide-info-cards` | Hides info cards in videos. | 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 |
@@ -52,7 +51,7 @@ The official ReVanced Patches.
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
| `premium-heading` | Shows premium branding on the home screen. | all |
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
-| `remove-player-button-background` | Removes the background from the video player buttons. | 18.19.35 |
+| `remove-player-controls-background` | Removes the background from the video player controls. | 18.19.35 |
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.19.35 |
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.19.35 |
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.19.35 |
@@ -90,14 +89,14 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `disable-login-requirement` | Do not force login. | all |
-| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
-| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
+| `downloads` | Removes download restrictions and changes the default path to download to. | all |
+| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | all |
| `fix-google-login` | Allows logging in with a Google account. | all |
| `hide-ads` | Removes ads from TikTok. | all |
| `playback-speed` | Enables the playback speed option for all videos. | all |
-| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
+| `settings` | Adds ReVanced settings to TikTok. | all |
| `show-seekbar` | Shows progress bar for all video. | all |
-| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
+| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | all |
### [📦 `com.zhiliaoapp.musically`](https://play.google.com/store/apps/details?id=com.zhiliaoapp.musically)
@@ -106,14 +105,14 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `disable-login-requirement` | Do not force login. | all |
-| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
-| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
+| `downloads` | Removes download restrictions and changes the default path to download to. | all |
+| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | all |
| `fix-google-login` | Allows logging in with a Google account. | all |
| `hide-ads` | Removes ads from TikTok. | all |
| `playback-speed` | Enables the playback speed option for all videos. | all |
-| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
+| `settings` | Adds ReVanced settings to TikTok. | all |
| `show-seekbar` | Shows progress bar for all video. | all |
-| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
+| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | all |
### [📦 `tv.twitch.android.app`](https://play.google.com/store/apps/details?id=tv.twitch.android.app)
@@ -152,16 +151,6 @@ The official ReVanced Patches.
| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
-### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `disable-capture-restriction` | Allows capturing Spotify's audio output while screen sharing or screen recording. | all |
-| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
-| `spotify-theme` | Applies a custom theme. | all |
-
-
### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
@@ -172,6 +161,15 @@ The official ReVanced Patches.
| `hide-inbox-ads` | Hides ads in inbox. | all |
+### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
+| `spotify-theme` | Applies a custom theme. | all |
+
+
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
@@ -286,6 +284,14 @@ The official ReVanced Patches.
| `remove-broadcasts-restriction` | Enables starting/stopping NetGuard via broadcasts. | all |
+### [📦 `com.scb.phone`](https://play.google.com/store/apps/details?id=com.scb.phone)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `remove-debugging-detection` | Removes the USB and wireless debugging checks. | all |
+
+
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
@@ -334,6 +340,14 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all pro features. | all |
+### [📦 `com.wakdev.apps.nfctools.se`](https://play.google.com/store/apps/details?id=com.wakdev.apps.nfctools.se)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks all pro features. | all |
+
+
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
diff --git a/gradle.properties b/gradle.properties
index 1922a104..aae1b086 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
kotlin.code.style = official
-version = 2.174.0
+version = 2.175.0-dev.16
diff --git a/patches.json b/patches.json
index f275f8b6..2b7476cf 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-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.","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-capture-restriction","description":"Allows capturing Spotify\u0027s audio output while screen sharing or screen recording.","version":"0.0.2","excluded":false,"options":[],"dependencies":["disable-capture-restriction-resource-patch"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"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":"Adds a download button to the YouTube video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"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":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"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":"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":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"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 from the Reddit frontpage and subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["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-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 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":"Hides advertisement for YouTube Premium under 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":"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"],"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-subreddit-banner","description":"Hides banner ads from comments on subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-timeline-ads","description":"Removes ads from the timeline.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":[]}]},{"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":"premium-unlock","description":"Unlocks premium functions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.citra.citra_emu","versions":[]},{"name":"org.citra.citra_emu.canary","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-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":["2.2.0"]}]},{"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-player-button-background","description":"Removes the background from the video player buttons.","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":["2.2.0"]}]},{"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":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"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":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"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},{"key":"splashScreenBackgroundColor","title":"Background color for the splash screen","description":"The background color of the splash screen. 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.ithebk.expensemanager","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 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":"co.windyapp.android","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 premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.candylink.openvpn","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":"com.vsco.cam","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":[]}]},{"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-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.","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 general ads from the Reddit frontpage and subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","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-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 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-subreddit-banner","description":"Hides banner ads from comments on subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-timeline-ads","description":"Removes ads from the timeline.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":[]}]},{"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":"premium-unlock","description":"Unlocks premium functions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.citra.citra_emu","versions":[]},{"name":"org.citra.citra_emu.canary","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-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":["2.2.0"]}]},{"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-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":["2.2.0"]}]},{"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},{"key":"splashScreenBackgroundColor","title":"Background color for the splash screen","description":"The background color of the splash screen. 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.ithebk.expensemanager","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":"com.wakdev.apps.nfctools.se","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":[],"compatiblePackages":[{"name":"tv.trakt.trakt","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 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 premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.candylink.openvpn","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":"com.vsco.cam","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
diff --git a/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/bytecode/patch/RemoveCaptureRestrictionPatch.kt b/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/bytecode/patch/RemoveCaptureRestrictionPatch.kt
new file mode 100644
index 00000000..39a43353
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/bytecode/patch/RemoveCaptureRestrictionPatch.kt
@@ -0,0 +1,66 @@
+package app.revanced.patches.all.screencapture.removerestriction.bytecode.patch
+
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotations.RequiresIntegrations
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.all.screencapture.removerestriction.resource.patch.RemoveCaptureRestrictionResourcePatch
+import app.revanced.util.patch.*
+import org.jf.dexlib2.iface.ClassDef
+import org.jf.dexlib2.iface.Method
+import org.jf.dexlib2.iface.instruction.Instruction
+
+@Patch(false)
+@Name("remove-screen-capture-restriction")
+@Description("Removes the restriction of capturing audio from apps that normally wouldn't allow it.")
+@Version("0.0.1")
+@DependsOn([RemoveCaptureRestrictionResourcePatch::class])
+@RequiresIntegrations
+internal class RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch() {
+ // Information about method calls we want to replace
+ enum class MethodCall(
+ override val definedClassName: String,
+ override val methodName: String,
+ override val methodParams: Array,
+ override val returnType: String
+ ): IMethodCall {
+ SetAllowedCapturePolicySingle(
+ "Landroid/media/AudioAttributes\$Builder;",
+ "setAllowedCapturePolicy",
+ arrayOf("I"),
+ "Landroid/media/AudioAttributes\$Builder;",
+ ),
+ SetAllowedCapturePolicyGlobal(
+ "Landroid/media/AudioManager;",
+ "setAllowedCapturePolicy",
+ arrayOf("I"),
+ "V",
+ );
+ }
+
+ override fun filterMap(
+ classDef: ClassDef,
+ method: Method,
+ instruction: Instruction,
+ instructionIndex: Int
+ ) = filterMapInstruction35c(
+ INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
+ classDef,
+ instruction,
+ instructionIndex
+ )
+
+ override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) {
+ val (methodType, instruction, instructionIndex) = entry
+ methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
+ }
+
+ private companion object {
+ const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
+ "Lapp/revanced/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
+ const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt b/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/resource/patch/RemoveCaptureRestrictionResourcePatch.kt
similarity index 75%
rename from src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/resource/patch/RemoveCaptureRestrictionResourcePatch.kt
index 5088cce8..5fe2f77f 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/screencapture/removerestriction/resource/patch/RemoveCaptureRestrictionResourcePatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.spotify.audio.resource.patch
+package app.revanced.patches.all.screencapture.removerestriction.resource.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
@@ -7,14 +7,12 @@ 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.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
import org.w3c.dom.Element
-@Name("disable-capture-restriction-resource-patch")
+@Name("remove-screen-capture-restriction-resource-patch")
@Description("Sets allowAudioPlaybackCapture in manifest to true.")
-@DisableCaptureRestrictionCompatibility
-@Version("0.0.2")
-class DisableCaptureRestrictionResourcePatch : ResourcePatch {
+@Version("0.0.1")
+internal class RemoveCaptureRestrictionResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
// create an xml editor instance
context.xmlEditor["AndroidManifest.xml"].use { dom ->
diff --git a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/annotations/UnlockProCompatibility.kt
new file mode 100644
index 00000000..0fdf6ac0
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/annotations/UnlockProCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.nfctoolsse.misc.pro.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.wakdev.apps.nfctools.se")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/fingerprints/IsLicenseRegisteredFingerprint.kt b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/fingerprints/IsLicenseRegisteredFingerprint.kt
new file mode 100644
index 00000000..fd6089e3
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/fingerprints/IsLicenseRegisteredFingerprint.kt
@@ -0,0 +1,10 @@
+package app.revanced.patches.nfctoolsse.misc.pro.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+
+object IsLicenseRegisteredFingerprint : MethodFingerprint(
+ returnType = "Z",
+ accessFlags = AccessFlags.PUBLIC.value,
+ strings = listOf("kLicenseCheck")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/patch/UnlockProPatch.kt
new file mode 100644
index 00000000..d49d19d6
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/patch/UnlockProPatch.kt
@@ -0,0 +1,41 @@
+package app.revanced.patches.nfctoolsse.misc.pro.patch
+
+import app.revanced.extensions.toErrorResult
+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.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.nfctoolsse.misc.pro.annotations.UnlockProCompatibility
+import app.revanced.patches.nfctoolsse.misc.pro.fingerprints.IsLicenseRegisteredFingerprint
+
+
+@Patch
+@Name("unlock-pro")
+@Description("Unlocks all pro features.")
+@Version("0.0.1")
+@UnlockProCompatibility
+class UnlockProPatch : BytecodePatch(
+ listOf(
+ IsLicenseRegisteredFingerprint
+ )
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ IsLicenseRegisteredFingerprint.result?.mutableMethod?.apply {
+ addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ )
+ } ?: return IsLicenseRegisteredFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/annotations/RemoveDebuggingDetectionCompatibility.kt b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/annotations/RemoveDebuggingDetectionCompatibility.kt
new file mode 100644
index 00000000..095abdaa
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/annotations/RemoveDebuggingDetectionCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.scbeasy.detection.debugging.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.scb.phone")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class RemoveDebuggingDetectionCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/fingerprints/DebuggingDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/fingerprints/DebuggingDetectionFingerprint.kt
new file mode 100644
index 00000000..61408b47
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/fingerprints/DebuggingDetectionFingerprint.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.scbeasy.detection.debugging.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object DebuggingDetectionFingerprint : MethodFingerprint(
+ returnType = "Z",
+ strings = listOf("adb_enabled")
+)
diff --git a/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/patch/RemoveDebuggingDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/patch/RemoveDebuggingDetectionPatch.kt
new file mode 100644
index 00000000..cc3f1111
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/scbeasy/detection/debugging/patch/RemoveDebuggingDetectionPatch.kt
@@ -0,0 +1,31 @@
+package app.revanced.patches.scbeasy.detection.debugging.patch
+
+import app.revanced.patcher.annotation.*
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.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.scbeasy.detection.debugging.annotations.RemoveDebuggingDetectionCompatibility
+import app.revanced.patches.scbeasy.detection.debugging.fingerprints.DebuggingDetectionFingerprint
+
+@Patch(false)
+@Name("remove-debugging-detection")
+@Description("Removes the USB and wireless debugging checks.")
+@RemoveDebuggingDetectionCompatibility
+@Version("0.0.1")
+class RemoveDebuggingDetectionPatch : BytecodePatch(
+ listOf(DebuggingDetectionFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ DebuggingDetectionFingerprint.result!!.mutableMethod.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x0
+ return v0
+ """
+ )
+ return PatchResultSuccess()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/util/AbstractPreferenceScreen.kt b/src/main/kotlin/app/revanced/patches/shared/settings/util/AbstractPreferenceScreen.kt
index a257af9a..a17b9c38 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/util/AbstractPreferenceScreen.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/util/AbstractPreferenceScreen.kt
@@ -35,8 +35,8 @@ internal abstract class AbstractPreferenceScreen(
return PreferenceScreen(
key,
StringResource("${key}_title", title),
- preferences.sortedBy { it.title.value } +
- categories.sortedBy { it.title }.map { it.transform() },
+ preferences.sortedBy { it.title.value.lowercase() } +
+ categories.sortedBy { it.title.lowercase() }.map { it.transform() },
summary?.let { summary ->
StringResource("${key}_summary", summary)
}
@@ -63,7 +63,7 @@ internal abstract class AbstractPreferenceScreen(
return PreferenceCategory(
key,
StringResource("${key}_title", title),
- preferences.sortedBy { it.title.value }
+ preferences.sortedBy { it.title.value.lowercase() }
)
}
diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt
deleted file mode 100644
index 849e34b5..00000000
--- a/src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package app.revanced.patches.spotify.audio.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package("com.spotify.music")]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class DisableCaptureRestrictionCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt
deleted file mode 100644
index cc656d11..00000000
--- a/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package app.revanced.patches.spotify.audio.bytecode.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.instruction
-import app.revanced.patcher.extensions.replaceInstruction
-import app.revanced.patcher.patch.BytecodePatch
-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.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
-import app.revanced.patches.spotify.audio.fingerprints.DisableCaptureRestrictionAudioDriverFingerprint
-import app.revanced.patches.spotify.audio.resource.patch.DisableCaptureRestrictionResourcePatch
-import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
-
-@Patch
-@Name("disable-capture-restriction")
-@DependsOn([DisableCaptureRestrictionResourcePatch::class])
-@Description("Allows capturing Spotify's audio output while screen sharing or screen recording.")
-@DisableCaptureRestrictionCompatibility
-@Version("0.0.2")
-class DisableCaptureRestrictionBytecodePatch : BytecodePatch(
- listOf(
- DisableCaptureRestrictionAudioDriverFingerprint
- )
-) {
- override fun execute(context: BytecodeContext): PatchResult {
- val method = DisableCaptureRestrictionAudioDriverFingerprint.result!!.mutableMethod
-
- method.apply {
- // Replace constant
- val original = instruction(0) as OneRegisterInstruction
- replaceInstruction(
- 0,
- "const/4 v${original.registerA}, $ALLOW_CAPTURE_BY_ALL"
- )
- }
-
- return PatchResultSuccess()
- }
-
- private companion object {
- const val ALLOW_CAPTURE_BY_ALL = 0x01
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt
deleted file mode 100644
index 97b9193e..00000000
--- a/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package app.revanced.patches.spotify.audio.fingerprints
-
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-import org.jf.dexlib2.iface.reference.MethodReference
-
-object DisableCaptureRestrictionAudioDriverFingerprint : MethodFingerprint(
- "L",
- AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC or AccessFlags.BRIDGE,
- listOf("L"),
- listOf(
- Opcode.CONST_4,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.RETURN_OBJECT
- ),
- customFingerprint = { methodDef, _ ->
- // Check for method call to AudioAttributes$Builder.setAllowedCapturePolicy Android API
- methodDef.implementation?.instructions?.any {
- ((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "setAllowedCapturePolicy"
- } == true
- }
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt
index a4c40c74..64d56b26 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt
@@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
@Compatibility(
[
- Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
- Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
+ Package("com.ss.android.ugc.trill"),
+ Package("com.zhiliaoapp.musically")
]
)
@Target(AnnotationTarget.CLASS)
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt
index a193c100..bb292064 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt
@@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
@Compatibility(
[
- Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
- Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
+ Package("com.ss.android.ugc.trill"),
+ Package("com.zhiliaoapp.musically")
]
)
@Target(AnnotationTarget.CLASS)
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt
index cb994126..b139f132 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/SettingsCompatibility.kt
@@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
@Compatibility(
[
- Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
- Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
+ Package("com.ss.android.ugc.trill"),
+ Package("com.zhiliaoapp.musically")
]
)
@Target(AnnotationTarget.CLASS)
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AboutPageFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AboutPageFingerprint.kt
new file mode 100644
index 00000000..7ef0e757
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AboutPageFingerprint.kt
@@ -0,0 +1,17 @@
+package app.revanced.patches.tiktok.misc.settings.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object AboutPageFingerprint : MethodFingerprint(
+ opcodes = listOf(
+ Opcode.CONST, // copyrightPolicyLabel resource id
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CONST_STRING
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/ss/android/ugc/aweme/setting/page/AboutPage;" &&
+ methodDef.name == "onViewCreated"
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AboutViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AboutViewFingerprint.kt
deleted file mode 100644
index e4b680c3..00000000
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AboutViewFingerprint.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package app.revanced.patches.tiktok.misc.settings.fingerprints
-
-import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.Opcode
-
-@FuzzyPatternScanMethod(4)
-object AboutViewFingerprint : MethodFingerprint(
- opcodes = listOf(
- Opcode.NEW_INSTANCE,
- Opcode.INVOKE_DIRECT,
- Opcode.INVOKE_DIRECT_RANGE,
- Opcode.INVOKE_DIRECT,
- Opcode.IPUT_OBJECT,
- Opcode.NEW_INSTANCE,
- Opcode.NEW_INSTANCE,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.SGET_OBJECT,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.NEW_INSTANCE,
- Opcode.INVOKE_DIRECT,
- Opcode.CONST_4,
- Opcode.CONST_STRING,
- Opcode.INVOKE_DIRECT_RANGE,
- Opcode.INVOKE_DIRECT,
- Opcode.IPUT_OBJECT,
- Opcode.CONST,
- Opcode.SGET_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT,
- Opcode.IF_EQZ,
- Opcode.CONST
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
index 42cd5a0d..66b06049 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
@@ -8,7 +8,6 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.replaceInstruction
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
@@ -17,14 +16,14 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.annotations.SettingsCompatibility
-import app.revanced.patches.tiktok.misc.settings.fingerprints.AboutViewFingerprint
+import app.revanced.patches.tiktok.misc.settings.fingerprints.AboutPageFingerprint
import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityOnCreateFingerprint
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsOnViewCreatedFingerprint
import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-import org.jf.dexlib2.iface.instruction.formats.Instruction35c
-import org.jf.dexlib2.iface.reference.StringReference
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Patch
@DependsOn([IntegrationsPatch::class])
@@ -34,84 +33,92 @@ import org.jf.dexlib2.iface.reference.StringReference
@Version("0.0.1")
class SettingsPatch : BytecodePatch(
listOf(
+ AboutPageFingerprint,
AdPersonalizationActivityOnCreateFingerprint,
SettingsOnViewCreatedFingerprint,
)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsOnViewCreatedFingerprint.result?.let {
- AboutViewFingerprint.resolve(context, it.method, it.classDef)
- }
- // Patch Settings UI to add 'Revanced Settings'.
- val targetIndexes = findOptionsOnClickIndex()
- with(SettingsOnViewCreatedFingerprint.result!!.mutableMethod) {
- for (index in targetIndexes) {
- if (
- instruction(index).opcode != Opcode.NEW_INSTANCE ||
- instruction(index - 4).opcode != Opcode.MOVE_RESULT_OBJECT
- )
- return PatchResultError("Hardcode offset changed.")
- patchOptionNameAndOnClickEvent(index, context)
- }
- }
- // Implement settings screen in `AdPersonalizationActivity`
- with(AdPersonalizationActivityOnCreateFingerprint.result!!.mutableMethod) {
- for ((index, instruction) in implementation!!.instructions.withIndex()) {
- if (instruction.opcode != Opcode.INVOKE_SUPER) continue
- val thisRegister = (instruction as Instruction35c).registerC
- addInstructions(
- index + 1,
+ SettingsOnViewCreatedFingerprint.result?.mutableMethod?.apply {
+ val instructions = implementation!!.instructions
+
+ // Find the indices that need to be patched.
+ val copyrightPolicyLabelId = AboutPageFingerprint.result?.let {
+ val startIndex = it.scanResult.patternScanResult!!.startIndex
+ it.mutableMethod.instruction(startIndex).wideLiteral
+ } ?: return AboutPageFingerprint.toErrorResult()
+
+ val copyrightIndex = instructions.indexOfFirst {
+ (it as? ReferenceInstruction)?.reference.toString() == "copyright_policy"
+ } - 6
+
+
+ val copyrightPolicyIndex = instructions.indexOfFirst {
+ (it as? WideLiteralInstruction)?.wideLiteral == copyrightPolicyLabelId
+ } + 2
+
+ // Replace an existing settings entry with ReVanced settings entry.
+ arrayOf(
+ copyrightIndex,
+ copyrightPolicyIndex
+ ).forEach { index ->
+ val instruction = instruction(index)
+ if (instruction.opcode != Opcode.MOVE_RESULT_OBJECT)
+ return PatchResultError("Hardcoded offset changed.")
+
+ val settingsEntryStringRegister = (instruction as OneRegisterInstruction).registerA
+
+ // Replace the settings entry string with a custom one.
+ replaceInstruction(
+ index,
"""
- invoke-static {v$thisRegister}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->initializeSettings(Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;)V
+ const-string v$settingsEntryStringRegister, "ReVanced Settings"
+ """
+ )
+
+ // Replace the OnClickListener class with a custom one.
+ val onClickListener = instruction(index + 4).reference.toString()
+
+ context.findClass(onClickListener)?.mutableClass?.methods?.first {
+ it.name == "onClick"
+ }?.addInstructions(
+ 0,
+ """
+ invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->startSettingsActivity()V
return-void
"""
- )
- break
+ ) ?: return PatchResultError("Could not find the onClick method.")
}
- }
+
+ } ?: return SettingsOnViewCreatedFingerprint.toErrorResult()
+
+ // Initialize the settings menu once the replaced setting entry is clicked.
+ AdPersonalizationActivityOnCreateFingerprint.result?.mutableMethod?.apply {
+ val initializeSettingsIndex = implementation!!.instructions.indexOfFirst {
+ it.opcode == Opcode.INVOKE_SUPER
+ } + 1
+
+ val thisRegister = instruction(initializeSettingsIndex - 1).registerC
+
+ addInstructions(
+ initializeSettingsIndex,
+ """
+ invoke-static {v$thisRegister}, $INITIALIZE_SETTINGS_METHOD_DESCRIPTOR
+ return-void
+ """
+ )
+ } ?: return AdPersonalizationActivityOnCreateFingerprint.toErrorResult()
+
return PatchResultSuccess()
}
- private fun findOptionsOnClickIndex(): IntArray {
- val results = IntArray(2)
- SettingsOnViewCreatedFingerprint.result?.apply {
- for ((index, instruction) in mutableMethod.implementation!!.instructions.withIndex()) {
- // Old UI settings option to replace to 'Revanced Settings'
- if (instruction.opcode == Opcode.CONST_STRING) {
- val string = ((instruction as ReferenceInstruction).reference as StringReference).string
- if (string == "copyright_policy") {
- results[0] = index - 2
- break
- }
- }
- }
+ private companion object {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
- // New UI settings option to replace to 'Revanced Settings'
- results[1] = AboutViewFingerprint.result!!.scanResult.patternScanResult!!.startIndex
- } ?: throw SettingsOnViewCreatedFingerprint.toErrorResult()
- return results
- }
-
- private fun patchOptionNameAndOnClickEvent(index: Int, context: BytecodeContext) {
- with(SettingsOnViewCreatedFingerprint.result!!.mutableMethod) {
- // Patch option name
- val overrideRegister = instruction(index - 4).registerA
- replaceInstruction(
- index - 4,
- """
- const-string v$overrideRegister, "Revanced Settings"
- """
- )
-
- // Patch option OnClick Event
- val type = instruction(index).reference.toString()
- context.findClass(type)!!.mutableClass.methods.first { type == "onClick" }.addInstructions(
- 0,
- """
- invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->startSettingsActivity()V
- return-void
- """
- )
- }
+ private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
+ "Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
+ ")V"
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt
index 97b091e6..b258cec9 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt
@@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
@Compatibility(
[
- Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
- Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
+ Package("com.ss.android.ugc.trill"),
+ Package("com.zhiliaoapp.musically")
]
)
@Target(AnnotationTarget.CLASS)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
index 4d907a65..886aa3bb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
@@ -14,13 +14,21 @@ import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
+import app.revanced.patches.youtube.ad.getpremium.bytecode.patch.HideGetPremiumPatch
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
-@DependsOn([HideAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
+@DependsOn(
+ [
+ HideGetPremiumPatch::class,
+ HideAdsResourcePatch::class,
+ VerticalScrollPatch::class,
+ FixBackToExitGesturePatch::class
+ ]
+)
@Name("hide-ads")
@Description("Removes general ads.")
@HideAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/annotations/HideGetPremiumCompatibility.kt
similarity index 79%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/annotations/HideGetPremiumCompatibility.kt
index bd210bfc..7f395874 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/annotations/HideGetPremiumCompatibility.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.hide.getpremium.annotations
+package app.revanced.patches.youtube.ad.getpremium.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
similarity index 86%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
index 2cffc237..18af00c4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.hide.getpremium.bytecode.fingerprints
+package app.revanced.patches.youtube.ad.getpremium.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
index 1c978a7c..da1f176a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
@@ -1,7 +1,6 @@
-package app.revanced.patches.youtube.layout.hide.getpremium.bytecode.patch
+package app.revanced.patches.youtube.ad.getpremium.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
import app.revanced.patcher.data.BytecodeContext
@@ -11,33 +10,35 @@ import app.revanced.patcher.patch.BytecodePatch
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.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.getpremium.annotations.HideGetPremiumCompatibility
-import app.revanced.patches.youtube.layout.hide.getpremium.bytecode.fingerprints.GetPremiumViewFingerprint
+import app.revanced.patches.youtube.ad.getpremium.annotations.HideGetPremiumCompatibility
+import app.revanced.patches.youtube.ad.getpremium.bytecode.fingerprints.GetPremiumViewFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
-@Patch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
@Name("hide-get-premium")
-@Description("Hides advertisement for YouTube Premium under the video player.")
@HideGetPremiumCompatibility
@Version("0.0.1")
-class HideGetPremiumPatch : BytecodePatch(
- listOf(
- GetPremiumViewFingerprint,
- )
-) {
+class HideGetPremiumPatch : BytecodePatch(listOf(GetPremiumViewFingerprint,)) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ SettingsPatch.PreferenceScreen.ADS.addPreferences(
SwitchPreference(
"revanced_hide_get_premium",
- StringResource("revanced_hide_get_premium_title", "Hide YouTube Premium advertisement"),
- StringResource("revanced_hide_get_premium_summary_on", "YouTube Premium advertisement are hidden"),
- StringResource("revanced_hide_get_premium_summary_off", "YouTube Premium advertisement are shown")
+ StringResource(
+ "revanced_hide_get_premium_title",
+ "Hide YouTube Premium advertisement under video player"
+ ),
+ StringResource(
+ "revanced_hide_get_premium_summary_on",
+ "YouTube Premium advertisement are hidden"
+ ),
+ StringResource(
+ "revanced_hide_get_premium_summary_off",
+ "YouTube Premium advertisement are shown"
+ )
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/ExternalDownloadsCompatibility.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/ExternalDownloadsCompatibility.kt
index 5e852530..7dc840c6 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/ExternalDownloadsCompatibility.kt
@@ -5,5 +5,5 @@ 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 DownloadsCompatibility
+internal annotation class ExternalDownloadsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/ExternalDownloadsBytecodePatch.kt
similarity index 76%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/ExternalDownloadsBytecodePatch.kt
index d296b396..5d5f6965 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/ExternalDownloadsBytecodePatch.kt
@@ -9,20 +9,20 @@ 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.youtube.interaction.downloads.annotation.DownloadsCompatibility
-import app.revanced.patches.youtube.interaction.downloads.resource.patch.DownloadsResourcePatch
+import app.revanced.patches.youtube.interaction.downloads.annotation.ExternalDownloadsCompatibility
+import app.revanced.patches.youtube.interaction.downloads.resource.patch.ExternalDownloadsResourcePatch
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
@Patch
-@Name("downloads")
-@DependsOn([DownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoInformationPatch::class])
-@Description("Adds a download button to the YouTube video player.")
-@DownloadsCompatibility
+@Name("external-downloads")
+@DependsOn([ExternalDownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoInformationPatch::class])
+@Description("Adds support to download and save YouTube videos using an external app.")
+@ExternalDownloadsCompatibility
@Version("0.0.1")
-class DownloadsBytecodePatch : BytecodePatch() {
+class ExternalDownloadsBytecodePatch : BytecodePatch() {
private companion object {
- const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/DownloadButton;"
+ const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/ExternalDownloadButton;"
}
override fun execute(context: BytecodeContext): PatchResult {
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/ExternalDownloadsResourcePatch.kt
similarity index 80%
rename from src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/ExternalDownloadsResourcePatch.kt
index 4ab4a883..1a0cad41 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/ExternalDownloadsResourcePatch.kt
@@ -14,50 +14,42 @@ import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
-@Name("downloads-resource-patch")
+@Name("external-downloads-resource-patch")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
@Version("0.0.1")
-class DownloadsResourcePatch : ResourcePatch {
+class ExternalDownloadsResourcePatch : ResourcePatch {
+
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
PreferenceScreen(
"revanced_external_downloader_preference_screen",
- StringResource("revanced_external_downloader_preference_screen_title", "Download settings"),
+ StringResource("revanced_external_downloader_preference_screen_title", "External download settings"),
listOf(
SwitchPreference(
"revanced_external_downloader",
- StringResource("revanced_external_downloader_title", "Show download button"),
- StringResource("revanced_external_downloader_summary_on", "Download button is shown"),
- StringResource("revanced_external_downloader_summary_off", "Download button is not shown")
+ StringResource("revanced_external_downloader_title", "Show external download button"),
+ StringResource("revanced_external_downloader_summary_on", "Download button shown in player"),
+ StringResource("revanced_external_downloader_summary_off", "Download button not shown in player")
),
TextPreference(
"revanced_external_downloader_name",
StringResource("revanced_external_downloader_name_title", "Downloader package name"),
- StringResource("revanced_external_downloader_name_summary", "Package name of the downloader app such as NewPipe\\'s or PowerTube\\'s"),
+ StringResource("revanced_external_downloader_name_summary", "Package name of your installed external downloader app, such as NewPipe or PowerTube"),
InputType.TEXT
)
),
- StringResource("revanced_external_downloader_preference_screen_summary", "Settings related to downloads")
+ StringResource("revanced_external_downloader_preference_screen_summary", "Settings for using an external downloader")
)
)
- /*
- * Copy strings
- */
-
+ // Copy strings
context.mergeStrings("downloads/host/values/strings.xml")
- /*
- * Copy resources
- */
-
+ // Copy resources
context.copyResources("downloads", ResourceUtils.ResourceGroup("drawable", "revanced_yt_download_button.xml"))
- /*
- * Add download button node
- */
-
+ // Add download button node
BottomControlsResourcePatch.addControls("downloads/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
return PatchResultSuccess()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
index 477fdf26..c7ef6e56 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
@@ -42,7 +42,7 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
"revanced_navigation_buttons_preference_screen",
- StringResource("revanced_navigation_buttons_preference_screen_title", "Navigation button settings"),
+ StringResource("revanced_navigation_buttons_preference_screen_title", "Navigation buttons"),
listOf(
SwitchPreference(
"revanced_hide_home_button",
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
index 3b22d811..8a7d5134 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
@@ -31,6 +31,7 @@ class HidePlayerButtonsPatch : BytecodePatch(
) {
private object ParameterOffsets {
const val HAS_NEXT = 5
+ const val HAS_PREVIOUS = 6
}
override fun execute(context: BytecodeContext): PatchResult {
@@ -58,13 +59,16 @@ class HidePlayerButtonsPatch : BytecodePatch(
// overriding this parameter register hides the previous and next buttons
val hasNextParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_NEXT
+ val hasPreviousParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_PREVIOUS
mutableMethod.addInstructions(
callIndex,
"""
- invoke-static { }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->hideButtons()Z
+ invoke-static { v$hasNextParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
move-result v$hasNextParameterRegister
- xor-int/lit8 v$hasNextParameterRegister, v$hasNextParameterRegister, 1
+
+ invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
+ move-result v$hasPreviousParameterRegister
"""
)
} ?: return PlayerControlsVisibilityModelFingerprint.toErrorResult()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
index c5aa4049..5d63010c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
@@ -23,10 +23,10 @@ class HideInfocardsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
- "revanced_hide_infocards",
- StringResource("revanced_hide_infocards_title", "Hide info cards"),
- StringResource("revanced_hide_infocards_summary_on", "Info cards are hidden"),
- StringResource("revanced_hide_infocards_summary_off", "Info cards are shown")
+ "revanced_hide_info_cards",
+ StringResource("revanced_hide_info_cards_title", "Hide info cards"),
+ StringResource("revanced_hide_info_cards_summary_on", "Info cards are hidden"),
+ StringResource("revanced_hide_info_cards_summary_off", "Info cards are shown")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
index 08102a5c..7a3fde5a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
@@ -17,6 +17,7 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.seekbar.annotations.HideSeekbarCompatibility
import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
+import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@@ -24,7 +25,10 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@DependsOn([
IntegrationsPatch::class,
SettingsPatch::class,
- SeekbarColorBytecodePatch::class // Used to hide the seekbar in the feed and watch history
+ // Does not alter the behavior of the seek bar by default.
+ SeekbarColorBytecodePatch::class,
+ // Used to add preferences to the seekbar settings menu.
+ SeekbarPreferencesPatch::class
])
@Name("hide-seekbar")
@Description("Hides the seekbar.")
@@ -34,12 +38,18 @@ class HideSeekbarPatch : BytecodePatch(
listOf(SeekbarFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ SeekbarPreferencesPatch.addPreferences(
SwitchPreference(
"revanced_hide_seekbar",
- StringResource("revanced_hide_seekbar_title", "Hide seekbar"),
- StringResource("revanced_hide_seekbar_summary_on", "Seekbar is hidden"),
- StringResource("revanced_hide_seekbar_summary_off", "Seekbar is shown")
+ StringResource("revanced_hide_seekbar_title", "Hide seekbar in video player"),
+ StringResource("revanced_hide_seekbar_summary_on", "Video player seekbar is hidden"),
+ StringResource("revanced_hide_seekbar_summary_off", "Video player seekbar is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_seekbar_thumbnail",
+ StringResource("revanced_hide_seekbar_thumbnail_title", "Hide seekbar in video thumbnails"),
+ StringResource("revanced_hide_seekbar_thumbnail_summary_on", "Thumbnail seekbar is hidden"),
+ StringResource("revanced_hide_seekbar_thumbnail_summary_off", "Thumbnail seekbar is shown")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
index 29e3d149..829161c5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
@@ -18,12 +18,12 @@ class HideShortsComponentsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
- "revanced_shorts",
- StringResource("revanced_shorts_title", "Shorts components"),
+ "revanced_shorts_preference_screen",
+ StringResource("revanced_shorts_preference_screen_title", "Shorts components"),
listOf(
SwitchPreference(
"revanced_hide_shorts",
- StringResource("revanced_hide_shorts_enabled_title", "Hide shorts"),
+ StringResource("revanced_hide_shorts_title", "Hide shorts in feed"),
StringResource("revanced_hide_shorts_on", "Shorts are hidden"),
StringResource("revanced_hide_shorts_off", "Shorts are shown")
),
@@ -63,14 +63,32 @@ class HideShortsComponentsResourcePatch : ResourcePatch {
StringResource("revanced_hide_shorts_share_button_on", "Share button is hidden"),
StringResource("revanced_hide_shorts_share_button_off", "Share button is shown")
),
+ SwitchPreference(
+ "revanced_hide_shorts_info_panel",
+ StringResource("revanced_hide_shorts_info_panel_title", "Hide info panel"),
+ StringResource("revanced_hide_shorts_info_panel_on", "Info panel is hidden"),
+ StringResource("revanced_hide_shorts_info_panel_off", "Info panel is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_channel_bar",
+ StringResource("revanced_hide_shorts_channel_bar_title", "Hide channel bar"),
+ StringResource("revanced_hide_shorts_channel_bar_on", "Channel bar is hidden"),
+ StringResource("revanced_hide_shorts_channel_bar_off", "Channel bar is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_sound_button",
+ StringResource("revanced_hide_shorts_sound_button_title", "Hide sound button"),
+ StringResource("revanced_hide_shorts_sound_button_on", "Sound button is hidden"),
+ StringResource("revanced_hide_shorts_sound_button_off", "Sound button is shown")
+ ),
SwitchPreference(
"revanced_hide_shorts_navigation_bar",
StringResource("revanced_hide_shorts_navigation_bar_title", "Hide navigation bar"),
StringResource("revanced_hide_shorts_navigation_bar_on", "Navigation bar is hidden"),
StringResource("revanced_hide_shorts_navigation_bar_off", "Navigation bar is shown")
- ),
+ )
),
- StringResource("revanced_shorts_summary", "Manage the visibility of Shorts components")
+ StringResource("revanced_shorts_preference_screen_summary", "Manage the visibility of Shorts components")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/annotations/PlayerControlsBackgroundCompatibility.kt
similarity index 60%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/player/background/annotations/PlayerControlsBackgroundCompatibility.kt
index a939d9b7..ac2062c5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/annotations/PlayerControlsBackgroundCompatibility.kt
@@ -1,7 +1,7 @@
-package app.revanced.patches.youtube.layout.buttons.player.background.annotations
+package app.revanced.patches.youtube.layout.player.background.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
-internal annotation class PlayerButtonBackgroundCompatibility
+internal annotation class PlayerControlsBackgroundCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/patch/PlayerControlsBackgroundPatch.kt
similarity index 73%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/player/background/patch/PlayerControlsBackgroundPatch.kt
index ead1c865..ef8ecfbb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/patch/PlayerControlsBackgroundPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.buttons.player.background.patch
+package app.revanced.patches.youtube.layout.player.background.patch
import app.revanced.extensions.doRecursively
import app.revanced.patcher.annotation.Description
@@ -9,15 +9,15 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.buttons.player.background.annotations.PlayerButtonBackgroundCompatibility
+import app.revanced.patches.youtube.layout.player.background.annotations.PlayerControlsBackgroundCompatibility
import org.w3c.dom.Element
@Patch(false)
-@Name("remove-player-button-background")
-@Description("Removes the background from the video player buttons.")
-@PlayerButtonBackgroundCompatibility
+@Name("remove-player-controls-background")
+@Description("Removes the background from the video player controls.")
+@PlayerControlsBackgroundCompatibility
@Version("0.0.1")
-class PlayerButtonBackgroundPatch : ResourcePatch {
+class PlayerControlsBackgroundPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
editor.file.doRecursively node@{ node ->
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
index 752f23af..bf3d4cea 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
@@ -15,9 +15,9 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
+import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook
-import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.util.patch.indexOfFirstConstantInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@@ -37,7 +37,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
addInstructions(
registerIndex + 1,
"""
- invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue(I)I
+ invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
move-result v$colorRegister
"""
)
@@ -47,7 +47,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
addInstructions(
registerIndex + 1,
"""
- invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue(I)I
+ invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
move-result v$colorRegister
"""
)
@@ -66,7 +66,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
addInstructions(
0,
"""
- invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorOverride(I)I
+ invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarClickedColor(I)I
move-result v$colorRegister
"""
)
@@ -74,7 +74,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
}
} ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
- lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getSeekbarColorOverride")
+ lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getLithoColor")
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarPreferencesPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarPreferencesPatch.kt
new file mode 100644
index 00000000..17a3f168
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarPreferencesPatch.kt
@@ -0,0 +1,39 @@
+package app.revanced.patches.youtube.layout.seekbar.resource
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.BasePreference
+import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import java.io.Closeable
+
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+class SeekbarPreferencesPatch : ResourcePatch, Closeable {
+ override fun execute(context: ResourceContext): PatchResult {
+
+ // Nothing to do here. All work is done in close method.
+
+ return PatchResultSuccess()
+ }
+
+ override fun close() {
+ SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ PreferenceScreen(
+ "revanced_seekbar_preference_screen",
+ StringResource("revanced_seekbar_preference_screen_title", "Seekbar settings"),
+ seekbarPreferences
+ )
+ )
+ }
+
+ companion object {
+ private val seekbarPreferences = mutableListOf()
+
+ internal fun addPreferences(vararg preferencesToAdd: BasePreference) {
+ seekbarPreferences.addAll(preferencesToAdd)
+ }
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
index 1889ed7a..25c3a3ec 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
@@ -49,7 +49,7 @@ class ThemeBytecodePatch : BytecodePatch() {
var splashScreenBackgroundColor: String? by option(
PatchOption.StringOption(
key = "splashScreenBackgroundColor",
- default = "@android:color/black",
+ default = "?android:attr/colorBackground",
title = "Background color for the splash screen",
description = "The background color of the splash screen. Can be a hex color or a resource reference.",
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
index a6927830..83ca11e2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
@@ -9,25 +9,23 @@ import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
+import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import org.w3c.dom.Element
-@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class, SeekbarPreferencesPatch::class])
class ThemeResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
- SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ SeekbarPreferencesPatch.addPreferences(
TextPreference(
"revanced_seekbar_color",
StringResource("revanced_seekbar_color_title", "Seekbar color"),
- StringResource(
- "revanced_seekbar_color_summary",
- "The color of the seekbar"
- ),
+ StringResource("revanced_seekbar_color_summary", "The color of the seekbar"),
InputType.TEXT_CAP_CHARACTERS
- ),
+ )
)
// Edit theme colors via resources.
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt
new file mode 100644
index 00000000..87607a77
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/APIPlayerServiceFingerprint.kt
@@ -0,0 +1,17 @@
+package app.revanced.patches.youtube.misc.integrations.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import org.jf.dexlib2.AccessFlags
+
+/**
+ * For embedded playback.
+ * It appears this hook may no longer be needed as one of the constructor parameters is the already hooked
+ * [EmbeddedPlayerControlsOverlayFingerprint]
+ */
+object APIPlayerServiceFingerprint : IntegrationsFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ customFingerprint = { methodDef, _ -> methodDef.definingClass == "Lcom/google/android/apps/youtube/embeddedplayer/service/service/jar/ApiPlayerService;" },
+ // Integrations context is the first method parameter.
+ contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt
similarity index 51%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt
index be3b5d8b..7adb101c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ApplicationInitFingerprint.kt
@@ -2,6 +2,10 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
-object InitFingerprint : IntegrationsFingerprint(
+/**
+ * Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
+ */
+object ApplicationInitFingerprint : IntegrationsFingerprint(
strings = listOf("Application creation", "Application.onCreate"),
+ // Integrations context is the Activity itself.
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
index 395fd022..80e47746 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
@@ -4,12 +4,19 @@ import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import org.jf.dexlib2.AccessFlags
+/**
+ * For embedded playback inside Google Play store (and probably other situations as well).
+ *
+ * Note: this fingerprint may no longer be needed, as it appears
+ * [RemoteEmbedFragmentFingerprint] may be set before this hook is called.
+ */
object EmbeddedPlayerControlsOverlayFingerprint : IntegrationsFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
returnType = "V",
- parameters = listOf("L", "L", "L"),
+ parameters = listOf("Landroid/content/Context;", "L", "L"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.startsWith("Lcom/google/android/apps/youtube/embeddedplayer/service/ui/overlays/controlsoverlay/remoteloaded/")
},
+ // Integrations context is the first method parameter.
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt
new file mode 100644
index 00000000..76615647
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerFingerprint.kt
@@ -0,0 +1,20 @@
+package app.revanced.patches.youtube.misc.integrations.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import org.jf.dexlib2.AccessFlags
+
+/**
+ * For embedded playback inside the Google app (such as the in app 'discover' tab).
+ *
+ * Note: this fingerprint may or may not be needed, as
+ * [RemoteEmbedFragmentFingerprint] might be set before this is called.
+ */
+object EmbeddedPlayerFingerprint : IntegrationsFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ returnType = "L",
+ parameters = listOf("L", "L", "Landroid/content/Context;"),
+ strings = listOf("android.hardware.type.television"), // String is also found in other classes
+ // Integrations context is the third method parameter.
+ contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size + 2 }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt
new file mode 100644
index 00000000..e719289f
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbedFragmentFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.misc.integrations.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import org.jf.dexlib2.AccessFlags
+
+/**
+ * For embedded playback. Likely covers Google Play store and other Google products.
+ */
+object RemoteEmbedFragmentFingerprint : IntegrationsFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ returnType = "V",
+ parameters = listOf("Landroid/content/Context;", "L", "L"),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/google/android/apps/youtube/embeddedplayer/service/jar/client/RemoteEmbedFragment;"
+ },
+ // Integrations context is the first method parameter.
+ contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt
new file mode 100644
index 00000000..6a16bf26
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/RemoteEmbeddedPlayerFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.misc.integrations.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import org.jf.dexlib2.AccessFlags
+
+/**
+ * For embedded playback inside 3rd party android app (such as 3rd party Reddit apps).
+ */
+object RemoteEmbeddedPlayerFingerprint : IntegrationsFingerprint(
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
+ returnType = "V",
+ parameters = listOf("Landroid/content/Context;", "L", "L", "Z"),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/google/android/youtube/api/jar/client/RemoteEmbeddedPlayer;"
+ },
+ // Integrations context is the first method parameter.
+ contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt
deleted file mode 100644
index dd5868d7..00000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.revanced.patches.youtube.misc.integrations.fingerprints
-
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
-
-object ServiceFingerprint : IntegrationsFingerprint(
- customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "" },
- contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt
new file mode 100644
index 00000000..799b80ee
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt
@@ -0,0 +1,18 @@
+package app.revanced.patches.youtube.misc.integrations.fingerprints
+
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+
+/**
+ * Old API activity to embed YouTube into 3rd party Android apps.
+ *
+ * In 2023 supported was ended and is no longer available,
+ * but this may still be used by older apps:
+ * https://developers.google.com/youtube/android/player
+ */
+object StandalonePlayerActivityFingerprint : IntegrationsFingerprint(
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/google/android/youtube/api/StandalonePlayerActivity;"
+ && methodDef.name == "onCreate"
+ },
+ // Integrations context is the Activity itself.
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt
deleted file mode 100644
index ff710614..00000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package app.revanced.patches.youtube.misc.integrations.fingerprints
-
-import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
-
-object StandalonePlayerFingerprint : IntegrationsFingerprint(
- strings = listOf(
- "Invalid PlaybackStartDescriptor. Returning the instance itself.",
- "com.google.android.music",
- ),
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
index 10a9dc93..aeaba895 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
@@ -4,15 +4,26 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility
-import app.revanced.patches.youtube.misc.integrations.fingerprints.InitFingerprint
import app.revanced.patches.youtube.misc.integrations.fingerprints.EmbeddedPlayerControlsOverlayFingerprint
-import app.revanced.patches.youtube.misc.integrations.fingerprints.ServiceFingerprint
-import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.EmbeddedPlayerFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.ApplicationInitFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.RemoteEmbedFragmentFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.RemoteEmbeddedPlayerFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.APIPlayerServiceFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerActivityFingerprint
@Name("integrations")
@IntegrationsCompatibility
@RequiresIntegrations
class IntegrationsPatch : AbstractIntegrationsPatch(
"Lapp/revanced/integrations/utils/ReVancedUtils;",
- listOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint, EmbeddedPlayerControlsOverlayFingerprint),
+ listOf(
+ ApplicationInitFingerprint,
+ StandalonePlayerActivityFingerprint,
+ RemoteEmbeddedPlayerFingerprint,
+ RemoteEmbedFragmentFingerprint,
+ EmbeddedPlayerControlsOverlayFingerprint,
+ EmbeddedPlayerFingerprint,
+ APIPlayerServiceFingerprint,
+ ),
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
index 635563bf..609230e8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
@@ -51,7 +51,7 @@ class RememberVideoQualityPatch : BytecodePatch(
StringResource("revanced_video_quality_default_entry_5", "720p"),
StringResource("revanced_video_quality_default_entry_6", "480p"),
StringResource("revanced_video_quality_default_entry_7", "360p"),
- StringResource("revanced_video_quality_default_entry_8", "280p"),
+ StringResource("revanced_video_quality_default_entry_8", "240p"),
StringResource("revanced_video_quality_default_entry_9", "144p"),
)
val entryValues = listOf(
@@ -62,7 +62,7 @@ class RememberVideoQualityPatch : BytecodePatch(
StringResource("revanced_video_quality_default_entry_value_5", "720"),
StringResource("revanced_video_quality_default_entry_value_6", "480"),
StringResource("revanced_video_quality_default_entry_value_7", "360"),
- StringResource("revanced_video_quality_default_entry_value_8", "280"),
+ StringResource("revanced_video_quality_default_entry_value_8", "240"),
StringResource("revanced_video_quality_default_entry_value_9", "144"),
)
diff --git a/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt b/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt
index 3a1b8f23..a8354c6b 100644
--- a/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt
+++ b/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt
@@ -21,39 +21,44 @@ internal abstract class AbstractTransformInstructionsPatch : BytecodePatch()
abstract fun transform(mutableMethod: MutableMethod, entry: T)
+ // Returns the patch indices as a Sequence, which will execute lazily.
+ private fun findPatchIndices(classDef: ClassDef, method: Method): Sequence? {
+ return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
+ filterMap(classDef, method, instruction, index)
+ }
+ }
+
override fun execute(context: BytecodeContext): PatchResult {
- // Find all instructions
+ // Find all methods to patch
buildMap {
context.classes.forEach { classDef ->
- classDef.methods.let { methods ->
- buildMap methodList@{
- methods.forEach methods@{ method ->
- with(method.implementation?.instructions ?: return@methods) {
- ArrayDeque().also { patchIndices ->
- this.forEachIndexed { index, instruction ->
- val result = filterMap(classDef, method, instruction, index)
- if (result != null) {
- patchIndices.add(result)
- }
- }
- }.also { if (it.isEmpty()) return@methods }.let { patches ->
- put(method, patches)
- }
- }
+ val methods = buildList {
+ classDef.methods.forEach { method ->
+ // Since the Sequence executes lazily,
+ // using any() results in only calling
+ // filterMap until the first index has been found.
+ val patchIndices = findPatchIndices(classDef, method)
+
+ if (patchIndices?.any() == true) {
+ add(method)
}
}
- }.also { if (it.isEmpty()) return@forEach }.let { methodPatches ->
- put(classDef, methodPatches)
+ }
+
+ if (methods.isNotEmpty()) {
+ put(classDef, methods)
}
}
}.forEach { (classDef, methods) ->
- // And finally transform the instructions...
- with(context.proxy(classDef).mutableClass) {
- methods.forEach { (method, patches) ->
- val mutableMethod = findMutableMethodOf(method)
- while (!patches.isEmpty()) {
- transform(mutableMethod, patches.removeLast())
- }
+ // And finally transform the methods...
+ val mutableClass = context.proxy(classDef).mutableClass
+
+ methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
+ val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
+ ?: return@methods
+
+ while (!patchIndices.isEmpty()) {
+ transform(mutableMethod, patchIndices.removeLast())
}
}
}
diff --git a/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml b/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml
index 23254785..419845aa 100644
--- a/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml
+++ b/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/src/main/resources/downloads/host/values/strings.xml b/src/main/resources/downloads/host/values/strings.xml
index 957d490f..dcdfd275 100644
--- a/src/main/resources/downloads/host/values/strings.xml
+++ b/src/main/resources/downloads/host/values/strings.xml
@@ -1,4 +1,4 @@
- is not installed. Please install it.
+ is not installed. Please install it.