diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f32303..d0fe67ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ +# [2.159.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.159.0-dev.3...v2.159.0-dev.4) (2023-02-03) + + +### Features + +* **netguard:** `remove-broadcasts-restriction` patch ([#1581](https://github.com/revanced/revanced-patches/issues/1581)) ([73132e3](https://github.com/revanced/revanced-patches/commit/73132e37cf83f4c1f05cf6a184dfd8e454f7456e)) + +# [2.159.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.159.0-dev.2...v2.159.0-dev.3) (2023-02-03) + + +### Features + +* **youtube:** `hide-player-buttons` patch ([3469d37](https://github.com/revanced/revanced-patches/commit/3469d37bcedfd2dfbe46231b17cd098b591810c1)) + +# [2.159.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.159.0-dev.1...v2.159.0-dev.2) (2023-02-01) + + +### Features + +* `spoof-wifi-connection` patch ([#1527](https://github.com/revanced/revanced-patches/issues/1527)) ([adce206](https://github.com/revanced/revanced-patches/commit/adce206d66e1f7017328fe68a5818d424f70e588)) + +# [2.159.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.158.0...v2.159.0-dev.1) (2023-02-01) + + +### Bug Fixes + +* **youtube/custom-branding:** correct scaling, margin and images ([#1580](https://github.com/revanced/revanced-patches/issues/1580)) ([491c413](https://github.com/revanced/revanced-patches/commit/491c4138f0185664a9c5d3db9ebdf026ff4594e8)) + + +### Features + +* **music:** bump patches compatibility to v5.41.50 ([#1551](https://github.com/revanced/revanced-patches/issues/1551)) ([0b1024a](https://github.com/revanced/revanced-patches/commit/0b1024ab754a3e2ce798a54cccda6f41f97069a5)) +* **spotify-lite:** enable on-demand patch ([9f0de4f](https://github.com/revanced/revanced-patches/commit/9f0de4f5678e9f57baaf6ec788821641d75defdc)) + # [2.158.0](https://github.com/revanced/revanced-patches/compare/v2.157.0...v2.158.0) (2023-01-29) diff --git a/README.md b/README.md index ffef3c48..9f6ea51a 100644 --- a/README.md +++ b/README.md @@ -38,15 +38,16 @@ The official Patch bundle provided by ReVanced and the community. | `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.03.36 | | `hide-info-cards` | Hides info-cards in videos. | 18.03.36 | | `hide-my-mix` | Hides mix playlists. | 18.03.36 | +| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | all | | `hide-shorts-button` | Hides the shorts button on the navigation bar. | 18.03.36 | | `hide-time-and-seekbar` | Hides progress bar and time counter on videos. | 18.03.36 | -| `hide-video-buttons` | Adds options to hide action buttons under a video. | 18.03.36 | +| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.03.36 | | `hide-watch-in-vr` | Hides the Watch in VR option in the player settings flyout panel. | 18.03.36 | | `hide-watermark` | Hides creator's watermarks on videos. | 18.03.36 | | `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.03.36 | | `minimized-playback` | Enables minimized and background playback. | 18.03.36 | | `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.03.36 | -| `open-links-directly` | Bypasses https://youtube.com/redirect URLs. | 18.03.36 | +| `open-links-directly` | Skips over redirection URLs to external links. | 18.03.36 | | `open-links-externally` | Open links outside of the app directly in your browser. | 18.03.36 | | `premium-heading` | Shows premium branding on the home screen. | all | | `remember-playback-rate` | Adds the ability to remember the playback rate you chose in the video playback rate flyout. | 18.03.36 | @@ -54,7 +55,7 @@ The official Patch bundle provided by ReVanced and the community. | `remove-player-button-background` | Removes the background from the video player buttons. | 18.03.36 | | `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.03.36 | | `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.03.36 | -| `sponsorblock` | Integrate SponsorBlock. | 18.03.36 | +| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.03.36 | | `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.03.36 | | `swipe-controls` | Adds volume and brightness swipe controls. | 18.03.36 | | `tablet-mini-player` | Enables the tablet mini player layout. | 18.03.36 | @@ -160,7 +161,7 @@ The official Patch bundle provided by ReVanced and the community. | 💊 Patch | 📜 Description | 🏹 Target Version | |:--------:|:--------------:|:-----------------:| | `remove-bootloader-detection` | Removes the check for an unlocked bootloader. | 2.2.0 | -| `remove-root-detection` | Removes the check for root permissions | 2.2.0 | +| `remove-root-detection` | Removes the check for root permissions. | 2.2.0 | </details> ### [📦 `at.gv.oe.app`](https://play.google.com/store/apps/details?id=at.gv.oe.app) @@ -188,6 +189,14 @@ The official Patch bundle provided by ReVanced and the community. | `disable-ads` | Disables ads in HexEditor. | all | </details> +### [📦 `com.spotify.lite`](https://play.google.com/store/apps/details?id=com.spotify.lite) +<details> + +| 💊 Patch | 📜 Description | 🏹 Target Version | +|:--------:|:--------------:|:-----------------:| +| `enable-on-demand` | Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads. | all | +</details> + ### [📦 `org.citra.citra_emu`](https://play.google.com/store/apps/details?id=org.citra.citra_emu) <details> @@ -228,6 +237,14 @@ The official Patch bundle provided by ReVanced and the community. | `remove-ads` | Removes all ads from the app. | all | </details> +### [📦 `eu.faircode.netguard`](https://play.google.com/store/apps/details?id=eu.faircode.netguard) +<details> + +| 💊 Patch | 📜 Description | 🏹 Target Version | +|:--------:|:--------------:|:-----------------:| +| `remove-broadcasts-restriction` | Enables starting/stopping NetGuard via broadcasts. | all | +</details> + ### [📦 `com.teslacoilsw.launcher`](https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher) <details> diff --git a/gradle.properties b/gradle.properties index 68098c7e..7e4db9fb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ kotlin.code.style = official -version = 2.158.0 +version = 2.159.0-dev.4 diff --git a/patches.json b/patches.json index 5f2b2ae6..61411d1f 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":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"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":[]}]},{"name":"block-embedded-ads","description":"Blocks embedded steam 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":[]}]},{"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":[]}]},{"name":"client-spoof","description":"Spoofs the YouTube or Vanced client to prevent playback issues.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]},{"name":"com.vanced.android.youtube","versions":[]}]},{"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":["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"]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","comments-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["5.14.53","5.16.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"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["locale-config-fix"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"custom-video-buffer","description":"Lets you change the buffers of videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"custom-video-speed","description":"Adds more video speed options.","version":"0.0.1","excluded":false,"options":[{"key":"granularity","title":"Video speed granularity","description":"The granularity of the video speeds. The higher the value, the more speeds will be available.","required":true,"choices":null},{"key":"min","title":"Minimum video speed","description":"The minimum video speed.","required":true,"choices":null},{"key":"max","title":"Maximum video speed","description":"The maximum video speed. Must be greater than the minimum video speed and smaller than 5.","required":true,"choices":null}],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":"debugging","description":"Adds debugging options.","version":"0.0.1","excluded":false,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","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":["17.49.37","18.03.36"]}]},{"name":"disable-auto-player-popup-panels","description":"Disable automatic popup panels (playlist or live chat) on video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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-startup-shorts-player","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":["17.49.37","18.03.36"]}]},{"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":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"downloads","description":"Enables downloading music and videos from YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-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":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"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":"general-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["GeneralAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"general-reddit-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":["2022.43.0"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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-create-button","description":"Hides the create button in the navigation bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","resource-mapping","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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-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":["17.49.37","18.03.36"]}]},{"name":"hide-my-mix","description":"Hides mix playlists.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-shorts-button","description":"Hides the shorts button on the navigation bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"hide-time-and-seekbar","description":"Hides progress bar and time counter on videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"hide-video-buttons","description":"Adds 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":["17.49.37","18.03.36"]}]},{"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"]}]},{"name":"hide-watch-in-vr","description":"Hides the Watch in VR option in the player settings flyout panel.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"name":"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":["17.49.37","18.03.36"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"name":"monochrome-icon","description":"Adds a monochrome icon.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","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":["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"]}]},{"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":["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"]}]},{"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","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"open-links-directly","description":"Bypasses https://youtube.com/redirect URLs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["locale-config-fix"],"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":[]}]},{"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-playback-rate","description":"Adds the ability to remember the playback rate you chose in the video playback rate flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-id-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-player-button-background","description":"Removes the background from the video player buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["locale-config-fix"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-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":["2.5.2"]}]},{"name":"remove-screenshot-restriction","description":"Removes the restriction of making screenshots.","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":["17.49.37","18.03.36"]}]},{"name":"seekbar-tapping","description":"Enables tap-to-seek on the seekbar of the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":"settings","description":"Adds settings menu to Twitch.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-deleted-messages","description":"Shows deleted chat messages behind a clickable spoiler.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"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":"Integrate SponsorBlock.","version":"0.0.1","excluded":false,"options":[],"dependencies":["video-information","player-controls-bytecode-patch","player-type-hook","integrations","sponsorblock-resource-patch","video-id-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["2.5.2"]}]},{"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":["locale-config-fix"],"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"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":"darkThemeSeekbarColor","title":"Dark theme seekbar color","description":"The background color of the seekbar of the dark theme. Leave empty for default color.","required":false,"choices":null}],"dependencies":["litho-components-theme","locale-config-fix"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"timeline-ads","description":"Removes ads from the Twitter timeline. Might require clearing app data to remove already cached ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.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 all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all professional features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"unlock-themes","description":"Unlocks all themes.","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":["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"]}]},{"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":["17.49.37","18.03.36"]}]}] \ 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":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"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":[]}]},{"name":"block-embedded-ads","description":"Blocks embedded steam 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":[]}]},{"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":[]}]},{"name":"client-spoof","description":"Spoofs the YouTube or Vanced client to prevent playback issues.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]},{"name":"com.vanced.android.youtube","versions":[]}]},{"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":["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"]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","comments-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["5.14.53","5.16.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"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"custom-video-speed","description":"Adds more video speed options.","version":"0.0.1","excluded":false,"options":[{"key":"granularity","title":"Video speed granularity","description":"The granularity of the video speeds. The higher the value, the more speeds will be available.","required":true,"choices":null},{"key":"min","title":"Minimum video speed","description":"The minimum video speed.","required":true,"choices":null},{"key":"max","title":"Maximum video speed","description":"The maximum video speed. Must be greater than the minimum video speed and smaller than 5.","required":true,"choices":null}],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":"debugging","description":"Adds debugging options.","version":"0.0.1","excluded":false,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","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":["17.49.37","18.03.36"]}]},{"name":"disable-auto-player-popup-panels","description":"Disable automatic popup panels (playlist or live chat) on video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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-startup-shorts-player","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":["17.49.37","18.03.36"]}]},{"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":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"downloads","description":"Enables downloading music and videos from YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-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":"enable-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":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"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":"general-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["GeneralAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"general-reddit-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":["2022.43.0"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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-create-button","description":"Hides the create button in the navigation bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","resource-mapping","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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-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":["17.49.37","18.03.36"]}]},{"name":"hide-my-mix","description":"Hides mix playlists.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":[]}]},{"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-shorts-button","description":"Hides the shorts button on the navigation bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"hide-time-and-seekbar","description":"Hides progress bar and time counter on videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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"]}]},{"name":"hide-watch-in-vr","description":"Hides the Watch in VR option in the player settings flyout panel.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"name":"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":["17.49.37","18.03.36"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"name":"monochrome-icon","description":"Adds a monochrome icon.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","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":["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"]}]},{"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":["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"]}]},{"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","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"name":"open-links-directly","description":"Skips over redirection URLs to external links.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":[]}]},{"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-playback-rate","description":"Adds the ability to remember the playback rate you chose in the video playback rate flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-id-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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-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":["2.5.2"]}]},{"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":["17.49.37","18.03.36"]}]},{"name":"seekbar-tapping","description":"Enables tap-to-seek on the seekbar of the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":"settings","description":"Adds settings menu to Twitch.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-deleted-messages","description":"Shows deleted chat messages behind a clickable spoiler.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"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":["video-information","player-controls-bytecode-patch","player-type-hook","integrations","sponsorblock-resource-patch","video-id-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["2.5.2"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["17.49.37","18.03.36"]}]},{"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":["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"]}]},{"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":"darkThemeSeekbarColor","title":"Dark theme seekbar color","description":"The background color of the seekbar of the dark theme. Leave empty for default color.","required":false,"choices":null}],"dependencies":["litho-components-theme"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"timeline-ads","description":"Removes ads from the Twitter timeline. Might require clearing app data to remove already cached ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.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 all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all professional features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"unlock-themes","description":"Unlocks all themes.","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":["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"]}]},{"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":["17.49.37","18.03.36"]}]}] \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/patch/SpoofWifiPatch.kt b/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/patch/SpoofWifiPatch.kt new file mode 100644 index 00000000..0c6bdeae --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/all/connectivity/wifi/spoof/patch/SpoofWifiPatch.kt @@ -0,0 +1,206 @@ +package app.revanced.patches.all.connectivity.wifi.spoof.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.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.util.patch.* +import org.jf.dexlib2.iface.ClassDef +import org.jf.dexlib2.iface.Method +import org.jf.dexlib2.iface.instruction.Instruction +import java.util.* + +@Patch(false) +@Name("spoof-wifi-connection") +@Description("Spoofs an existing Wi-Fi connection.") +@Version("0.0.1") +internal class SpoofWifiPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() { + + private companion object { + const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch" + const val INTEGRATIONS_CLASS_DESCRIPTOR = "${INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX};" + } + + // Information about method calls we want to replace + enum class MethodCall( + override val definedClassName: String, + override val methodName: String, + override val methodParams: Array<String>, + override val returnType: String, + ): IMethodCall { + GetSystemService1( + "Landroid/content/Context;", + "getSystemService", + arrayOf("Ljava/lang/String;"), + "Ljava/lang/Object;", + ), + GetSystemService2( + "Landroid/content/Context;", + "getSystemService", + arrayOf("Ljava/lang/Class;"), + "Ljava/lang/Object;", + ), + GetActiveNetworkInfo( + "Landroid/net/ConnectivityManager;", + "getActiveNetworkInfo", + arrayOf(), + "Landroid/net/NetworkInfo;", + ), + IsConnected( + "Landroid/net/NetworkInfo;", + "isConnected", + arrayOf(), + "Z", + ), + IsConnectedOrConnecting( + "Landroid/net/NetworkInfo;", + "isConnectedOrConnecting", + arrayOf(), + "Z", + ), + IsAvailable( + "Landroid/net/NetworkInfo;", + "isAvailable", + arrayOf(), + "Z", + ), + GetState( + "Landroid/net/NetworkInfo;", + "getState", + arrayOf(), + "Landroid/net/NetworkInfo\$State;", + ), + GetDetailedState( + "Landroid/net/NetworkInfo;", + "getDetailedState", + arrayOf(), + "Landroid/net/NetworkInfo\$DetailedState;", + ), + IsActiveNetworkMetered( + "Landroid/net/ConnectivityManager;", + "isActiveNetworkMetered", + arrayOf(), + "Z", + ), + GetActiveNetwork( + "Landroid/net/ConnectivityManager;", + "getActiveNetwork", + arrayOf(), + "Landroid/net/Network;", + ), + GetNetworkInfo( + "Landroid/net/ConnectivityManager;", + "getNetworkInfo", + arrayOf("Landroid/net/Network;"), + "Landroid/net/NetworkInfo;", + ), + HasTransport( + "Landroid/net/NetworkCapabilities;", + "hasTransport", + arrayOf("I"), + "Z", + ), + HasCapability( + "Landroid/net/NetworkCapabilities;", + "hasCapability", + arrayOf("I"), + "Z", + ), + RegisterBestMatchingNetworkCallback( + "Landroid/net/ConnectivityManager;", + "registerBestMatchingNetworkCallback", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), + "V", + ), + RegisterDefaultNetworkCallback1( + "Landroid/net/ConnectivityManager;", + "registerDefaultNetworkCallback", + arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"), + "V", + ), + RegisterDefaultNetworkCallback2( + "Landroid/net/ConnectivityManager;", + "registerDefaultNetworkCallback", + arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), + "V", + ), + RegisterNetworkCallback1( + "Landroid/net/ConnectivityManager;", + "registerNetworkCallback", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"), + "V", + ), + RegisterNetworkCallback2( + "Landroid/net/ConnectivityManager;", + "registerNetworkCallback", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/app/PendingIntent;"), + "V", + ), + RegisterNetworkCallback3( + "Landroid/net/ConnectivityManager;", + "registerNetworkCallback", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), + "V", + ), + RequestNetwork1( + "Landroid/net/ConnectivityManager;", + "requestNetwork", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"), + "V", + ), + RequestNetwork2( + "Landroid/net/ConnectivityManager;", + "requestNetwork", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "I"), + "V", + ), + RequestNetwork3( + "Landroid/net/ConnectivityManager;", + "requestNetwork", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), + "V", + ), + RequestNetwork4( + "Landroid/net/ConnectivityManager;", + "requestNetwork", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/app/PendingIntent;"), + "V", + ), + RequestNetwork5( + "Landroid/net/ConnectivityManager;", + "requestNetwork", + arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;", "I"), + "V", + ), + UnregisterNetworkCallback1( + "Landroid/net/ConnectivityManager;", + "unregisterNetworkCallback", + arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"), + "V", + ), + UnregisterNetworkCallback2( + "Landroid/net/ConnectivityManager;", + "unregisterNetworkCallback", + arrayOf("Landroid/app/PendingIntent;"), + "V", + ); + } + + override fun filterMap( + classDef: ClassDef, + method: Method, + instruction: Instruction, + instructionIndex: Int + ) = filterMapInstruction35c<MethodCall>( + INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX, + classDef, + instruction, + instructionIndex + ) + + override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) { + val (methodType, instruction, instructionIndex) = entry + methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex) + } +} diff --git a/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt b/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt index c3d2f86e..b9f26c99 100644 --- a/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/all/screenshot/removerestriction/patch/RemoveScreenshotRestrictionPatch.kt @@ -1,106 +1,57 @@ package app.revanced.patches.all.screenshot.removerestriction.patch -import app.revanced.extensions.findMutableMethodOf 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.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.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.Instruction35c -import org.jf.dexlib2.iface.reference.MethodReference +import app.revanced.util.patch.* +import org.jf.dexlib2.iface.ClassDef +import org.jf.dexlib2.iface.Method +import org.jf.dexlib2.iface.instruction.Instruction +import java.util.* @Patch(false) @Name("remove-screenshot-restriction") -@Description("Removes the restriction of making screenshots.") +@Description("Removes the restriction of taking screenshots in apps that normally wouldn't allow it.") @Version("0.0.1") -class RemoveScreenshotRestrictionPatch : BytecodePatch() { +internal class RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() { private companion object { - const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch;" + const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = + "Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch" + const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;" } // Information about method calls we want to replace - private enum class MethodCall( - val definedClassName: String, - val methodName: String, - val replacementMethodDefinition: String - ) { + enum class MethodCall( + override val definedClassName: String, + override val methodName: String, + override val methodParams: Array<String>, + override val returnType: String + ): IMethodCall { SetFlags( "Landroid/view/Window;", "setFlags", - "setFlags(Landroid/view/Window;II)V", + arrayOf("I", "I"), + "V", ); - - fun replaceInstruction(method: MutableMethod, instruction: Instruction35c, instructionIndex: Int) { - when (this) { - SetFlags -> { - method.replaceInstruction( - instructionIndex, - "invoke-static { v${instruction.registerC}, v${instruction.registerD}, v${instruction.registerE} }, ${INTEGRATIONS_CLASS_DESCRIPTOR}->${replacementMethodDefinition}" - ) - } - } - } - - companion object { - fun fromMethodReference(methodReference: MethodReference) = values().firstOrNull { search -> - search.definedClassName == methodReference.definingClass && search.methodName == methodReference.name - } - } } - override fun execute(context: BytecodeContext): PatchResult { - // Find all instructions where one of the methods is called - buildMap { - context.classes.forEach { classDef -> - if (classDef.type == INTEGRATIONS_CLASS_DESCRIPTOR) { - // avoid infinite recursion - return@forEach - } + override fun filterMap( + classDef: ClassDef, + method: Method, + instruction: Instruction, + instructionIndex: Int + ) = filterMapInstruction35c<MethodCall>( + INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX, + classDef, + instruction, + instructionIndex + ) - classDef.methods.let { methods -> - buildMap methodList@{ - methods.forEach methods@{ method -> - with(method.implementation?.instructions ?: return@methods) { - ArrayDeque<Triple<MethodCall, Instruction35c, Int>>().also { patchIndices -> - this.forEachIndexed { index, instruction -> - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed - - val invokeInstruction = instruction as Instruction35c - val methodRef = invokeInstruction.reference as MethodReference - val methodCall = MethodCall.fromMethodReference(methodRef) ?: return@forEachIndexed - - patchIndices.add(Triple(methodCall, invokeInstruction, index)) - } - }.also { if (it.isEmpty()) return@methods }.let { patches -> - put(method, patches) - } - } - } - } - }.also { if (it.isEmpty()) return@forEach }.let { methodPatches -> - put(classDef, methodPatches) - } - } - }.forEach { (classDef, methods) -> - // And finally replace the instructions... - with(context.proxy(classDef).mutableClass) { - methods.forEach { (method, patches) -> - val mutableMethod = findMutableMethodOf(method) - while (!patches.isEmpty()) { - val (methodType, instruction, instructionIndex) = patches.removeLast() - methodType.replaceInstruction(mutableMethod, instruction, instructionIndex) - } - } - } - } - - return PatchResultSuccess() + override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) { + val (methodType, instruction, instructionIndex) = entry + methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex) } } diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt index 216ba2cd..4995e070 100644 --- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/patch/RootDetectionPatch.kt @@ -15,7 +15,7 @@ import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionC @Patch @Name("remove-root-detection") -@Description("Removes the check for root permissions") +@Description("Removes the check for root permissions.") @DetectionCompatibility @Version("0.0.1") class RootDetectionPatch : BytecodePatch( diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt index 674d9112..46380e54 100644 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt @@ -24,7 +24,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt index f7845cbe..9d12ae27 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt @@ -24,7 +24,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt index e2209b59..81262914 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt @@ -24,7 +24,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt index ec3539ed..80012565 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt @@ -23,7 +23,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt index 7216851b..691da156 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt @@ -24,7 +24,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt index 650674b2..d5f2bd0b 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt @@ -26,7 +26,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt index e6aca8df..73efd97b 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt @@ -24,7 +24,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt index 571ac001..c80a2483 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt @@ -22,9 +22,10 @@ import app.revanced.patcher.annotation.Package "5.31.50", "5.34.51", "5.36.51", - "5.38.53", - "5.39.52", - "5.40.51" + "5.38.53", + "5.39.52", + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt index 3dd028e2..c857e828 100644 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt @@ -24,7 +24,8 @@ import app.revanced.patcher.annotation.Package "5.36.51", "5.38.53", "5.39.52", - "5.40.51" + "5.40.51", + "5.41.50" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/annotations/RemoveBroadcastsRestrictionCompatibility.kt b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/annotations/RemoveBroadcastsRestrictionCompatibility.kt new file mode 100644 index 00000000..0a8a7e56 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/annotations/RemoveBroadcastsRestrictionCompatibility.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.netguard.broadcasts.removerestriction.resource.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility([Package("eu.faircode.netguard")]) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class RemoveBroadcastsRestrictionCompatibility diff --git a/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/patch/RemoveBroadcastsRestrictionPatch.kt b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/patch/RemoveBroadcastsRestrictionPatch.kt new file mode 100644 index 00000000..728e4481 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/netguard/broadcasts/removerestriction/resource/patch/RemoveBroadcastsRestrictionPatch.kt @@ -0,0 +1,40 @@ +package app.revanced.patches.netguard.broadcasts.removerestriction.resource.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.ResourcePatch +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.netguard.broadcasts.removerestriction.resource.annotations.RemoveBroadcastsRestrictionCompatibility +import org.w3c.dom.Element + +@Patch(false) +@Name("remove-broadcasts-restriction") +@Description("Enables starting/stopping NetGuard via broadcasts.") +@RemoveBroadcastsRestrictionCompatibility +@Version("0.0.1") +class RemoveBroadcastsRestrictionPatch : ResourcePatch { + override fun execute(context: ResourceContext): PatchResult { + context.xmlEditor["AndroidManifest.xml"].use { dom -> + val applicationNode = dom + .file + .getElementsByTagName("application") + .item(0) as Element + + applicationNode.getElementsByTagName("receiver").also { list -> + for (i in 0 until list.length) { + val element = list.item(i) as? Element ?: continue + if (element.getAttribute("android:name") == "eu.faircode.netguard.WidgetAdmin") { + element.removeAttribute("android:permission") + break + } + } + } + } + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt index dfbc7fd1..731f1b3d 100644 --- a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt +++ b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt @@ -5,14 +5,11 @@ import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.spotify.layout.theme.annotations.ThemeCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import org.w3c.dom.Element @Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) @Name("spotify-theme") @Description("Applies a custom theme.") @ThemeCompatibility diff --git a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/annotations/OnDemandCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/annotations/OnDemandCompatibility.kt new file mode 100644 index 00000000..741e23b8 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/annotations/OnDemandCompatibility.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.spotify.lite.ondemand.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package("com.spotify.lite")] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class OnDemandCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/fingerprints/OnDemandFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/fingerprints/OnDemandFingerprint.kt new file mode 100644 index 00000000..099eaa43 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/fingerprints/OnDemandFingerprint.kt @@ -0,0 +1,25 @@ +package app.revanced.patches.spotify.lite.ondemand.fingerprints + +import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +@FuzzyPatternScanMethod(2) +object OnDemandFingerprint : MethodFingerprint( + "L", + parameters = listOf(), + opcodes = listOf( + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_EQZ, + Opcode.SGET_OBJECT, + Opcode.GOTO, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IPUT, + Opcode.RETURN_OBJECT + ) +) diff --git a/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/patch/OnDemandPatch.kt b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/patch/OnDemandPatch.kt new file mode 100644 index 00000000..bbb5159e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/patch/OnDemandPatch.kt @@ -0,0 +1,34 @@ +package app.revanced.patches.spotify.lite.ondemand.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.addInstruction +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.spotify.lite.ondemand.annotations.OnDemandCompatibility +import app.revanced.patches.spotify.lite.ondemand.fingerprints.OnDemandFingerprint + +@Patch +@Name("enable-on-demand") +@Description("Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.") +@OnDemandCompatibility +@Version("0.0.1") +class OnDemandPatch : BytecodePatch( + listOf( + OnDemandFingerprint + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + OnDemandFingerprint.result?.apply { + val insertIndex = scanResult.patternScanResult!!.endIndex - 1 + // Spoof a premium account + mutableMethod.addInstruction(insertIndex, "const/4 v0, 0x2") + } ?: return OnDemandFingerprint.toErrorResult() + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt index bfbf411b..734869dc 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt @@ -10,13 +10,11 @@ import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.settings.preference.impl.* import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen @DependsOn( dependencies = [ - FixLocaleConfigErrorPatch::class, LithoFilterPatch::class, SettingsPatch::class, ResourceMappingPatch::class diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt index de4a3c52..6e60282c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt @@ -12,7 +12,6 @@ import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.youtube.interaction.copyvideourl.annotation.CopyVideoUrlCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.util.resources.ResourceUtils @@ -20,7 +19,7 @@ import app.revanced.util.resources.ResourceUtils.copyResources @Name("copy-video-url-resource") @Description("Makes necessary changes to resources for copy video link buttons.") -@DependsOn([BottomControlsResourcePatch::class, FixLocaleConfigErrorPatch::class, SettingsPatch::class]) +@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class]) @CopyVideoUrlCompatibility @Version("0.0.1") class CopyVideoUrlResourcePatch : ResourcePatch { 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/DownloadsResourcePatch.kt index 9589c4c7..f628f4d0 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/DownloadsResourcePatch.kt @@ -10,7 +10,6 @@ import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patches.shared.settings.preference.impl.* import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.util.resources.ResourceUtils @@ -18,7 +17,7 @@ import app.revanced.util.resources.ResourceUtils.copyResources import app.revanced.util.resources.ResourceUtils.mergeStrings @Name("downloads-resource-patch") -@DependsOn([BottomControlsResourcePatch::class, FixLocaleConfigErrorPatch::class, SettingsPatch::class]) +@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class]) @Description("Makes necessary changes to resources for the download button.") @DownloadsCompatibility @Version("0.0.1") diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt index 83eca468..2d358f79 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt @@ -8,16 +8,13 @@ import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.youtube.layout.branding.header.annotations.PremiumHeadingCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import java.nio.file.Files import java.nio.file.StandardCopyOption import kotlin.io.path.exists @Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) @Name("premium-heading") @Description("Shows premium branding on the home screen.") @PremiumHeadingCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt index f373fd6c..f9d93d4c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt @@ -5,17 +5,14 @@ import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.youtube.layout.branding.icon.annotations.CustomBrandingCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.util.resources.ResourceUtils import app.revanced.util.resources.ResourceUtils.copyResources import java.io.File import java.nio.file.Files @Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) @Name("custom-branding") @Description("Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).") @CustomBrandingCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt index bd82e1dd..3de82865 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt @@ -9,18 +9,18 @@ import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch -import app.revanced.patches.youtube.layout.buttons.annotations.HideButtonsCompatibility import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.SwitchPreference +import app.revanced.patches.youtube.layout.buttons.annotations.HideButtonsCompatibility +import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch +import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch @Patch @DependsOn([ResourceMappingPatch::class, LithoFilterPatch::class]) -@Name("hide-video-buttons") -@Description("Adds options to hide action buttons under a video.") +@Name("hide-video-action-buttons") +@Description("Adds the options to hide action buttons under a video.") @HideButtonsCompatibility @Version("0.0.1") class HideButtonsPatch : ResourcePatch { diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/annotations/HidePlayerButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/annotations/HidePlayerButtonsCompatibility.kt new file mode 100644 index 00000000..bfce8a06 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/annotations/HidePlayerButtonsCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.player.buttons.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf() + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class HidePlayerButtonsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/fingerprints/PlayerControlsVisibilityModelFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/fingerprints/PlayerControlsVisibilityModelFingerprint.kt new file mode 100644 index 00000000..d8e45c03 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/fingerprints/PlayerControlsVisibilityModelFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.youtube.layout.player.buttons.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object PlayerControlsVisibilityModelFingerprint : MethodFingerprint( + opcodes = listOf(Opcode.INVOKE_DIRECT_RANGE), + strings = listOf("hasNext", "hasPrevious", "Missing required properties:") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/patch/HidePlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/patch/HidePlayerButtonsPatch.kt new file mode 100644 index 00000000..bd12a855 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/buttons/patch/HidePlayerButtonsPatch.kt @@ -0,0 +1,74 @@ +package app.revanced.patches.youtube.layout.player.buttons.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.extensions.instruction +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.player.buttons.annotations.HidePlayerButtonsCompatibility +import app.revanced.patches.youtube.layout.player.buttons.fingerprints.PlayerControlsVisibilityModelFingerprint +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.formats.Instruction3rc + +@Patch +@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) +@Name("hide-player-buttons") +@Description("Adds the option to hide video player previous and next buttons.") +@HidePlayerButtonsCompatibility +@Version("0.0.1") +class HidePlayerButtonsPatch : BytecodePatch( + listOf(PlayerControlsVisibilityModelFingerprint) +) { + private object ParameterOffsets { + const val HAS_NEXT = 5 + } + + override fun execute(context: BytecodeContext): PatchResult { + SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( + SwitchPreference( + "revanced_hide_player_buttons", + StringResource( + "revanced_hide_player_buttons_title", + "Hide previous & next video buttons" + ), + false, + StringResource( + "revanced_hide_player_buttons_summary_on", + "The buttons are hidden" + ), + StringResource( + "revanced_hide_player_buttons_summary_off", + "The buttons are shown" + ) + ) + ) + + PlayerControlsVisibilityModelFingerprint.result?.apply { + val callIndex = scanResult.patternScanResult!!.endIndex + val callInstruction = mutableMethod.instruction(callIndex) as Instruction3rc + + // overriding this parameter register hides the previous and next buttons + val hasNextParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_NEXT + + mutableMethod.addInstructions( + callIndex, + """ + invoke-static { }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->hideButtons()Z + move-result v$hasNextParameterRegister + xor-int/lit8 v$hasNextParameterRegister, v$hasNextParameterRegister, 1 + """ + ) + } ?: return PlayerControlsVisibilityModelFingerprint.toErrorResult() + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/playerbuttonbackground/patch/PlayerButtonBackgroundPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/playerbuttonbackground/patch/PlayerButtonBackgroundPatch.kt index c99615d9..32a7baa3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/playerbuttonbackground/patch/PlayerButtonBackgroundPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/playerbuttonbackground/patch/PlayerButtonBackgroundPatch.kt @@ -7,15 +7,12 @@ import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.ResourcePatch +import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.youtube.layout.playerbuttonbackground.annotations.PlayerButtonBackgroundCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import org.w3c.dom.Element @Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) @Name("remove-player-button-background") @Description("Removes the background from the video player buttons.") @PlayerButtonBackgroundCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt index 35dd0af7..16eaf3a2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt @@ -11,11 +11,10 @@ import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patches.shared.settings.preference.impl.Preference import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.util.resources.ResourceUtils.mergeStrings -@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class]) +@DependsOn([SettingsPatch::class]) @Name("return-youtube-dislike-resource-patch") @Description("Adds the preferences for Return YouTube Dislike.") @ReturnYouTubeDislikeCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt index 8ca1ab12..0a75529e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt @@ -46,7 +46,7 @@ import org.jf.dexlib2.iface.reference.StringReference ] ) @Name("sponsorblock") -@Description("Integrate SponsorBlock.") +@Description("Integrates SponsorBlock which allows skipping video segments such as sponsored content.") @SponsorBlockCompatibility @Version("0.0.1") class SponsorBlockBytecodePatch : BytecodePatch( diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt index 4f85e378..fb6f903c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt @@ -11,7 +11,6 @@ import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.settings.preference.impl.Preference import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.util.resources.ResourceUtils import app.revanced.util.resources.ResourceUtils.copyResources @@ -20,7 +19,7 @@ import app.revanced.util.resources.ResourceUtils.mergeStrings @Name("sponsorblock-resource-patch") @SponsorBlockCompatibility -@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class, ResourceMappingPatch::class]) +@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @Version("0.0.1") class SponsorBlockResourcePatch : ResourcePatch { diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt index 7b50a360..8bc9c1c1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt @@ -8,13 +8,12 @@ import app.revanced.patcher.patch.* import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.util.resources.ResourceUtils import app.revanced.util.resources.ResourceUtils.copyResources import org.w3c.dom.Element @Patch -@DependsOn([LithoThemePatch::class, FixLocaleConfigErrorPatch::class]) +@DependsOn([LithoThemePatch::class]) @Name("theme") @Description("Applies a custom theme.") @ThemeCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt deleted file mode 100644 index a304b71f..00000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.manifest.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class FixLocaleConfigErrorCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt deleted file mode 100644 index 801e444d..00000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt +++ /dev/null @@ -1,36 +0,0 @@ -package app.revanced.patches.youtube.misc.manifest.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patches.youtube.misc.manifest.annotations.FixLocaleConfigErrorCompatibility -import org.w3c.dom.Element - -@Name("locale-config-fix") -@Description("Fixes an error when building the resources by patching the manifest file.") -@FixLocaleConfigErrorCompatibility -@Version("0.0.1") -class FixLocaleConfigErrorPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - // create an xml editor instance - context.xmlEditor["AndroidManifest.xml"].use { - // edit the application nodes attribute... - val applicationNode = it - .file - .getElementsByTagName("application") - .item(0) as Element - - - // by replacing the attributes name - val attribute = "android:localeConfig" - applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute)) - applicationNode.removeAttribute(attribute) - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt index 1cdc47f4..257f779e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt @@ -8,7 +8,8 @@ import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch +import app.revanced.patches.shared.settings.preference.impl.Preference +import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NAME @@ -16,15 +17,13 @@ import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAG import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.shared.settings.preference.impl.Preference -import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch import app.revanced.util.microg.Constants.MICROG_VENDOR import app.revanced.util.microg.MicroGManifestHelper import app.revanced.util.microg.MicroGResourceHelper @Name("microg-resource-patch") -@DependsOn([FixLocaleConfigErrorPatch::class, SettingsResourcePatch::class]) +@DependsOn([SettingsResourcePatch::class]) @Description("Resource patch to allow YouTube ReVanced to run without root and under a different package name.") @MicroGPatchCompatibility @Version("0.0.1") diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt index 8cae83e9..ef4dc936 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt @@ -25,7 +25,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c @Patch @DependsOn([IntegrationsPatch::class, SettingsPatch::class]) @Name("open-links-directly") -@Description("Bypasses https://youtube.com/redirect URLs.") +@Description("Skips over redirection URLs to external links.") @OpenLinksDirectlyCompatibility @Version("0.0.1") class OpenLinksDirectlyPatch : BytecodePatch( diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt index e569e56a..d6fb1889 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt @@ -8,12 +8,9 @@ import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility @Name("bottom-controls-resource-patch") -@DependsOn([FixLocaleConfigErrorPatch::class]) @Description("Manages the resources for the bottom controls of the YouTube player.") @PlayerControlsCompatibility @Version("0.0.1") diff --git a/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt b/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt new file mode 100644 index 00000000..3a1b8f23 --- /dev/null +++ b/src/main/kotlin/app/revanced/util/patch/AbstractTransformInstructionsPatch.kt @@ -0,0 +1,63 @@ +package app.revanced.util.patch + +import app.revanced.extensions.findMutableMethodOf +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import org.jf.dexlib2.iface.ClassDef +import org.jf.dexlib2.iface.Method +import org.jf.dexlib2.iface.instruction.Instruction + +internal abstract class AbstractTransformInstructionsPatch<T> : BytecodePatch() { + + abstract fun filterMap( + classDef: ClassDef, + method: Method, + instruction: Instruction, + instructionIndex: Int + ): T? + + abstract fun transform(mutableMethod: MutableMethod, entry: T) + + override fun execute(context: BytecodeContext): PatchResult { + // Find all instructions + buildMap { + context.classes.forEach { classDef -> + classDef.methods.let { methods -> + buildMap methodList@{ + methods.forEach methods@{ method -> + with(method.implementation?.instructions ?: return@methods) { + ArrayDeque<T>().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) + } + } + } + } + }.also { if (it.isEmpty()) return@forEach }.let { methodPatches -> + put(classDef, methodPatches) + } + } + }.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()) + } + } + } + } + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/util/patch/MethodCall.kt b/src/main/kotlin/app/revanced/util/patch/MethodCall.kt new file mode 100644 index 00000000..fe21f4fc --- /dev/null +++ b/src/main/kotlin/app/revanced/util/patch/MethodCall.kt @@ -0,0 +1,92 @@ +package app.revanced.util.patch + +import app.revanced.patcher.extensions.replaceInstruction +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.ClassDef +import org.jf.dexlib2.iface.instruction.Instruction +import org.jf.dexlib2.iface.instruction.formats.Instruction35c +import org.jf.dexlib2.iface.reference.MethodReference + +internal typealias Instruction35cInfo = Triple<IMethodCall, Instruction35c, Int> + +internal interface IMethodCall { + val definedClassName: String + val methodName: String + val methodParams: Array<String> + val returnType: String + + /** + * Replaces an invoke-virtual instruction with an invoke-static instruction, + * which calls a static replacement method in the respective integrations class. + * The method definition in the integrations class is expected to be the same, + * except that the method should be static and take as a first parameter + * an instance of the class, in which the original method was defined in. + * + * Example: + * + * original method: Window#setFlags(int, int) + * + * replacement method: Integrations#setFlags(Window, int, int) + */ + fun replaceInvokeVirtualWithIntegrations( + definingClassDescriptor: String, + method: MutableMethod, + instruction: Instruction35c, + instructionIndex: Int + ) { + val registers = arrayOf( + instruction.registerC, + instruction.registerD, + instruction.registerE, + instruction.registerF, + instruction.registerG + ) + val argsNum = methodParams.size + 1 // + 1 for instance of definedClassName + if (argsNum > registers.size) { + // should never happen, but just to be sure (also for the future) a safety check + throw RuntimeException( + "Not enough registers for ${definedClassName}#${methodName}: " + + "Required $argsNum registers, but only got ${registers.size}." + ) + } + + val args = registers.take(argsNum).joinToString(separator = ", ") { reg -> "v${reg}" } + val replacementMethodDefinition = + "${methodName}(${definedClassName}${methodParams.joinToString(separator = "")})${returnType}" + + method.replaceInstruction( + instructionIndex, + "invoke-static { $args }, ${definingClassDescriptor}->${replacementMethodDefinition}" + ) + } +} + +internal inline fun <reified E> fromMethodReference(methodReference: MethodReference) + where E : Enum<E>, E : IMethodCall = enumValues<E>().firstOrNull { search -> + search.definedClassName == methodReference.definingClass + && search.methodName == methodReference.name + && methodReference.parameterTypes.toTypedArray().contentEquals(search.methodParams) +} + +internal inline fun <reified E> filterMapInstruction35c( + integrationsClassDescriptorPrefix: String, + classDef: ClassDef, + instruction: Instruction, + instructionIndex: Int +): Instruction35cInfo? where E : Enum<E>, E : IMethodCall { + if (classDef.type.startsWith(integrationsClassDescriptorPrefix)) { + // avoid infinite recursion + return null + } + + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) { + return null + } + + val invokeInstruction = instruction as Instruction35c + val methodRef = invokeInstruction.reference as MethodReference + val methodCall = fromMethodReference<E>(methodRef) ?: return null + + return Instruction35cInfo(methodCall, invokeInstruction, instructionIndex) +} diff --git a/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png index e2dc8a53..473330fe 100644 Binary files a/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png and b/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png index e5a73b56..0616301e 100644 Binary files a/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png and b/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/branding/mipmap-hdpi/ic_launcher.png b/src/main/resources/branding/mipmap-hdpi/ic_launcher.png index dc967b77..333f5c3f 100644 Binary files a/src/main/resources/branding/mipmap-hdpi/ic_launcher.png and b/src/main/resources/branding/mipmap-hdpi/ic_launcher.png differ diff --git a/src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png index dc967b77..333f5c3f 100644 Binary files a/src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png and b/src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png index 4dee1752..f2e71489 100644 Binary files a/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png and b/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png index 3d26f5b2..4a454727 100644 Binary files a/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png and b/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/branding/mipmap-mdpi/ic_launcher.png b/src/main/resources/branding/mipmap-mdpi/ic_launcher.png index 4e3735d0..947dca92 100644 Binary files a/src/main/resources/branding/mipmap-mdpi/ic_launcher.png and b/src/main/resources/branding/mipmap-mdpi/ic_launcher.png differ diff --git a/src/main/resources/branding/mipmap-mdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-mdpi/ic_launcher_round.png index 4e3735d0..947dca92 100644 Binary files a/src/main/resources/branding/mipmap-mdpi/ic_launcher_round.png and b/src/main/resources/branding/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png index 49d5f450..5ebd9b9b 100644 Binary files a/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png and b/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png index 4f66f60a..af465feb 100644 Binary files a/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png and b/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/branding/mipmap-xhdpi/ic_launcher.png b/src/main/resources/branding/mipmap-xhdpi/ic_launcher.png index 471c9779..811c31f2 100644 Binary files a/src/main/resources/branding/mipmap-xhdpi/ic_launcher.png and b/src/main/resources/branding/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/main/resources/branding/mipmap-xhdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-xhdpi/ic_launcher_round.png index 471c9779..811c31f2 100644 Binary files a/src/main/resources/branding/mipmap-xhdpi/ic_launcher_round.png and b/src/main/resources/branding/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png index 1a92bea2..fbeb03fc 100644 Binary files a/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png and b/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png index 777daea5..0c893628 100644 Binary files a/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png and b/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png b/src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png index 6e217856..7eca7042 100644 Binary files a/src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png and b/src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/main/resources/branding/mipmap-xxhdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-xxhdpi/ic_launcher_round.png index 6e217856..7eca7042 100644 Binary files a/src/main/resources/branding/mipmap-xxhdpi/ic_launcher_round.png and b/src/main/resources/branding/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png index 9c4462f8..b7b84772 100644 Binary files a/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png and b/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png index 0abe542a..bc688ad3 100644 Binary files a/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png and b/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png b/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png index c0505bf8..e0fd4891 100644 Binary files a/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png and b/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png index c0505bf8..e0fd4891 100644 Binary files a/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png and b/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png differ