chore: merge branch dev
to main
(#2582)
This commit is contained in:
commit
e466b86c3e
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
35
CHANGELOG.md
35
CHANGELOG.md
|
@ -1,3 +1,38 @@
|
|||
# [2.182.0-dev.5](https://github.com/revanced/revanced-patches/compare/v2.182.0-dev.4...v2.182.0-dev.5) (2023-07-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/hide-layout-components:** hide mix playlists ([33a87bd](https://github.com/revanced/revanced-patches/commit/33a87bd6eac1639687ebdf96ef8924cd674f81e4))
|
||||
|
||||
# [2.182.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.182.0-dev.3...v2.182.0-dev.4) (2023-07-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube:** support version `18.23.35` ([#2461](https://github.com/revanced/revanced-patches/issues/2461)) ([d20fde1](https://github.com/revanced/revanced-patches/commit/d20fde1e57077fe9a943f9782b415d7a0249b083))
|
||||
|
||||
# [2.182.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.182.0-dev.2...v2.182.0-dev.3) (2023-07-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **pixiv:** add `hide-ads` patch ([#2578](https://github.com/revanced/revanced-patches/issues/2578)) ([862a7ec](https://github.com/revanced/revanced-patches/commit/862a7ec5b0767c28e79454a44218069d3e9cbac7))
|
||||
|
||||
# [2.182.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.182.0-dev.1...v2.182.0-dev.2) (2023-07-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **slideforreddit:** add `change-oauth-client-id` patch ([#2571](https://github.com/revanced/revanced-patches/issues/2571)) ([8cd60ee](https://github.com/revanced/revanced-patches/commit/8cd60eea36bd49514ed1c42bf362dce7e9675fca))
|
||||
|
||||
# [2.182.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.181.0...v2.182.0-dev.1) (2023-07-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove unnecessary notice ([7e9f0b2](https://github.com/revanced/revanced-patches/commit/7e9f0b2d02e910984f08777fefcd2ad7df6a21ee))
|
||||
|
||||
# [2.181.0](https://github.com/revanced/revanced-patches/compare/v2.180.0...v2.181.0) (2023-07-03)
|
||||
|
||||
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
## 🧩 ReVanced Patches
|
||||
|
||||
The official ReVanced Patches.
|
||||
|
||||
## 📋 List of patches in this repository
|
||||
|
||||
{{ table }}
|
||||
|
||||
> Looking for the JSON variant of this? [Click here](patches.json).
|
||||
|
||||
## 📝 JSON Format
|
||||
|
||||
This section explains the JSON format for the [patches.json](patches.json) file.
|
||||
|
||||
The file contains an array of objects, each object representing a patch. The object contains the following properties:
|
||||
|
||||
| key | description |
|
||||
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `name` | The name of the patch. |
|
||||
| `description` | The description of the patch. |
|
||||
| `version` | The version of the patch. |
|
||||
| `excluded` | Whether the patch is excluded by default. If `true`, the patch must never be included by default. |
|
||||
| `options` | An array of options for this patch. |
|
||||
| `options.key` | The key of the option. |
|
||||
| `options.title` | The title of the option. |
|
||||
| `options.description` | The description of the option. |
|
||||
| `options.required` | Whether the option is required. |
|
||||
| `options.choices?` | An array of choices of the option. This may be `null` if this option has no choices. The element type of this array may be any type. It can be a `String`, `Int` or something else. |
|
||||
| `dependencies` | An array of dependencies, which are patch names. |
|
||||
| `compatiblePackages` | An array of packages compatible with this patch. |
|
||||
| `compatiblePackages.name` | The name of the package. |
|
||||
| `compatiblePackages.versions` | An array of versions of the package compatible with this patch. If empty, all versions are seemingly compatible. |
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"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"
|
||||
],
|
||||
"compatiblePackages": [
|
||||
{
|
||||
"name": "com.google.android.youtube",
|
||||
"versions": [
|
||||
"17.22.36",
|
||||
"17.24.35",
|
||||
"17.26.35",
|
||||
"17.27.39",
|
||||
"17.28.34",
|
||||
"17.29.34",
|
||||
"17.32.35",
|
||||
"17.33.42"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "theme",
|
||||
"description": "Enables a custom theme.",
|
||||
"version": "0.0.1",
|
||||
"excluded": false,
|
||||
"options": [
|
||||
{
|
||||
"key": "theme",
|
||||
"title": "Theme",
|
||||
"description": "Select a theme.",
|
||||
"required": true,
|
||||
"choices": [
|
||||
"Amoled"
|
||||
]
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
"locale-config-fix"
|
||||
],
|
||||
"compatiblePackages": [
|
||||
{
|
||||
"name": "com.google.android.youtube",
|
||||
"versions": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": "appIconPath",
|
||||
"title": "Application Icon Path",
|
||||
"description": "A path to the icon of the application.",
|
||||
"required": false,
|
||||
"choices": null
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
"locale-config-fix"
|
||||
],
|
||||
"compatiblePackages": [
|
||||
{
|
||||
"name": "com.google.android.youtube",
|
||||
"versions": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
618
README.md
618
README.md
|
@ -1,619 +1,3 @@
|
|||
## 🧩 ReVanced Patches
|
||||
|
||||
The official ReVanced Patches.
|
||||
|
||||
## 📋 List of patches in this repository
|
||||
|
||||
### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `always-autorepeat` | Always repeats the playing video again. | 18.19.35 |
|
||||
| `client-spoof` | Spoofs a patched client to allow playback. | 18.19.35 |
|
||||
| `comments` | Hides components related to comments. | 18.19.35 |
|
||||
| `copy-video-url` | Adds buttons in player to copy video links. | 18.19.35 |
|
||||
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
|
||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 18.19.35 |
|
||||
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.19.35 |
|
||||
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.19.35 |
|
||||
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.19.35 |
|
||||
| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
|
||||
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
|
||||
| `enable-debugging` | Adds debugging options. | all |
|
||||
| `external-downloads` | Adds support to download and save YouTube videos using an external app. | 18.19.35 |
|
||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
|
||||
| `hide-ads` | Removes general ads. | 18.19.35 |
|
||||
| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
|
||||
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
|
||||
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
|
||||
| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
|
||||
| `hide-cast-button` | Hides the cast button in the video player. | all |
|
||||
| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.19.35 |
|
||||
| `hide-email-address` | Hides the email address in the account switcher. | 18.19.35 |
|
||||
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.19.35 |
|
||||
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.19.35 |
|
||||
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.19.35 |
|
||||
| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
|
||||
| `hide-layout-components` | Hides general layout components. | 18.19.35 |
|
||||
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
|
||||
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
|
||||
| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
|
||||
| `hide-seekbar` | Hides the seekbar. | 18.19.35 |
|
||||
| `hide-shorts-components` | Hides components from YouTube Shorts. | 18.19.35 |
|
||||
| `hide-timestamp` | Hides timestamp in video player. | 18.19.35 |
|
||||
| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.19.35 |
|
||||
| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.19.35 |
|
||||
| `hide-watermark` | Hides creator's watermarks on videos. | 18.19.35 |
|
||||
| `minimized-playback` | Enables minimized and background playback. | 18.19.35 |
|
||||
| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.19.35 |
|
||||
| `old-quality-layout` | Enables the original video quality flyout in the video player settings. | 18.19.35 |
|
||||
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
|
||||
| `premium-heading` | Shows premium branding on the home screen. | all |
|
||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
|
||||
| `remove-player-controls-background` | Removes the background from the video player controls. | 18.19.35 |
|
||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.19.35 |
|
||||
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.19.35 |
|
||||
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.19.35 |
|
||||
| `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.19.35 |
|
||||
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.19.35 |
|
||||
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.19.35 |
|
||||
| `theme` | Applies a custom theme. | all |
|
||||
| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.19.35 |
|
||||
| `video-ads` | Removes ads in the video player. | 18.19.35 |
|
||||
| `video-speed` | Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout. | 18.19.35 |
|
||||
| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.19.35 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `background-play` | Enables playing music in the background. | all |
|
||||
| `bypass-certificate-checks` | Bypasses certificate checks which prevent YouTube Music from working on Android Auto. | all |
|
||||
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | all |
|
||||
| `compact-header` | Hides the music category bar at the top of the homepage. | all |
|
||||
| `exclusive-audio-playback` | Enables the option to play music without video. | all |
|
||||
| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | all |
|
||||
| `minimized-playback-music` | Enables minimized playback on Kids music. | all |
|
||||
| `music-video-ads` | Removes ads in the music player. | all |
|
||||
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | all |
|
||||
| `vanced-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ss.android.ugc.trill`](https://play.google.com/store/apps/details?id=com.ss.android.ugc.trill)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `disable-login-requirement` | Do not force login. | all |
|
||||
| `downloads` | Removes download restrictions and changes the default path to download to. | all |
|
||||
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | all |
|
||||
| `fix-google-login` | Allows logging in with a Google account. | all |
|
||||
| `hide-ads` | Removes ads from TikTok. | all |
|
||||
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
||||
| `settings` | Adds ReVanced settings to TikTok. | all |
|
||||
| `show-seekbar` | Shows progress bar for all video. | all |
|
||||
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.zhiliaoapp.musically`](https://play.google.com/store/apps/details?id=com.zhiliaoapp.musically)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `disable-login-requirement` | Do not force login. | all |
|
||||
| `downloads` | Removes download restrictions and changes the default path to download to. | all |
|
||||
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | all |
|
||||
| `fix-google-login` | Allows logging in with a Google account. | all |
|
||||
| `hide-ads` | Removes ads from TikTok. | all |
|
||||
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
||||
| `settings` | Adds ReVanced settings to TikTok. | all |
|
||||
| `show-seekbar` | Shows progress bar for all video. | all |
|
||||
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `tv.twitch.android.app`](https://play.google.com/store/apps/details?id=tv.twitch.android.app)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `auto-claim-channel-points` | Automatically claim Channel Points. | 15.4.1 |
|
||||
| `block-audio-ads` | Blocks audio ads in streams and VODs. | 15.4.1 |
|
||||
| `block-embedded-ads` | Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker. | 15.4.1 |
|
||||
| `block-video-ads` | Blocks video ads in streams and VODs. | 15.4.1 |
|
||||
| `debug-mode` | Enables Twitch's internal debugging mode. | all |
|
||||
| `settings` | Adds settings menu to Twitch. | all |
|
||||
| `show-deleted-messages` | Shows deleted chat messages behind a clickable spoiler. | 15.4.1 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `disable-screenshot-popup` | Disables the popup that shows up when taking a screenshot. | all |
|
||||
| `hide-ads` | Removes ads from the Reddit. | all |
|
||||
| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
|
||||
| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.twitter.android`](https://play.google.com/store/apps/details?id=com.twitter.android)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `dynamic-color` | Replaces the default Twitter Blue with the users Material You palette. | all |
|
||||
| `hide-ads` | Hides ads. | all |
|
||||
| `hide-recommended-users` | Hides recommended users. | all |
|
||||
| `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `disable-switching-emoji-to-sticker-in-message-input-field` | Disables switching from emoji to sticker search mode in message input field | all |
|
||||
| `disable-typing-indicator` | Disables the indicator while typing a message | all |
|
||||
| `hide-inbox-ads` | Hides ads in inbox. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.laurencedawson.reddit_sync`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "http://redditsync/auth". | all |
|
||||
| `disable-ads` | Disables ads. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
|
||||
| `spotify-theme` | Applies a custom theme. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.sony.songpal.mdr`](https://play.google.com/store/apps/details?id=com.sony.songpal.mdr)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `remove-badge-tab` | Removes the badge tab from the activity tab. | all |
|
||||
| `remove-notification-badge` | Removes the red notification badge from the activity tab. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `remove-bootloader-detection` | Removes the check for an unlocked bootloader. | all |
|
||||
| `remove-root-detection` | Removes the check for root permissions. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `at.gv.oe.app`](https://play.google.com/store/apps/details?id=at.gv.oe.app)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `remove-root-detection` | Removes the check for root permissions and unlocked bootloader. | all |
|
||||
| `spoof-signature` | Spoofs the signature of the app. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `ml.docilealligator.infinityforreddit`](https://play.google.com/store/apps/details?id=ml.docilealligator.infinityforreddit)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "infinity://localhost". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `free.reddit.news`](https://play.google.com/store/apps/details?id=free.reddit.news)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "dbrady://relay". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `reddit.news`](https://play.google.com/store/apps/details?id=reddit.news)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "dbrady://relay". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.onelouder.baconreader`](https://play.google.com/store/apps/details?id=com.onelouder.baconreader)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "http://baconreader.com/auth". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.onelouder.baconreader.premium`](https://play.google.com/store/apps/details?id=com.onelouder.baconreader.premium)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "http://baconreader.com/auth". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.rubenmayayo.reddit`](https://play.google.com/store/apps/details?id=com.rubenmayayo.reddit)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "http://rubenmayayo.com". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.andrewshu.android.reddit`](https://play.google.com/store/apps/details?id=com.andrewshu.android.reddit)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "redditisfun://auth". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.andrewshu.android.redditdonation`](https://play.google.com/store/apps/details?id=com.andrewshu.android.redditdonation)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "redditisfun://auth". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.laurencedawson.reddit_sync.pro`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync.pro)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "http://redditsync/auth". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.laurencedawson.reddit_sync.dev`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync.dev)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID. The OAuth application type has to be "Installed app" and the redirect URI has to be set to "http://redditsync/auth". | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.myprog.hexedit`](https://play.google.com/store/apps/details?id=com.myprog.hexedit)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `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>
|
||||
|
||||
### [📦 `com.nis.app`](https://play.google.com/store/apps/details?id=com.nis.app)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `hide-ads` | Removes ads from Inshorts. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.vanced.android.youtube`](https://play.google.com/store/apps/details?id=com.vanced.android.youtube)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `hide-ads` | Removes general ads. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.instagram.android`](https://play.google.com/store/apps/details?id=com.instagram.android)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `hide-timeline-ads` | Removes ads from the timeline. | 275.0.0.27.98 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.backdrops.wallpapers`](https://play.google.com/store/apps/details?id=com.backdrops.wallpapers)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `pro-unlock` | Unlocks pro-only functions. | 4.52 |
|
||||
</details>
|
||||
|
||||
### [📦 `de.dwd.warnapp`](https://play.google.com/store/apps/details?id=de.dwd.warnapp)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `net.binarymode.android.irplus`](https://play.google.com/store/apps/details?id=net.binarymode.android.irplus)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `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.scb.phone`](https://play.google.com/store/apps/details?id=com.scb.phone)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `remove-debugging-detection` | Removes the USB and wireless debugging checks. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.google.android.apps.recorder`](https://play.google.com/store/apps/details?id=com.google.android.apps.recorder)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `remove-device-restrictions` | Removes restrictions from using the app on any device. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-paid-widgets` | Unlocks paid widgets of the app | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.microblink.photomath`](https://play.google.com/store/apps/details?id=com.microblink.photomath)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-plus` | Unlocks plus features. | 8.20.0 |
|
||||
</details>
|
||||
|
||||
### [📦 `io.yuka.android`](https://play.google.com/store/apps/details?id=io.yuka.android)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-premium` | Unlocks premium features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.teslacoilsw.launcher`](https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
|
||||
</details>
|
||||
|
||||
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | 4.6377 |
|
||||
</details>
|
||||
|
||||
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.vsco.cam`](https://play.google.com/store/apps/details?id=com.vsco.cam)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.wakdev.apps.nfctools.se`](https://play.google.com/store/apps/details?id=com.wakdev.apps.nfctools.se)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks premium features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-themes` | Unlocks all themes that are inaccessible until a certain level is reached. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `net.dinglisch.android.taskerm`](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-trial` | Unlocks the trial version. | all |
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
> Looking for the JSON variant of this? [Click here](patches.json).
|
||||
|
||||
## 📝 JSON Format
|
||||
|
||||
This section explains the JSON format for the [patches.json](patches.json) file.
|
||||
|
||||
The file contains an array of objects, each object representing a patch. The object contains the following properties:
|
||||
|
||||
| key | description |
|
||||
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `name` | The name of the patch. |
|
||||
| `description` | The description of the patch. |
|
||||
| `version` | The version of the patch. |
|
||||
| `excluded` | Whether the patch is excluded by default. If `true`, the patch must never be included by default. |
|
||||
| `options` | An array of options for this patch. |
|
||||
| `options.key` | The key of the option. |
|
||||
| `options.title` | The title of the option. |
|
||||
| `options.description` | The description of the option. |
|
||||
| `options.required` | Whether the option is required. |
|
||||
| `options.choices?` | An array of choices of the option. This may be `null` if this option has no choices. The element type of this array may be any type. It can be a `String`, `Int` or something else. |
|
||||
| `dependencies` | An array of dependencies, which are patch names. |
|
||||
| `compatiblePackages` | An array of packages compatible with this patch. |
|
||||
| `compatiblePackages.name` | The name of the package. |
|
||||
| `compatiblePackages.versions` | An array of versions of the package compatible with this patch. If empty, all versions are seemingly compatible. |
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"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"
|
||||
],
|
||||
"compatiblePackages": [
|
||||
{
|
||||
"name": "com.google.android.youtube",
|
||||
"versions": [
|
||||
"17.22.36",
|
||||
"17.24.35",
|
||||
"17.26.35",
|
||||
"17.27.39",
|
||||
"17.28.34",
|
||||
"17.29.34",
|
||||
"17.32.35",
|
||||
"17.33.42"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "theme",
|
||||
"description": "Enables a custom theme.",
|
||||
"version": "0.0.1",
|
||||
"excluded": false,
|
||||
"options": [
|
||||
{
|
||||
"key": "theme",
|
||||
"title": "Theme",
|
||||
"description": "Select a theme.",
|
||||
"required": true,
|
||||
"choices": [
|
||||
"Amoled"
|
||||
]
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
"locale-config-fix"
|
||||
],
|
||||
"compatiblePackages": [
|
||||
{
|
||||
"name": "com.google.android.youtube",
|
||||
"versions": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": "appIconPath",
|
||||
"title": "Application Icon Path",
|
||||
"description": "A path to the icon of the application.",
|
||||
"required": false,
|
||||
"choices": null
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
"locale-config-fix"
|
||||
],
|
||||
"compatiblePackages": [
|
||||
{
|
||||
"name": "com.google.android.youtube",
|
||||
"versions": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
Patches for ReVanced.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
kotlin("jvm") version "1.8.10"
|
||||
kotlin("jvm") version "1.8.20"
|
||||
}
|
||||
|
||||
group = "app.revanced"
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 2.181.0
|
||||
version = 2.182.0-dev.5
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,7 +1,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
5
gradlew
vendored
5
gradlew
vendored
|
@ -130,11 +130,14 @@ location of your Java installation."
|
|||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -19,7 +19,7 @@ internal interface PatchesFileGenerator {
|
|||
).loadPatches().also {
|
||||
if (it.isEmpty()) throw IllegalStateException("No patches found")
|
||||
}.let { bundle ->
|
||||
arrayOf(JsonGenerator(), ReadmeGenerator()).forEach { it.generate(bundle) }
|
||||
arrayOf(JsonGenerator()).forEach { it.generate(bundle) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package app.revanced.meta
|
||||
|
||||
import app.revanced.patcher.data.Context
|
||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||
import app.revanced.patcher.extensions.PatchExtensions.description
|
||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import com.unascribed.flexver.FlexVerComparator
|
||||
import java.io.File
|
||||
|
||||
internal class ReadmeGenerator : PatchesFileGenerator {
|
||||
private companion object {
|
||||
private const val TABLE_HEADER =
|
||||
"| \uD83D\uDC8A Patch | \uD83D\uDCDC Description | \uD83C\uDFF9 Target Version |\n" +
|
||||
"|:--------:|:--------------:|:-----------------:|"
|
||||
}
|
||||
|
||||
override fun generate(bundle: PatchBundlePatches) {
|
||||
val output = StringBuilder()
|
||||
|
||||
mutableMapOf<String, MutableList<Class<out Patch<Context>>>>()
|
||||
.apply {
|
||||
for (patch in bundle) {
|
||||
patch.compatiblePackages?.forEach { pkg ->
|
||||
if (!contains(pkg.name)) put(pkg.name, mutableListOf())
|
||||
this[pkg.name]!!.add(patch)
|
||||
}
|
||||
}
|
||||
}
|
||||
.entries
|
||||
.sortedByDescending { it.value.size }
|
||||
.forEach { (`package`, patches) ->
|
||||
val mostCommonVersion = buildMap {
|
||||
patches.forEach { patch ->
|
||||
patch.compatiblePackages?.single { compatiblePackage -> compatiblePackage.name == `package` }?.versions?.let {
|
||||
it.forEach { version -> merge(version, 1, Integer::sum) }
|
||||
}
|
||||
}
|
||||
}.let { commonMap ->
|
||||
commonMap.maxByOrNull { it.value }?.value?.let {
|
||||
commonMap.entries.filter { mostCommon -> mostCommon.value == it }
|
||||
.maxOfWith(FlexVerComparator::compare, Map.Entry<String, Int>::key)
|
||||
} ?: "all"
|
||||
}
|
||||
|
||||
output.apply {
|
||||
appendLine("### [\uD83D\uDCE6 `${`package`}`](https://play.google.com/store/apps/details?id=${`package`})")
|
||||
appendLine("<details>\n")
|
||||
appendLine(TABLE_HEADER)
|
||||
patches.forEach { patch ->
|
||||
val recommendedPatchVersion = if (
|
||||
patch.compatiblePackages?.single { it.name == `package` }?.versions?.isNotEmpty() == true
|
||||
) mostCommonVersion else "all"
|
||||
|
||||
appendLine(
|
||||
"| `${patch.patchName}` " +
|
||||
"| ${patch.description} " +
|
||||
"| $recommendedPatchVersion |"
|
||||
)
|
||||
}
|
||||
appendLine("</details>\n")
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder(File("README-template.md").readText())
|
||||
.replace(Regex("\\{\\{\\s?table\\s?}}"), output.toString())
|
||||
.let(File("README.md")::writeText)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package app.revanced.patches.pixiv.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
|
||||
object IsNotPremiumFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
listOf("L"),
|
||||
strings = listOf("pixivAccountManager"),
|
||||
customFingerprint = custom@{ _, classDef ->
|
||||
// The "isNotPremium" method is the only method in the class.
|
||||
if (classDef.virtualMethods.count() != 1) return@custom false
|
||||
|
||||
classDef.virtualMethods.first().let { isNotPremiumMethod ->
|
||||
isNotPremiumMethod.parameterTypes.size == 0 && isNotPremiumMethod.returnType == "Z"
|
||||
}
|
||||
}
|
||||
)
|
|
@ -0,0 +1,33 @@
|
|||
package app.revanced.patches.pixiv.ads.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.*
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.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.pixiv.ads.fingerprints.IsNotPremiumFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("hide-ads")
|
||||
@Description("Hides ads.")
|
||||
@Compatibility([Package("jp.pxv.android")])
|
||||
@Version("0.0.1")
|
||||
class HideAdsPatch : BytecodePatch(listOf(IsNotPremiumFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
// Always return false in the "isNotPremium" method which normally returns !this.accountManager.isPremium.
|
||||
// However, this is not the method that controls the user's premium status.
|
||||
// Instead, this method is used to determine whether ads should be shown.
|
||||
IsNotPremiumFingerprint.result?.mutableClass?.virtualMethods?.first()?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
"""
|
||||
) ?: return IsNotPremiumFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package app.revanced.patches.reddit.customclients.slide.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object GetClientIdFingerprint : MethodFingerprint(
|
||||
customFingerprint = custom@{ methodDef, classDef ->
|
||||
if (!classDef.type.endsWith("Credentials;")) return@custom false
|
||||
|
||||
methodDef.name == "getClientId"
|
||||
}
|
||||
)
|
|
@ -0,0 +1,36 @@
|
|||
package app.revanced.patches.reddit.customclients.slide.api.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://www.ccrama.me\".")
|
||||
@Compatibility([Package("me.ccrama.redditslide")])
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
"http://www.ccrama.me", Options, listOf(GetClientIdFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
first().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
}
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.ad.general.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideAdsCompatibility
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.ad.getpremium.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideGetPremiumCompatibility
|
||||
|
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.ad.video.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class VideoAdsCompatibility
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.interaction.copyvideourl.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class CopyVideoUrlCompatibility
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.interaction.downloads.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class ExternalDownloadsCompatibility
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.interaction.seekbar.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SeekbarTappingCompatibility
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.interaction.swipecontrols.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SwipeControlsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.autocaptions.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AutoCaptionsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.action.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideButtonsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.autoplay.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AutoplayButtonCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.captions.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideCaptionsButtonCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.navigation.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class NavigationButtonsCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.player.hide.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HidePlayerButtonsCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.albumcards.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AlbumCardsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.breakingnews.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class BreakingNewsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.comments.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideCommentsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class CrowdfundingBoxCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.endscreencards.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideEndscreenCardsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.filterbar.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideFilterBar
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.floatingmicrophone.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideFloatingMicrophoneButtonCompatibility
|
||||
|
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.layout.hide.general.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideLayoutComponentsCompatibility
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package app.revanced.patches.youtube.layout.hide.general.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object ConvertElementToFlatBufferFingerprint : MethodFingerprint(
|
||||
strings = listOf("Failed to convert Element to Flatbuffers: %s"),
|
||||
opcodes = listOf(Opcode.IGET_OBJECT) // Patched at this opcodes index
|
||||
)
|
|
@ -1,18 +1,24 @@
|
|||
package app.revanced.patches.youtube.layout.hide.general.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.ResourceContext
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||
import app.revanced.patches.youtube.layout.hide.general.annotations.HideLayoutComponentsCompatibility
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ConvertElementToFlatBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
|
||||
|
@ -23,8 +29,10 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.P
|
|||
@DependsOn([LithoFilterPatch::class, SettingsPatch::class])
|
||||
@HideLayoutComponentsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideLayoutComponentsPatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
class HideLayoutComponentsPatch : BytecodePatch(
|
||||
listOf(ConvertElementToFlatBufferFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_gray_separator",
|
||||
|
@ -237,6 +245,35 @@ class HideLayoutComponentsPatch : ResourcePatch {
|
|||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// region Mix playlists
|
||||
|
||||
ConvertElementToFlatBufferFingerprint.result?.let {
|
||||
val returnEmptyComponentIndex = it.scanResult.stringsScanResult!!.matches.first().index + 2
|
||||
|
||||
it.mutableMethod.apply {
|
||||
// The last virtual register (not parameter). Used to store the byte array
|
||||
// that may contain information about a mix playlist.
|
||||
val freeRegister = (implementation!!.registerCount - 1) - parameterTypes.size - 1
|
||||
|
||||
// Check if the byte array contains anything about a mix playlist.
|
||||
addInstructionsWithLabels(
|
||||
it.scanResult.patternScanResult!!.startIndex,
|
||||
"""
|
||||
invoke-static {v$freeRegister}, $FILTER_CLASS_DESCRIPTOR->filterMixPlaylists([B)Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :return_empty_component
|
||||
""",
|
||||
ExternalLabel("return_empty_component", getInstruction(returnEmptyComponentIndex))
|
||||
)
|
||||
|
||||
// Move the byte array to a free register.
|
||||
addInstruction(0, "move-object/from16 v$freeRegister, p3")
|
||||
}
|
||||
|
||||
} ?: return ConvertElementToFlatBufferFingerprint.toErrorResult()
|
||||
|
||||
// endregion
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.infocards.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideInfocardsCompatibility
|
||||
|
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideLoadMoreButtonCompatibility
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.personalinformation.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideEmailAddressCompatibility
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package app.revanced.patches.youtube.layout.hide.player.overlay.bytecode.fingerprints
|
||||
|
||||
import app.revanced.extensions.containsConstantInstructionValue
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.patch.LiteralValueFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.player.overlay.resource.patch.HidePlayerOverlayResourcePatch
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object CreatePlayerOverviewFingerprint : LiteralValueFingerprint(
|
||||
object CreatePlayerOverviewFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
opcodes = listOf(
|
||||
|
@ -15,5 +16,8 @@ object CreatePlayerOverviewFingerprint : LiteralValueFingerprint(
|
|||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST
|
||||
),
|
||||
literal = HidePlayerOverlayResourcePatch.scrimOverlayId
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("YouTubeControlsOverlay;")
|
||||
&& methodDef.containsConstantInstructionValue(HidePlayerOverlayResourcePatch.scrimOverlayId)
|
||||
}
|
||||
)
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.seekbar.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideSeekbarCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.shorts.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideShortsComponentsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.time.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideTimeCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.watchinvr.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class WatchInVRCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.watermark.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideWatermarkCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.panels.fullscreen.remove.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class FullscreenPanelsCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.panels.popup.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerPopupPanelsCompatibility
|
||||
|
|
|
@ -2,6 +2,6 @@ package app.revanced.patches.youtube.layout.player.background.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerControlsBackgroundCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class ReturnYouTubeDislikeCompatibility
|
|
@ -21,14 +21,11 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
|
|||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.MOVE_OBJECT, // CharSequence reference, and control flow label. Insert code here.
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
null, // invoke-interface or invoke-virtual
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
null, // invoke-interface or invoke-virtual
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_VIRTUAL_RANGE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
)
|
||||
)
|
|
@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
|
|||
import org.jf.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves against the same method that [TextComponentContextFingerprint] resolves to.
|
||||
* Resolves against the same class that [TextComponentConstructorFingerprint] resolves to.
|
||||
*/
|
||||
object TextComponentContextFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.searchbar.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class WideSearchbarCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.sponsorblock.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SponsorBlockCompatibility
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.youtube.layout.spoofappversion.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SpoofAppVersionCompatibility
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.startupshortsreset.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class StartupShortsResetCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.tabletminiplayer.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class TabletMiniPlayerCompatibility
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
|
|||
|
||||
object MiniPlayerOverrideFingerprint : MethodFingerprint(
|
||||
"Z", AccessFlags.STATIC or AccessFlags.PUBLIC,
|
||||
listOf("L"),
|
||||
listOf("Landroid/content/Context;"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
|
|
|
@ -3,5 +3,5 @@ package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
|
|||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object MiniPlayerOverrideParentFingerprint : MethodFingerprint(
|
||||
strings = listOf("Possible Context wrapper loop - chain of wrappers larger than 10000")
|
||||
strings = listOf("Unset or unknown Input OneOf case for dynamic input")
|
||||
)
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.autorepeat.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AutoRepeatCompatibility
|
|
@ -0,0 +1,13 @@
|
|||
package app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.video.videoqualitymenu.patch.OldVideoQualityMenuResourcePatch
|
||||
import app.revanced.util.patch.LiteralValueFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
object CreateBottomSheetFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
returnType = "Landroid/widget/LinearLayout;",
|
||||
literal = OldVideoQualityMenuResourcePatch.bottomSheetMargins
|
||||
)
|
|
@ -0,0 +1,43 @@
|
|||
package app.revanced.patches.youtube.misc.bottomsheet.hook.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints.CreateBottomSheetFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
class BottomSheetHookPatch : BytecodePatch(
|
||||
listOf(CreateBottomSheetFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
CreateBottomSheetFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val returnLinearLayoutIndex = implementation!!.instructions.lastIndex
|
||||
val linearLayoutRegister = getInstruction<OneRegisterInstruction>(returnLinearLayoutIndex).registerA
|
||||
|
||||
addHook = { classDescriptor ->
|
||||
addInstruction(
|
||||
returnLinearLayoutIndex,
|
||||
"invoke-static { v$linearLayoutRegister }, " +
|
||||
"${classDescriptor}->" +
|
||||
"onFlyoutMenuCreate(Landroid/widget/LinearLayout;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: return CreateBottomSheetFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
internal lateinit var addHook: (String) -> Unit
|
||||
private set
|
||||
}
|
||||
}
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class FixBackToExitGestureCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.fix.playback.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class ClientSpoofCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.integrations.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class IntegrationsCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.links.open.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class OpenLinksExternallyCompatibility
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package app.revanced.patches.youtube.misc.litho.filter.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object ProtobufBufferFingerprint : MethodFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT, // References the field required below.
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.GOTO,
|
||||
Opcode.CHECK_CAST, // Casts the referenced field to a specific type that stores the protobuf buffer.
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
)
|
|
@ -0,0 +1,18 @@
|
|||
package app.revanced.patches.youtube.misc.litho.filter.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object ProtobufBufferReferenceFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("I", "Ljava/nio/ByteBuffer;"),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.SUB_INT_2ADDR
|
||||
)
|
||||
)
|
|
@ -4,50 +4,110 @@ import app.revanced.extensions.toErrorResult
|
|||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.immutable.ImmutableField
|
||||
import java.io.Closeable
|
||||
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.")
|
||||
@Version("0.0.1")
|
||||
class LithoFilterPatch : BytecodePatch(
|
||||
listOf(ComponentContextParserFingerprint, LithoFilterFingerprint)
|
||||
listOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint)
|
||||
), Closeable {
|
||||
/**
|
||||
* The following patch inserts a hook into the method that parses the bytes into a ComponentContext.
|
||||
* This method contains a StringBuilder object that represents the pathBuilder of the component.
|
||||
* The pathBuilder is used to filter components by their path.
|
||||
*
|
||||
* Additionally, the method contains a reference to the components identifier.
|
||||
* The identifier is used to filter components by their identifier.
|
||||
*
|
||||
* In addition to that, a static field is added to the class of this method. (See protobufBufferField).
|
||||
* This field holds a reference to the protobuf buffer object.
|
||||
* The field is being set in another method that holds a reference to the protobuf buffer object.
|
||||
* The object contains a large byte array that represents the component tree.
|
||||
* This byte array is searched for strings that indicate the current component.
|
||||
*
|
||||
* The following pseudo code shows how the patch works:
|
||||
*
|
||||
* class ComponentContextParser {
|
||||
* public static ByteBuffer buffer; // Inserted by this patch.
|
||||
*
|
||||
* public ComponentContext parseBytesToComponentContext(...) {
|
||||
* ...
|
||||
* if (filter(identifier, pathBuilder, buffer)); // Inserted by this patch.
|
||||
* return emptyComponent;
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class SomeOtherClass {
|
||||
* // Called before ComponentContextParser.parseBytesToComponentContext method.
|
||||
* public void someOtherMethod(ByteBuffer byteBuffer) {
|
||||
* ComponentContextParser.buffer = byteBuffer; // Inserted by this patch.
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
ComponentContextParserFingerprint.result?.also {
|
||||
arrayOf(
|
||||
EmptyComponentBuilderFingerprint,
|
||||
ReadComponentIdentifierFingerprint,
|
||||
ProtobufBufferFingerprint
|
||||
ReadComponentIdentifierFingerprint
|
||||
).forEach { fingerprint ->
|
||||
if (fingerprint.resolve(context, it.mutableMethod, it.mutableClass)) return@forEach
|
||||
return fingerprint.toErrorResult()
|
||||
}
|
||||
}?.let { result ->
|
||||
}?.let { bytesToComponentContextMethod ->
|
||||
// region Add a static field that holds a reference to the protobuf buffer object.
|
||||
val protobufBufferField = ImmutableField(
|
||||
bytesToComponentContextMethod.mutableClass.type,
|
||||
"buffer",
|
||||
"Ljava/nio/ByteBuffer;",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).toMutable()
|
||||
bytesToComponentContextMethod.mutableClass.staticFields.add(protobufBufferField)
|
||||
|
||||
// Set the field with the reference to the protobuf buffer object.
|
||||
ProtobufBufferReferenceFingerprint.result
|
||||
?.mutableMethod?.addInstruction(0, "sput-object p2, $protobufBufferField")
|
||||
?: return ProtobufBufferReferenceFingerprint.toErrorResult()
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hook the method that parses bytes into a ComponentContext.
|
||||
|
||||
val builderMethodIndex = EmptyComponentBuilderFingerprint.patternScanEndIndex
|
||||
val emptyComponentFieldIndex = builderMethodIndex + 2
|
||||
|
||||
result.mutableMethod.apply {
|
||||
val insertHookIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
bytesToComponentContextMethod.mutableMethod.apply {
|
||||
val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
// region Get free registers that this patch uses
|
||||
// region Get free registers that this patch uses.
|
||||
// Registers are overwritten right after they are used in this patch, therefore free to clobber.
|
||||
|
||||
val freeRegistersInstruction = getInstruction<FiveRegisterInstruction>(insertHookIndex - 2)
|
||||
|
@ -64,7 +124,7 @@ class LithoFilterPatch : BytecodePatch(
|
|||
|
||||
// endregion
|
||||
|
||||
// region Get references that this patch needs
|
||||
// region Get references that this patch needs.
|
||||
|
||||
val builderMethodDescriptor = getInstruction(builderMethodIndex).descriptor
|
||||
val emptyComponentFieldDescriptor = getInstruction(emptyComponentFieldIndex).descriptor
|
||||
|
@ -72,34 +132,18 @@ class LithoFilterPatch : BytecodePatch(
|
|||
val identifierRegister =
|
||||
getInstruction<OneRegisterInstruction>(ReadComponentIdentifierFingerprint.patternScanEndIndex).registerA
|
||||
|
||||
// Parameter that holds a ref to a type with a field that ref the protobuf buffer object.
|
||||
val protobufParameterNumber = 3
|
||||
|
||||
// Get the field that stores an protobuf buffer required below.
|
||||
val protobufBufferRefTypeRefFieldDescriptor =
|
||||
getInstruction(ProtobufBufferFingerprint.patternScanStartIndex).descriptor
|
||||
val protobufBufferRefTypeDescriptor =
|
||||
getInstruction(ProtobufBufferFingerprint.patternScanEndIndex - 1).descriptor
|
||||
val protobufBufferFieldDescriptor = "$protobufBufferRefTypeDescriptor->b:Ljava/nio/ByteBuffer;"
|
||||
|
||||
// endregion
|
||||
|
||||
// region Patch the method
|
||||
// region Patch the method.
|
||||
|
||||
// Insert the instructions that are responsible
|
||||
// to return an EmptyComponent instead of the original component if the filter method returns false.
|
||||
addInstructionsWithLabels(
|
||||
insertHookIndex,
|
||||
"""
|
||||
# Get the protobuf buffer object.
|
||||
# Register "free1" holds the protobuf buffer object
|
||||
|
||||
move-object/from16 v$free1, p$protobufParameterNumber
|
||||
iget-object v$free1, v$free1, $protobufBufferRefTypeRefFieldDescriptor
|
||||
check-cast v$free1, $protobufBufferRefTypeDescriptor
|
||||
|
||||
# Register "free" now holds the protobuf buffer object
|
||||
|
||||
iget-object v$free1, v$free1, $protobufBufferFieldDescriptor
|
||||
sget-object v$free1, $protobufBufferField
|
||||
|
||||
# Invoke the filter method.
|
||||
|
||||
|
@ -119,6 +163,8 @@ class LithoFilterPatch : BytecodePatch(
|
|||
)
|
||||
// endregion
|
||||
}
|
||||
|
||||
// endregion
|
||||
} ?: return ComponentContextParserFingerprint.toErrorResult()
|
||||
|
||||
LithoFilterFingerprint.result?.mutableMethod?.apply {
|
||||
|
@ -150,9 +196,6 @@ class LithoFilterPatch : BytecodePatch(
|
|||
private val MethodFingerprint.patternScanEndIndex
|
||||
get() = patternScanResult.endIndex
|
||||
|
||||
private val MethodFingerprint.patternScanStartIndex
|
||||
get() = patternScanResult.startIndex
|
||||
|
||||
private val Instruction.descriptor
|
||||
get() = (this as ReferenceInstruction).reference.toString()
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.microg.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class MicroGPatchCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.minimizedplayback.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class MinimizedPlaybackCompatibility
|
|
@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
|
|||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object MinimizedPlaybackSettingsFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
returnType = "Ljava/lang/String;",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf(),
|
||||
opcodes = listOf(
|
||||
|
|
|
@ -8,7 +8,8 @@ import org.jf.dexlib2.AccessFlags
|
|||
* Class fingerprint for [MinimizedPlaybackSettingsFingerprint]
|
||||
*/
|
||||
object MinimizedPlaybackSettingsParentFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("Landroid/content/Context;", "Landroid/support/v4/media/session/MediaSessionCompat"),
|
||||
strings = listOf("sessionToken must not be null")
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
returnType = "I",
|
||||
parameters = listOf(),
|
||||
strings = listOf("BiometricManager", "Failure in canAuthenticate(). FingerprintManager was null.")
|
||||
)
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.playercontrols.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerControlsCompatibility
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.playeroverlay.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerOverlaysHookCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.playertype.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerTypeHookCompatibility
|
||||
|
|
|
@ -4,6 +4,6 @@ import app.revanced.patcher.annotation.Compatibility
|
|||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
// TODO: delete this
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class CustomVideoBufferCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.video.hdrbrightness.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HDRBrightnessCompatibility
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.video.information.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class VideoInformationCompatibility
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package app.revanced.patches.youtube.video.oldqualitylayout.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.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.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.video.oldqualitylayout.annotations.OldQualityLayoutCompatibility
|
||||
import app.revanced.patches.youtube.video.oldqualitylayout.fingerprints.QualityMenuViewInflateFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, OldQualityLayoutResourcePatch::class])
|
||||
@Name("old-quality-layout")
|
||||
@Description("Enables the original video quality flyout in the video player settings.")
|
||||
@OldQualityLayoutCompatibility
|
||||
@Version("0.0.1")
|
||||
class OldQualityLayoutPatch : BytecodePatch(listOf(QualityMenuViewInflateFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
val inflateFingerprintResult = QualityMenuViewInflateFingerprint.result!!
|
||||
val method = inflateFingerprintResult.mutableMethod
|
||||
val instructions = method.implementation!!.instructions
|
||||
|
||||
// at this index the listener is added to the list view
|
||||
val listenerInvokeRegister = instructions.size - 1 - 1
|
||||
|
||||
// get the register which stores the quality menu list view
|
||||
val onItemClickViewRegister = (instructions[listenerInvokeRegister] as FiveRegisterInstruction).registerC
|
||||
|
||||
// insert the integrations method
|
||||
method.addInstruction(
|
||||
listenerInvokeRegister, // insert the integrations instructions right before the listener
|
||||
"invoke-static { v$onItemClickViewRegister }, Lapp/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch;->showOldQualityMenu(Landroid/widget/ListView;)V"
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package app.revanced.patches.youtube.video.oldqualitylayout.patch
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
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.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
class OldQualityLayoutResourcePatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_show_old_video_menu",
|
||||
StringResource("revanced_show_old_video_menu_title", "Use old video quality player menu"),
|
||||
StringResource("revanced_show_old_video_menu_summary_on", "Old video quality menu is used"),
|
||||
StringResource("revanced_show_old_video_menu_summary_off", "Old video quality menu is not used")
|
||||
)
|
||||
)
|
||||
|
||||
videoQualityBottomSheetListFragmentTitle =
|
||||
ResourceMappingPatch.resourceMappings.find { it.name == "video_quality_bottom_sheet_list_fragment_title" }
|
||||
?.id ?: return PatchResultError("Could not find resource")
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
var videoQualityBottomSheetListFragmentTitle = -1L
|
||||
}
|
||||
}
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.video.quality.annotations
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class RememberVideoQualityCompatibility
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package app.revanced.patches.youtube.video.quality.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object NewVideoQualityChangedFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET, // Video resolution (human readable).
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_BOOLEAN,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET,
|
||||
)
|
||||
)
|
|
@ -3,6 +3,9 @@ package app.revanced.patches.youtube.video.quality.fingerprints
|
|||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves with the class found in [VideoQualitySetterFingerprint].
|
||||
*/
|
||||
object SetQualityByIndexMethodClassFieldReferenceFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
parameters = listOf("L"),
|
||||
|
|
|
@ -7,6 +7,7 @@ import app.revanced.patcher.annotation.Version
|
|||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
|
@ -22,10 +23,12 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
|||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.video.quality.annotations.RememberVideoQualityCompatibility
|
||||
import app.revanced.patches.youtube.video.quality.fingerprints.NewVideoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.video.quality.fingerprints.SetQualityByIndexMethodClassFieldReferenceFingerprint
|
||||
import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualityItemOnClickParentFingerprint
|
||||
import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualitySetterFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch
|
||||
|
@ -37,7 +40,8 @@ import org.jf.dexlib2.iface.reference.FieldReference
|
|||
class RememberVideoQualityPatch : BytecodePatch(
|
||||
listOf(
|
||||
VideoQualitySetterFingerprint,
|
||||
VideoQualityItemOnClickParentFingerprint
|
||||
VideoQualityItemOnClickParentFingerprint,
|
||||
NewVideoQualityChangedFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
|
@ -113,6 +117,7 @@ class RememberVideoQualityPatch : BytecodePatch(
|
|||
|
||||
VideoInformationPatch.onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "newVideoStarted")
|
||||
|
||||
|
||||
// Inject a call to set the remembered quality once a video loads.
|
||||
VideoQualitySetterFingerprint.result?.also {
|
||||
if (!SetQualityByIndexMethodClassFieldReferenceFingerprint.resolve(context, it.classDef))
|
||||
|
@ -159,6 +164,7 @@ class RememberVideoQualityPatch : BytecodePatch(
|
|||
)
|
||||
} ?: return VideoQualitySetterFingerprint.toErrorResult()
|
||||
|
||||
|
||||
// Inject a call to remember the selected quality.
|
||||
VideoQualityItemOnClickParentFingerprint.result?.let {
|
||||
val onItemClickMethod = it.mutableClass.methods.find { method -> method.name == "onItemClick" }
|
||||
|
@ -172,6 +178,22 @@ class RememberVideoQualityPatch : BytecodePatch(
|
|||
)
|
||||
} ?: return PatchResultError("Failed to find onItemClick method")
|
||||
} ?: return VideoQualityItemOnClickParentFingerprint.toErrorResult()
|
||||
|
||||
|
||||
// Remember video quality if not using old layout menu.
|
||||
NewVideoQualityChangedFingerprint.result?.apply {
|
||||
mutableMethod.apply {
|
||||
val index = scanResult.patternScanResult!!.startIndex
|
||||
val qualityRegister = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstruction(
|
||||
index + 1,
|
||||
"invoke-static {v$qualityRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->userChangedQualityInNewFlyout(I)V"
|
||||
)
|
||||
}
|
||||
} ?: return NewVideoQualityChangedFingerprint.toErrorResult()
|
||||
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,7 @@ import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackS
|
|||
@VideoSpeedCompatibility
|
||||
@Version("0.0.1")
|
||||
class VideoSpeed : BytecodePatch() {
|
||||
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
return PatchResultSuccess() // All patches this patch depends on succeed.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.video.speed
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class VideoSpeedCompatibility
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package app.revanced.patches.youtube.video.speed.custom.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object GetOldVideoSpeedsFingerprint : MethodFingerprint(
|
||||
parameters = listOf("[L", "I"),
|
||||
strings = listOf("menu_item_playback_speed")
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
package app.revanced.patches.youtube.video.speed.custom.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object ShowOldVideoSpeedMenuFingerprint : MethodFingerprint(
|
||||
strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
package app.revanced.patches.youtube.video.speed.custom.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object ShowOldVideoSpeedMenuIntegrationsFingerprint : MethodFingerprint(
|
||||
customFingerprint = { method, _ -> method.name == "showOldVideoSpeedMenu" }
|
||||
)
|
|
@ -1,36 +1,46 @@
|
|||
package app.revanced.patches.youtube.video.speed.custom.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.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.settings.preference.impl.InputType
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patches.shared.settings.preference.impl.*
|
||||
import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookPatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint
|
||||
import app.revanced.patches.youtube.video.speed.custom.fingerprints.SpeedLimiterFingerprint
|
||||
import app.revanced.patches.youtube.video.speed.custom.fingerprints.*
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
import org.jf.dexlib2.immutable.ImmutableField
|
||||
|
||||
@Name("custom-video-speed")
|
||||
@Description("Adds custom video speed options.")
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, BottomSheetHookPatch::class])
|
||||
@Version("0.0.1")
|
||||
class CustomVideoSpeedPatch : BytecodePatch(
|
||||
listOf(
|
||||
SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint
|
||||
SpeedArrayGeneratorFingerprint,
|
||||
SpeedLimiterFingerprint,
|
||||
GetOldVideoSpeedsFingerprint,
|
||||
ShowOldVideoSpeedMenuIntegrationsFingerprint
|
||||
)
|
||||
) {
|
||||
|
||||
|
@ -45,7 +55,7 @@ class CustomVideoSpeedPatch : BytecodePatch(
|
|||
inputType = InputType.TEXT_MULTI_LINE,
|
||||
summary = StringResource(
|
||||
"revanced_custom_playback_speeds_summary",
|
||||
"Add or change the video speeds available"
|
||||
"Add or change the available playback speeds"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -71,7 +81,7 @@ class CustomVideoSpeedPatch : BytecodePatch(
|
|||
|
||||
val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
|
||||
|
||||
val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->customVideoSpeeds:[F"
|
||||
val videoSpeedsArrayType = "$INTEGRATIONS_CLASS_DESCRIPTOR->customVideoSpeeds:[F"
|
||||
|
||||
arrayGenMethod.addInstructions(
|
||||
arrayLengthConstIndex + 1,
|
||||
|
@ -111,14 +121,72 @@ class CustomVideoSpeedPatch : BytecodePatch(
|
|||
// edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x
|
||||
limiterMethod.replaceInstruction(
|
||||
limiterMinConstIndex,
|
||||
"sget v$limiterMinConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->minVideoSpeed:F"
|
||||
"sget v$limiterMinConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->minVideoSpeed:F"
|
||||
)
|
||||
limiterMethod.replaceInstruction(
|
||||
limiterMaxConstIndex,
|
||||
"sget v$limiterMaxConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->maxVideoSpeed:F"
|
||||
"sget v$limiterMaxConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->maxVideoSpeed:F"
|
||||
)
|
||||
|
||||
// region Force old video quality menu.
|
||||
// This is necessary, because there is no known way of adding custom video speeds to the new menu.
|
||||
|
||||
BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
|
||||
// Required to check if the video speed menu is currently shown.
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
GetOldVideoSpeedsFingerprint.result?.let { result ->
|
||||
// Add a static INSTANCE field to the class.
|
||||
// This is later used to call "showOldVideoSpeedMenu" on the instance.
|
||||
val instanceField = ImmutableField(
|
||||
result.classDef.type,
|
||||
"INSTANCE",
|
||||
result.classDef.type,
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).toMutable()
|
||||
|
||||
result.mutableClass.staticFields.add(instanceField)
|
||||
// Set the INSTANCE field to the instance of the class.
|
||||
// In order to prevent a conflict with another patch, add the instruction at index 1.
|
||||
result.mutableMethod.addInstruction(1, "sput-object p0, $instanceField")
|
||||
|
||||
// Get the "showOldVideoSpeedMenu" method.
|
||||
// This is later called on the field INSTANCE.
|
||||
val showOldVideoSpeedMenuMethod = ShowOldVideoSpeedMenuFingerprint.also {
|
||||
if (!it.resolve(context, result.classDef))
|
||||
throw ShowOldVideoSpeedMenuFingerprint.toErrorResult()
|
||||
}.result!!.method.toString()
|
||||
|
||||
// Insert the call to the "showOldVideoSpeedMenu" method on the field INSTANCE.
|
||||
ShowOldVideoSpeedMenuIntegrationsFingerprint.result?.mutableMethod?.apply {
|
||||
addInstructionsWithLabels(
|
||||
implementation!!.instructions.lastIndex,
|
||||
"""
|
||||
sget-object v0, $instanceField
|
||||
if-nez v0, :not_null
|
||||
return-void
|
||||
:not_null
|
||||
invoke-virtual { v0 }, $showOldVideoSpeedMenuMethod
|
||||
"""
|
||||
)
|
||||
} ?: return ShowOldVideoSpeedMenuIntegrationsFingerprint.toErrorResult()
|
||||
} ?: return GetOldVideoSpeedsFingerprint.toErrorResult()
|
||||
|
||||
// endregion
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch;"
|
||||
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;"
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ package app.revanced.patches.youtube.video.videoid.annotation
|
|||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class VideoIdCompatibility
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package app.revanced.patches.youtube.video.oldqualitylayout.annotations
|
||||
package app.revanced.patches.youtube.video.videoqualitymenu.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class OldQualityLayoutCompatibility
|
||||
internal annotation class OldVideoQualityMenuCompatibility
|
|
@ -1,12 +1,12 @@
|
|||
package app.revanced.patches.youtube.video.oldqualitylayout.fingerprints
|
||||
package app.revanced.patches.youtube.video.videoqualitymenu.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.video.videoqualitymenu.patch.OldVideoQualityMenuResourcePatch
|
||||
import app.revanced.util.patch.LiteralValueFingerprint
|
||||
import app.revanced.patches.youtube.video.oldqualitylayout.patch.OldQualityLayoutResourcePatch
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object QualityMenuViewInflateFingerprint : LiteralValueFingerprint(
|
||||
object VideoQualityMenuViewInflateFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L", "L"),
|
||||
returnType = "L",
|
||||
|
@ -26,5 +26,5 @@ object QualityMenuViewInflateFingerprint : LiteralValueFingerprint(
|
|||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST
|
||||
),
|
||||
literal = OldQualityLayoutResourcePatch.videoQualityBottomSheetListFragmentTitle
|
||||
literal = OldVideoQualityMenuResourcePatch.videoQualityBottomSheetListFragmentTitle
|
||||
)
|
|
@ -0,0 +1,73 @@
|
|||
package app.revanced.patches.youtube.video.videoqualitymenu.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
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.youtube.misc.bottomsheet.hook.patch.BottomSheetHookPatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.video.videoqualitymenu.annotations.OldVideoQualityMenuCompatibility
|
||||
import app.revanced.patches.youtube.video.videoqualitymenu.fingerprints.VideoQualityMenuViewInflateFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@DependsOn([
|
||||
IntegrationsPatch::class,
|
||||
OldVideoQualityMenuResourcePatch::class,
|
||||
LithoFilterPatch::class,
|
||||
BottomSheetHookPatch::class
|
||||
])
|
||||
@Name("old-video-quality-menu")
|
||||
@Description("Shows the old video quality with the advanced video quality options instead of the new one.")
|
||||
@OldVideoQualityMenuCompatibility
|
||||
@Version("0.0.1")
|
||||
class OldVideoQualityMenuPatch : BytecodePatch(
|
||||
listOf(VideoQualityMenuViewInflateFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
// region Patch for the old type of the video quality menu.
|
||||
|
||||
VideoQualityMenuViewInflateFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val checkCastIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val listViewRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"invoke-static { v$listViewRegister }, " +
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->" +
|
||||
"showOldVideoQualityMenu(Landroid/widget/ListView;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Patch for the new type of the video quality menu.
|
||||
|
||||
BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
|
||||
// Required to check if the video quality menu is currently shown in order to click on the "Advanced" item.
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// endregion
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/VideoQualityMenuFilterPatch;"
|
||||
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch;"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package app.revanced.patches.youtube.video.videoqualitymenu.patch
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
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.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
class OldVideoQualityMenuResourcePatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_show_old_video_quality_menu",
|
||||
StringResource("revanced_show_old_video_quality_menu_title", "Show old video quality menu"),
|
||||
StringResource("revanced_show_old_video_quality_menu_summary_on", "Old video quality menu is shown"),
|
||||
StringResource("revanced_show_old_video_quality_menu_summary_off", "New video quality menu is hidden")
|
||||
)
|
||||
)
|
||||
|
||||
fun findResource(name: String) = ResourceMappingPatch.resourceMappings.find { it.name == name }?.id
|
||||
?: throw PatchResultError("Could not find resource")
|
||||
|
||||
// Used for the old type of the video quality menu.
|
||||
videoQualityBottomSheetListFragmentTitle = findResource("video_quality_bottom_sheet_list_fragment_title")
|
||||
|
||||
// Used for the new type of the video quality menu.
|
||||
bottomSheetMargins = findResource("bottom_sheet_margins")
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
var videoQualityBottomSheetListFragmentTitle = -1L
|
||||
var bottomSheetMargins = -1L
|
||||
}
|
||||
}
|
|
@ -190,5 +190,4 @@
|
|||
<string name="sb_about">About</string>
|
||||
<string name="sb_about_api">sponsor.ajay.app</string>
|
||||
<string name="sb_about_api_sum">Data is provided by the SponsorBlock API. Tap here to learn more and see downloads for other platforms</string>
|
||||
<string name="sb_about_made_by">ReVanced integration by JakubWeg,\nrecoded by oSumAtrIX</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue