Compare commits

..

26 Commits

Author SHA1 Message Date
semantic-release-bot
769b1932d4 chore(release): 2.174.0-dev.39 [skip ci]
# [2.174.0-dev.39](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.38...v2.174.0-dev.39) (2023-05-22)

### Features

* **reddit:** remove compatibility version constraints ([#2226](https://github.com/revanced/revanced-patches/issues/2226)) ([324d4b8](324d4b83d3))
2023-05-22 19:31:24 +00:00
KAZI MMT
324d4b83d3 feat(reddit): remove compatibility version constraints (#2226) 2023-05-22 21:28:51 +02:00
semantic-release-bot
97822d6ee7 chore(release): 2.174.0-dev.38 [skip ci]
# [2.174.0-dev.38](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.37...v2.174.0-dev.38) (2023-05-21)

### Features

* **trakt:** add `unlock-pro` patch ([#2210](https://github.com/revanced/revanced-patches/issues/2210)) ([6767417](67674170da))
2023-05-21 17:29:44 +00:00
johnconner122
67674170da feat(trakt): add unlock-pro patch (#2210)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-05-21 19:27:50 +02:00
semantic-release-bot
76711f0785 chore(release): 2.174.0-dev.37 [skip ci]
# [2.174.0-dev.37](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.36...v2.174.0-dev.37) (2023-05-21)

### Features

* **reddit:** add `sanitize-sharing-links` patch ([#2192](https://github.com/revanced/revanced-patches/issues/2192)) ([4178ca3](4178ca3be1))
2023-05-21 15:57:02 +00:00
KAZI MMT
4178ca3be1 feat(reddit): add sanitize-sharing-links patch (#2192)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-05-21 17:55:10 +02:00
semantic-release-bot
c681316ee1 chore(release): 2.174.0-dev.36 [skip ci]
# [2.174.0-dev.36](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.35...v2.174.0-dev.36) (2023-05-20)

### Bug Fixes

* **twitter:** correctly resolve to integrations methods ([b56844d](b56844dc6b))
2023-05-20 02:35:28 +00:00
oSumAtrIX
b56844dc6b fix(twitter): correctly resolve to integrations methods 2023-05-20 04:32:39 +02:00
semantic-release-bot
d4843d185a chore(release): 2.174.0-dev.35 [skip ci]
# [2.174.0-dev.35](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.34...v2.174.0-dev.35) (2023-05-19)

### Bug Fixes

* **youtube/minimized-playback:** update settings description ([#2191](https://github.com/revanced/revanced-patches/issues/2191)) ([ebf144e](ebf144e2c8))
* **youtube/settings:** fix non functional back button in settings ([#2178](https://github.com/revanced/revanced-patches/issues/2178)) ([52029ee](52029ee987))

### Features

* add capability to filter from protobuf buffer ([7e2502c](7e2502c26b))
* use consistent names for patches ([acb9b5f](acb9b5fe6b))
* **youtube/copy-video-url:** add tap and hold functionality to copy video url buttons ([#2174](https://github.com/revanced/revanced-patches/issues/2174)) ([80661db](80661dbf43))
* **youtube/hide-shorts-components:** hide navigation bar ([8e627c6](8e627c682f))
* **youtube:** add `hide-shorts-components` patch ([af82eb6](af82eb633c))
* **youtube:** constrain patches to `18.16.37` ([d746f32](d746f32594))
* **youtube:** support version `18.19.35` ([3cfbe20](3cfbe206dc))
2023-05-19 21:46:05 +00:00
LisoUseInAIKyrios
52029ee987 fix(youtube/settings): fix non functional back button in settings (#2178) 2023-05-19 23:43:49 +02:00
LisoUseInAIKyrios
80661dbf43 feat(youtube/copy-video-url): add tap and hold functionality to copy video url buttons (#2174) 2023-05-19 23:43:48 +02:00
oSumAtrIX
e9b2b72681 chore: use correct description for patch 2023-05-19 23:43:48 +02:00
oSumAtrIX
b4110fb798 refactor: remove spacing 2023-05-19 23:43:48 +02:00
oSumAtrIX
3cfbe206dc feat(youtube): support version 18.19.35 2023-05-19 23:43:47 +02:00
oSumAtrIX
1d0bf1b289 refactor(youtube/remember-playback-speed): do not use other unrelated patches extension methods 2023-05-19 23:43:47 +02:00
oSumAtrIX
99de705e8e refactor(youtube/settings): increase fingerprint robustness 2023-05-19 23:43:46 +02:00
oSumAtrIX
d746f32594 feat(youtube): constrain patches to 18.16.37 2023-05-19 23:43:46 +02:00
johnconner122
ebf144e2c8 fix(youtube/minimized-playback): update settings description (#2191) 2023-05-19 23:43:46 +02:00
oSumAtrIX
8e627c682f feat(youtube/hide-shorts-components): hide navigation bar 2023-05-18 19:06:06 +02:00
oSumAtrIX
af82eb633c feat(youtube): add hide-shorts-components patch 2023-05-18 19:06:05 +02:00
oSumAtrIX
acb9b5fe6b feat: use consistent names for patches 2023-05-18 18:59:35 +02:00
oSumAtrIX
7e2502c26b feat: add capability to filter from protobuf buffer 2023-05-18 18:59:35 +02:00
semantic-release-bot
1fcdc74056 chore(release): 2.174.0-dev.34 [skip ci]
# [2.174.0-dev.34](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.33...v2.174.0-dev.34) (2023-05-16)

### Features

* **vsco:** add `unlock-pro` patch ([#2168](https://github.com/revanced/revanced-patches/issues/2168)) ([91ee6b7](91ee6b7750))
2023-05-16 21:52:12 +00:00
redphx
91ee6b7750 feat(vsco): add unlock-pro patch (#2168)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-05-16 23:50:33 +02:00
semantic-release-bot
3a905484c0 chore(release): 2.174.0-dev.33 [skip ci]
# [2.174.0-dev.33](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.32...v2.174.0-dev.33) (2023-05-16)

### Bug Fixes

* **youtube/spoof-signature-verification:** adjusting summary text ([#2169](https://github.com/revanced/revanced-patches/issues/2169)) ([677c0f8](677c0f8145))
2023-05-16 17:28:32 +00:00
LisoUseInAIKyrios
677c0f8145 fix(youtube/spoof-signature-verification): adjusting summary text (#2169) 2023-05-16 21:26:42 +04:00
141 changed files with 1488 additions and 1579 deletions

View File

@@ -1,3 +1,64 @@
# [2.174.0-dev.39](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.38...v2.174.0-dev.39) (2023-05-22)
### Features
* **reddit:** remove compatibility version constraints ([#2226](https://github.com/revanced/revanced-patches/issues/2226)) ([f1288e4](https://github.com/revanced/revanced-patches/commit/f1288e4bb8fb1b9f394d73fd814d97db8704b8e0))
# [2.174.0-dev.38](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.37...v2.174.0-dev.38) (2023-05-21)
### Features
* **trakt:** add `unlock-pro` patch ([#2210](https://github.com/revanced/revanced-patches/issues/2210)) ([1e8dcae](https://github.com/revanced/revanced-patches/commit/1e8dcae6f540455b8698703bbded5f52fd0c6300))
# [2.174.0-dev.37](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.36...v2.174.0-dev.37) (2023-05-21)
### Features
* **reddit:** add `sanitize-sharing-links` patch ([#2192](https://github.com/revanced/revanced-patches/issues/2192)) ([9593e4b](https://github.com/revanced/revanced-patches/commit/9593e4b5db604957545b4ab6747c82fb815ac08b))
# [2.174.0-dev.36](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.35...v2.174.0-dev.36) (2023-05-20)
### Bug Fixes
* **twitter:** correctly resolve to integrations methods ([c655416](https://github.com/revanced/revanced-patches/commit/c655416a91f0a32cfe82b1384f5958cace891833))
# [2.174.0-dev.35](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.34...v2.174.0-dev.35) (2023-05-19)
### Bug Fixes
* **youtube/minimized-playback:** update settings description ([#2191](https://github.com/revanced/revanced-patches/issues/2191)) ([a561a9a](https://github.com/revanced/revanced-patches/commit/a561a9afc233e466459546fcc8452800ec56e057))
* **youtube/settings:** fix non functional back button in settings ([#2178](https://github.com/revanced/revanced-patches/issues/2178)) ([46da834](https://github.com/revanced/revanced-patches/commit/46da83430f69b451f971bf5e9261e9d64d1a365c))
### Features
* add capability to filter from protobuf buffer ([b738b6b](https://github.com/revanced/revanced-patches/commit/b738b6bf3506f222844ef4bca99a91f78d331391))
* use consistent names for patches ([6347146](https://github.com/revanced/revanced-patches/commit/634714690086168e63d6aa9475893135cb58db68))
* **youtube/copy-video-url:** add tap and hold functionality to copy video url buttons ([#2174](https://github.com/revanced/revanced-patches/issues/2174)) ([95bbf46](https://github.com/revanced/revanced-patches/commit/95bbf46e77a608bd7ba8f0073d50fef01012d4df))
* **youtube/hide-shorts-components:** hide navigation bar ([24f376a](https://github.com/revanced/revanced-patches/commit/24f376a4b8d6bdccc32ffff0d983f22eb4940791))
* **youtube:** add `hide-shorts-components` patch ([64868f4](https://github.com/revanced/revanced-patches/commit/64868f41be9f567cb54d9214fafbf849d08b64d2))
* **youtube:** constrain patches to `18.16.37` ([758b300](https://github.com/revanced/revanced-patches/commit/758b3005919e11d9dd4f19bf110e9d282f8d1925))
* **youtube:** support version `18.19.35` ([491f292](https://github.com/revanced/revanced-patches/commit/491f292182a419cb5399de768560ae4daa7c86cb))
# [2.174.0-dev.34](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.33...v2.174.0-dev.34) (2023-05-16)
### Features
* **vsco:** add `unlock-pro` patch ([#2168](https://github.com/revanced/revanced-patches/issues/2168)) ([7ffd1a0](https://github.com/revanced/revanced-patches/commit/7ffd1a09a7bcf09bc7e7d5f3c8c8613ca34c8c59))
# [2.174.0-dev.33](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.32...v2.174.0-dev.33) (2023-05-16)
### Bug Fixes
* **youtube/spoof-signature-verification:** adjusting summary text ([#2169](https://github.com/revanced/revanced-patches/issues/2169)) ([4ccb1ee](https://github.com/revanced/revanced-patches/commit/4ccb1ee0b988bc0ddd6a0c986975b17caa828770))
# [2.174.0-dev.32](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.31...v2.174.0-dev.32) (2023-05-16)

132
README.md
View File

@@ -9,60 +9,61 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `always-autorepeat` | Always repeats the playing video again. | 18.16.37 |
| `client-spoof` | Spoofs a patched client to allow playback. | 18.16.37 |
| `comments` | Hides components related to comments. | 18.16.37 |
| `copy-video-url` | Adds buttons in player to copy video links. | 18.16.37 |
| `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.16.37 |
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.16.37 |
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.16.37 |
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.16.37 |
| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.16.37 |
| `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 |
| `downloads` | Adds a download button to the YouTube video player. | 18.16.37 |
| `downloads` | Adds a download button to the YouTube video player. | 18.19.35 |
| `enable-debugging` | Adds debugging options. | all |
| `general-ads` | Removes general ads. | 18.16.37 |
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.16.37 |
| `hide-album-cards` | Hides the album cards below the artist description. | 18.16.37 |
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.16.37 |
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.16.37 |
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.16.37 |
| `hide-captions-button` | Hides the captions button on video player. | 18.16.37 |
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
| `hide-ads` | Removes general ads. | 18.19.35 |
| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.19.35 |
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
| `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.16.37 |
| `hide-email-address` | Hides the email address in the account switcher. | 18.16.37 |
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.16.37 |
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.16.37 |
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.16.37 |
| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.16.37 |
| `hide-info-cards` | Hides info cards in videos. | 18.16.37 |
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.16.37 |
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 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-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.19.35 |
| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
| `hide-seekbar` | Hides the seekbar. | 18.16.37 |
| `hide-timestamp` | Hides timestamp in video player. | 18.16.37 |
| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.16.37 |
| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.16.37 |
| `hide-watermark` | Hides creator's watermarks on videos. | 18.16.37 |
| `minimized-playback` | Enables minimized and background playback. | 18.16.37 |
| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.16.37 |
| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.16.37 |
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.16.37 |
| `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.16.37 |
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.16.37 |
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.16.37 |
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.16.37 |
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.16.37 |
| `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.16.37 |
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.16.37 |
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.16.37 |
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.19.35 |
| `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.16.37 |
| `video-ads` | Removes ads in the video player. | 18.16.37 |
| `video-speed` | Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout. | 18.16.37 |
| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.16.37 |
| `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)
@@ -140,6 +141,17 @@ The official ReVanced Patches.
| `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
</details>
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `hide-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | 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.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
<details>
@@ -160,16 +172,6 @@ The official ReVanced Patches.
| `hide-inbox-ads` | Hides ads in inbox. | all |
</details>
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | 2023.12.0 |
| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | 2023.12.0 |
| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
</details>
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
<details>
@@ -340,6 +342,14 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all pro 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>
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
<details>
@@ -372,6 +382,14 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
</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.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
<details>

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official
version = 2.174.0-dev.32
version = 2.174.0-dev.39

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,15 @@
package app.revanced.extensions
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.util.MethodUtil
import org.w3c.dom.Node
@@ -15,7 +19,7 @@ import org.w3c.dom.Node
*
* @return A [PatchResultError] for the [MethodFingerprint].
*/
fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
internal fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
/**
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
@@ -23,7 +27,7 @@ fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $nam
* @param method The [Method] to find.
* @return The [MutableMethod].
*/
fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
internal fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
MethodUtil.methodSignaturesMatch(it, method)
}
@@ -32,7 +36,7 @@ fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
*
* @param transform the transformation function. original method goes in, transformed method goes out
*/
fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
internal fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
val transformedMethods = methods.map { it.transform() }
methods.clear()
methods.addAll(transformedMethods)
@@ -41,4 +45,29 @@ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod)
internal fun Node.doRecursively(action: (Node) -> Unit) {
action(this)
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
}
internal fun MutableMethod.injectHideViewCall(
insertIndex: Int,
viewRegister: Int,
classDescriptor: String,
targetMethod: String
) = addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V"
)
internal fun MutableMethod.findIndexForIdResource(resourceName: String): Int {
fun getIdResourceId(resourceName: String) = ResourceMappingPatch.resourceMappings.single {
it.type == "id" && it.name == resourceName
}.id
val resourceId = getIdResourceId(resourceName)
return implementation!!.instructions.indexOfFirst {
if (it.opcode != Opcode.CONST) return@indexOfFirst false
val literal = (it as WideLiteralInstruction).wideLiteral
return@indexOfFirst resourceId == literal
}
}

View File

@@ -5,18 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.reddit.frontpage", arrayOf(
"2023.05.0",
"2023.06.0",
"2023.07.0",
"2023.07.1",
"2023.08.0",
"2023.09.0",
"2023.09.1",
"2023.10.0",
"2023.11.0",
"2023.12.0"
)
"com.reddit.frontpage"
)]
)
@Target(AnnotationTarget.CLASS)

View File

@@ -1,25 +0,0 @@
package app.revanced.patches.reddit.ad.general.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.reddit.frontpage", arrayOf(
"2021.45.0",
"2022.43.0",
"2023.05.0",
"2023.06.0",
"2023.07.0",
"2023.07.1",
"2023.08.0",
"2023.09.0",
"2023.09.1",
"2023.10.0",
"2023.11.0",
"2023.12.0"
)
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class GeneralAdsCompatibility

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.reddit.ad.general.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.reddit.frontpage"
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class HideAdsCompatibility

View File

@@ -8,7 +8,7 @@ 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.reddit.ad.general.annotations.GeneralAdsCompatibility
import app.revanced.patches.reddit.ad.general.annotations.HideAdsCompatibility
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@@ -16,11 +16,11 @@ import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
@Patch
@Name("general-reddit-ads")
@Name("hide-ads")
@Description("Removes general ads from the Reddit frontpage and subreddits.")
@GeneralAdsCompatibility
@HideAdsCompatibility
@Version("0.0.1")
class GeneralAdsPatch : BytecodePatch() {
class HideAdsPatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach methodLoop@{ method ->

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.reddit.misc.tracking.url.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.reddit.frontpage"
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class SanitizeUrlQueryCompatibility

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.reddit.misc.tracking.url.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 ShareLinkFactoryFingerprint : MethodFingerprint(
returnType = "L",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.INVOKE_DIRECT,
Opcode.APUT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC, // Returns the URL.
Opcode.MOVE_RESULT_OBJECT
),
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("ShareLinkFactory;") }
)

View File

@@ -0,0 +1,52 @@
package app.revanced.patches.reddit.misc.tracking.url.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.reddit.misc.tracking.url.annotations.SanitizeUrlQueryCompatibility
import app.revanced.patches.reddit.misc.tracking.url.fingerprints.ShareLinkFactoryFingerprint
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@Name("sanitize-sharing-links")
@Description("Removes (tracking) query parameters from the URLs when sharing links.")
@SanitizeUrlQueryCompatibility
@Version("0.0.1")
@RequiresIntegrations
class SanitizeUrlQueryPatch : BytecodePatch(
listOf(ShareLinkFactoryFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
ShareLinkFactoryFingerprint.result?.let { result ->
result.mutableMethod.apply {
val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
val urlRegister = instruction<OneRegisterInstruction>(insertIndex - 1).registerA
addInstructions(
insertIndex,
"""
invoke-static {v$urlRegister}, $SANITIZE_METHOD_DESCRIPTOR
move-result-object v$urlRegister
"""
)
}
} ?: return ShareLinkFactoryFingerprint.toErrorResult()
return PatchResultSuccess()
}
private companion object {
private const val SANITIZE_METHOD_DESCRIPTOR =
"Lapp/revanced/reddit/patches/SanitizeUrlQueryPatch;" +
"->stripQueryParameters(Ljava/lang/String;)Ljava/lang/String;"
}
}

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.shared.misc.fix.spoof.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class ClientSpoofCompatibility

View File

@@ -13,7 +13,7 @@ import app.revanced.patches.shared.misc.fix.verticalscroll.annotations.VerticalS
import app.revanced.patches.shared.misc.fix.verticalscroll.fingerprints.CanScrollVerticallyFingerprint
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Description("Fixes issues with scrolling on the home screen when the first component is of type EmptyComponent.")
@Description("Fixes issues with refreshing the feed when the first component is of type EmptyComponent.")
@VerticalScrollCompatibility
@Version("0.0.1")
class VerticalScrollPatch : BytecodePatch(

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.trakt.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("tv.trakt.trakt")])
@Target(AnnotationTarget.CLASS)
internal annotation class UnlockProCompatibility

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.trakt.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsVIPEPFingerprint : MethodFingerprint(
customFingerprint = custom@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("RealmUserSettings;")) return@custom false
methodDef.name == "isVIPEP"
}
)

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.trakt.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsVIPFingerprint : MethodFingerprint(
customFingerprint = custom@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("RealmUserSettings;")) return@custom false
methodDef.name == "isVIP"
}
)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.trakt.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object RealmUserSettingsFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("RealmUserSettings;")
}
)

View File

@@ -0,0 +1,52 @@
package app.revanced.patches.trakt.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.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.Patch
import app.revanced.patches.trakt.annotations.UnlockProCompatibility
import app.revanced.patches.trakt.fingerprints.IsVIPEPFingerprint
import app.revanced.patches.trakt.fingerprints.IsVIPFingerprint
import app.revanced.patches.trakt.fingerprints.RealmUserSettingsFingerprint
@Patch
@Name("unlock-pro")
@Description("Unlocks pro features.")
@UnlockProCompatibility
@Version("0.0.1")
class UnlockProPatch : BytecodePatch(
listOf(RealmUserSettingsFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
RealmUserSettingsFingerprint.result?.classDef?.let { realUserSettingsClass ->
arrayOf(IsVIPFingerprint, IsVIPEPFingerprint).onEach { fingerprint ->
// Resolve both fingerprints on the same class.
if (!fingerprint.resolve(context, realUserSettingsClass))
throw fingerprint.toErrorResult()
}.forEach { fingerprint ->
// Return true for both VIP check methods.
fingerprint.result?.mutableMethod?.addInstructions(0, RETURN_TRUE_INSTRUCTIONS)
?: return fingerprint.toErrorResult()
}
} ?: return RealmUserSettingsFingerprint.toErrorResult()
return PatchResultSuccess()
}
private companion object {
const val RETURN_TRUE_INSTRUCTIONS =
"""
const/4 v0, 0x1
invoke-static {v0}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
move-result-object v1
return-object v1
"""
}
}

View File

@@ -5,5 +5,9 @@ import org.jf.dexlib2.Opcode
object JsonHookPatchFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> methodDef.name == "<clinit>" },
opcodes = listOf(Opcode.IGET_OBJECT)
opcodes = listOf(
Opcode.INVOKE_INTERFACE, // Add dummy hook to hooks list.
// Add hooks to the hooks list.
Opcode.INVOKE_STATIC // Call buildList.
)
)

View File

@@ -5,13 +5,18 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.removeInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.*
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.RequiresIntegrations
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonHookPatchFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonInputStreamFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint
import java.io.Closeable
import java.io.InvalidClassException
@Name("json-hook")
@@ -20,16 +25,16 @@ import java.io.InvalidClassException
@RequiresIntegrations
class JsonHookPatch : BytecodePatch(
listOf(LoganSquareFingerprint)
) {
), Closeable {
override fun execute(context: BytecodeContext): PatchResult {
// Make sure the integrations are present.
val jsonHookPatch = context.findClass { it.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
?: return PatchResultError("Could not find integrations.")
JsonHookPatchFingerprint.also {
// Make sure the integrations are present.
val jsonHookPatch = context.findClass { classDef -> classDef.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
?: throw PatchResultError("Could not find integrations.")
// Allow patch to inject hooks into the patches integrations.
jsonHookPatchFingerprintResult = JsonHookPatchFingerprint.also {
it.resolve(context, jsonHookPatch.immutableClass)
}.result ?: return PatchResultError("Unexpected integrations.")
if (!it.resolve(context, jsonHookPatch.immutableClass))
throw PatchResultError("Unexpected integrations.")
}.let { hooks = JsonHookPatchHook(it) }
// Conveniently find the type to hook a method in, via a named field.
val jsonFactory = LoganSquareFingerprint.result
@@ -64,30 +69,10 @@ class JsonHookPatch : BytecodePatch(
*
* @param context The [BytecodeContext] of the current patch.
* @param descriptor The class descriptor of the hook.
* @throws ClassNotFoundException If the class could not be found.
*/
internal class Hook(context: BytecodeContext, private val descriptor: String) {
private var added = false
/**
* Add the hook.
*/
internal fun add() {
if (added) return
jsonHookPatchFingerprintResult.apply {
mutableMethod.apply {
addInstructions(
scanResult.patternScanResult!!.startIndex,
"""
sget-object v1, $descriptor->INSTANCE:$descriptor
invoke-virtual {v0, v1}, Lkotlin/collections/builders/ListBuilder;->add(Ljava/lang/Object;)Z
"""
)
}
}
added = true
}
internal class Hook(context: BytecodeContext, internal val descriptor: String) {
internal var added = false
init {
context.findClass { it.type == descriptor }?.let {
@@ -102,15 +87,67 @@ class JsonHookPatch : BytecodePatch(
}
}
private companion object {
const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
/**
* A hook for the [JsonHookPatch].
*
* @param jsonHookPatchFingerprint The [JsonHookPatchFingerprint] to hook.
*/
internal class JsonHookPatchHook(jsonHookPatchFingerprint: MethodFingerprint): Closeable {
private val jsonHookPatchFingerprintResult = jsonHookPatchFingerprint.result!!
private val jsonHookPatchIndex = jsonHookPatchFingerprintResult.scanResult.patternScanResult!!.endIndex
const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
/**
* Add a hook to the [JsonHookPatch].
* Will not add the hook if it's already added.
*
* @param hook The [Hook] to add.
*/
fun addHook(hook: Hook) {
if (hook.added) return
const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
jsonHookPatchFingerprintResult.mutableMethod.apply {
// Insert hooks right before calling buildList.
val insertIndex = jsonHookPatchIndex
const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
addInstructions(
insertIndex,
"""
sget-object v1, ${hook.descriptor}->INSTANCE:${hook.descriptor}
invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
"""
)
}
private lateinit var jsonHookPatchFingerprintResult: MethodFingerprintResult
hook.added = true
}
override fun close() {
// Remove hooks.add(dummyHook).
jsonHookPatchFingerprintResult.mutableMethod.apply {
val addDummyHookIndex = jsonHookPatchIndex - 2
removeInstructions(addDummyHookIndex, 2)
}
}
}
override fun close() = hooks.close()
internal companion object {
private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
/**
* The [JsonHookPatchHook] of the [JsonHookPatch].
*
* @see JsonHookPatchHook
*/
internal lateinit var hooks: JsonHookPatchHook
}
}

View File

@@ -4,13 +4,13 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
@DependsOn([JsonHookPatch::class])
abstract class BaseHookPatchPatch(private val hookClassDescriptor: String) : BytecodePatch() {
override fun execute(context: BytecodeContext) = try {
PatchResultSuccess().also { JsonHookPatch.Hook(context, hookClassDescriptor).add() }
JsonHookPatch.hooks.addHook(JsonHookPatch.Hook(context, hookClassDescriptor))
PatchResultSuccess()
} catch (ex: Exception) {
PatchResultError(ex)
}

View File

@@ -15,8 +15,4 @@ import app.revanced.patches.twitter.misc.hook.patch.ads.annotations.HideAdsCompa
@Description("Hides ads.")
@HideAdsCompatibility
@Version("0.0.1")
class HideAdsPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) {
private companion object {
const val HOOK_CLASS_DESCRIPTOR = "Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;"
}
}
class HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")

View File

@@ -15,9 +15,6 @@ import app.revanced.patches.twitter.misc.hook.patch.recommendation.annotations.H
@Description("Hides recommended users.")
@HideRecommendedUsersCompatibility
@Version("0.0.1")
class HideRecommendedUsersPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) {
private companion object {
const val HOOK_CLASS_DESCRIPTOR =
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
}
}
class HideRecommendedUsersPatch : BaseHookPatchPatch(
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
)

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.vsco.misc.pro.fingerprints
import org.jf.dexlib2.AccessFlags
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object RevCatSubscriptionFingerprint : MethodFingerprint(
returnType = "V",
strings = listOf("use_debug_subscription_settings"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/RevCatSubscriptionSettingsRepository;")
}
)

View File

@@ -0,0 +1,35 @@
package app.revanced.patches.vsco.misc.pro.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.vsco.misc.pro.fingerprints.RevCatSubscriptionFingerprint
@Patch
@Name("unlock-pro")
@Description("Unlocks pro features.")
@Compatibility([Package("com.vsco.cam")])
@Version("0.0.1")
class UnlockProPatch : BytecodePatch(
listOf(RevCatSubscriptionFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
RevCatSubscriptionFingerprint.result?.mutableMethod?.apply {
// Set isSubscribed to true.
addInstructions(
0,
"""
const p1, 0x1
"""
)
} ?: return RevCatSubscriptionFingerprint.toErrorResult()
return PatchResultSuccess()
}
}

View File

@@ -1,25 +0,0 @@
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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class GeneralAdsCompatibility

View File

@@ -0,0 +1,9 @@
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"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideAdsCompatibility

View File

@@ -1,17 +0,0 @@
package app.revanced.patches.youtube.ad.general.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object ReelConstructorFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_VIRTUAL
),
customFingerprint = { method, _ ->
method.implementation?.instructions?.any {
it.opcode == Opcode.CONST && (it as WideLiteralInstruction).wideLiteral == GeneralAdsResourcePatch.reelMultipleItemShelfId
} ?: false
}
)

View File

@@ -1,47 +1,32 @@
package app.revanced.patches.youtube.ad.general.bytecode.patch
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.toErrorResult
import app.revanced.extensions.injectHideViewCall
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
import app.revanced.patches.youtube.ad.general.bytecode.fingerprints.ReelConstructorFingerprint
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
@DependsOn([GeneralAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
@Name("general-ads")
@DependsOn([HideAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
@Name("hide-ads")
@Description("Removes general ads.")
@GeneralAdsCompatibility
@HideAdsCompatibility
@Version("0.0.1")
class GeneralAdsPatch : BytecodePatch(
listOf(ReelConstructorFingerprint)
) {
class HideAdsPatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult {
fun String.buildHideCall(viewRegister: Int) = "invoke-static { v$viewRegister }, " +
"Lapp/revanced/integrations/patches/GeneralAdsPatch;" +
"->" +
"$this(Landroid/view/View;)V"
fun MutableMethod.injectHideCall(insertIndex: Int, viewRegister: Int, method: String) =
this.addInstruction(insertIndex, method.buildHideCall(viewRegister))
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
@@ -49,7 +34,7 @@ class GeneralAdsPatch : BytecodePatch(
if (instruction.opcode != org.jf.dexlib2.Opcode.CONST)
return@forEachIndexed
// Instruction to store the id adAttribution into a register
if ((instruction as Instruction31i).wideLiteral != GeneralAdsResourcePatch.adAttributionId)
if ((instruction as Instruction31i).wideLiteral != HideAdsResourcePatch.adAttributionId)
return@forEachIndexed
val insertIndex = index + 1
@@ -64,25 +49,18 @@ class GeneralAdsPatch : BytecodePatch(
context.proxy(classDef)
.mutableClass
.findMutableMethodOf(method)
.injectHideCall(insertIndex, viewRegister, "hideAdAttributionView")
.injectHideViewCall(
insertIndex,
viewRegister,
"Lapp/revanced/integrations/patches/components/AdsFilter;",
"hideAdAttributionView"
)
}
}
}
}
}
ReelConstructorFingerprint.result?.let {
// iput-object v$viewRegister, ...
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
it.mutableMethod.apply {
val viewRegister = instruction<TwoRegisterInstruction>(insertIndex).registerA
injectHideCall(insertIndex, viewRegister, "hideReelView")
}
} ?: return ReelConstructorFingerprint.toErrorResult()
return PatchResultSuccess()
}
}

View File

@@ -8,7 +8,7 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.*
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
@@ -20,13 +20,9 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.P
ResourceMappingPatch::class
]
)
@GeneralAdsCompatibility
@HideAdsCompatibility
@Version("0.0.1")
class GeneralAdsResourcePatch : ResourcePatch {
internal companion object {
var adAttributionId: Long = -1
var reelMultipleItemShelfId: Long = -1
}
class HideAdsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
PreferenceScreen.LAYOUT.addPreferences(
@@ -105,12 +101,6 @@ class GeneralAdsResourcePatch : ResourcePatch {
StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
),
SwitchPreference(
"revanced_hide_shorts",
StringResource("revanced_hide_shorts_title", "Hide shorts"),
StringResource("revanced_hide_shorts_summary_on", "Shorts are hidden"),
StringResource("revanced_hide_shorts_summary_off", "Shorts are shown")
),
SwitchPreference(
"revanced_hide_community_guidelines",
StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
@@ -263,11 +253,12 @@ class GeneralAdsResourcePatch : ResourcePatch {
)
)
fun String.getId() = ResourceMappingPatch.resourceMappings.single { it.name == this }.id
adAttributionId = "ad_attribution".getId()
reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
return PatchResultSuccess()
}
internal companion object {
var adAttributionId: Long = -1
}
}

View File

@@ -3,23 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class VideoAdsCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class CopyVideoUrlCompatibility

View File

@@ -26,8 +26,7 @@ import app.revanced.patches.youtube.video.information.patch.VideoInformationPatc
@Version("0.0.1")
class CopyVideoUrlBytecodePatch : BytecodePatch() {
private companion object {
const val INTEGRATIONS_PACKAGE = "Lapp/revanced/integrations"
const val INTEGRATIONS_PLAYER_PACKAGE = "$INTEGRATIONS_PACKAGE/videoplayer"
const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
val BUTTONS_DESCRIPTORS = listOf(
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
@@ -38,10 +37,8 @@ class CopyVideoUrlBytecodePatch : BytecodePatch() {
// Initialize buttons and inject visibility control
BUTTONS_DESCRIPTORS.forEach { descriptor ->
val initializeButtonDescriptor = "$descriptor->initializeButton(Ljava/lang/Object;)V"
val visibilityDescriptor = "$descriptor->changeVisibility(Z)V"
PlayerControlsBytecodePatch.initializeControl(initializeButtonDescriptor)
PlayerControlsBytecodePatch.injectVisibilityCheckCall(visibilityDescriptor)
PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
}
return PatchResultSuccess()

View File

@@ -14,6 +14,7 @@ import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomCon
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("copy-video-url-resource")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
@@ -28,13 +29,13 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_copy_video_url",
StringResource("revanced_copy_video_url_title", "Show copy video URL button"),
StringResource("revanced_copy_video_url_summary_on", "Button is shown, click to copy video URL without timestamp"),
StringResource("revanced_copy_video_url_summary_on", "Button is shown. Tap to copy video URL. Tap and hold to copy video URL with timestamp"),
StringResource("revanced_copy_video_url_summary_off", "Button is not shown")
),
SwitchPreference(
"revanced_copy_video_url_timestamp",
StringResource("revanced_copy_video_url_timestamp_title", "Show copy timestamp URL button"),
StringResource("revanced_copy_video_url_timestamp_summary_on", "Button is shown, click to copy video URL with timestamp"),
StringResource("revanced_copy_video_url_timestamp_summary_on", "Button is shown. Tap to copy video URL with timestamp. Tap and hold to copy video without timestamp"),
StringResource("revanced_copy_video_url_timestamp_summary_off", "Button is not shown")
)
),
@@ -48,6 +49,9 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
"revanced_yt_copy_timestamp.xml"
))
// merge strings
context.mergeStrings("copyvideourl/host/values/strings.xml")
BottomControlsResourcePatch.addControls("copyvideourl/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
return PatchResultSuccess()

View File

@@ -3,23 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class DownloadsCompatibility

View File

@@ -21,23 +21,24 @@ import app.revanced.patches.youtube.video.information.patch.VideoInformationPatc
@DownloadsCompatibility
@Version("0.0.1")
class DownloadsBytecodePatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult {
val integrationsPackage = "app/revanced/integrations"
val classDescriptor = "L$integrationsPackage/videoplayer/DownloadButton;"
private companion object {
const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/DownloadButton;"
}
override fun execute(context: BytecodeContext): PatchResult {
/*
initialize the control
*/
val initializeDownloadsDescriptor = "$classDescriptor->initializeButton(Ljava/lang/Object;)V"
PlayerControlsBytecodePatch.initializeControl(initializeDownloadsDescriptor)
PlayerControlsBytecodePatch.initializeControl(
"$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
/*
add code to change the visibility of the control
*/
val changeVisibilityDescriptor = "$classDescriptor->changeVisibility(Z)V"
PlayerControlsBytecodePatch.injectVisibilityCheckCall(changeVisibilityDescriptor)
PlayerControlsBytecodePatch.injectVisibilityCheckCall(
"$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
return PatchResultSuccess()
}

View File

@@ -3,23 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SeekbarTappingCompatibility

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.interaction.seekbar.patch.EnableSeekbarTappingResourcePatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object AccessibilityPlayerProgressTimeFingerprint : MethodFingerprint(
returnType = "L",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
if (instruction.opcode != Opcode.CONST) return@any false
val wideLiteral = (instruction as WideLiteralInstruction).wideLiteral
EnableSeekbarTappingResourcePatch.accessibilityPlayerProgressTime == wideLiteral
} ?: false
}
)

View File

@@ -1,34 +1,34 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
object SeekbarTappingFingerprint : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_WIDE,
Opcode.IGET,
Opcode.IGET_OBJECT,
Opcode.IGET,
Opcode.DIV_INT_2ADDR,
Opcode.ADD_INT,
Opcode.SUB_INT_2ADDR,
Opcode.INT_TO_FLOAT,
Opcode.CMPG_FLOAT,
Opcode.IF_GTZ,
Opcode.INT_TO_FLOAT,
Opcode.CMPG_FLOAT,
Opcode.IF_GTZ,
Opcode.CONST_4,
Opcode.INVOKE_INTERFACE,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.IPUT_OBJECT,
Opcode.INVOKE_VIRTUAL
)
Opcode.INVOKE_VIRTUAL,
// Insert seekbar tapping instructions here.
Opcode.RETURN,
Opcode.INVOKE_VIRTUAL,
),
customFingerprint = custom@{ methodDef, _ ->
if (methodDef.name != "onTouchEvent") return@custom false
methodDef.implementation!!.instructions.any { instruction ->
if (instruction.opcode != Opcode.CONST) return@any false
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
// onTouchEvent method contains a CONST instruction
// with this literal making it unique with the rest of the properties of this fingerprint.
literal == Integer.MAX_VALUE
}
}
)

View File

@@ -1,44 +0,0 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
object SeekbarTappingParentFingerprint : MethodFingerprint(
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.NEW_ARRAY,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_WIDE,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.APUT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_WIDE,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.APUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT
)
)

View File

@@ -1,109 +1,95 @@
package app.revanced.patches.youtube.interaction.seekbar.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
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.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.AccessibilityPlayerProgressTimeFingerprint
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.formats.Instruction11n
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
@DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
@Name("seekbar-tapping")
@Description("Enables tap-to-seek on the seekbar of the video player.")
@SeekbarTappingCompatibility
@Version("0.0.1")
class EnableSeekbarTappingPatch : BytecodePatch(
listOf(
SeekbarTappingParentFingerprint, SeekbarTappingFingerprint
)
listOf(AccessibilityPlayerProgressTimeFingerprint, SeekbarTappingFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
SwitchPreference(
"revanced_tap_seeking",
StringResource("revanced_tap_seeking_title", "Enable seekbar tapping"),
StringResource("revanced_tap_seeking_summary_on", "Seekbar tapping is enabled"),
StringResource("revanced_tap_seeking_summary_off", "Seekbar tapping is disabled")
)
)
// Find the required methods to tap the seekbar.
val seekbarTappingMethods =
AccessibilityPlayerProgressTimeFingerprint.result?.classDef?.methods?.let { methods ->
buildMap {
// find the methods which tap the seekbar
methods.forEach { method ->
if (method.implementation == null) return@forEach
var result = SeekbarTappingParentFingerprint.result!!
val instructions = method.implementation!!.instructions
val tapSeekMethods = mutableMapOf<String, Method>()
// The method has more than 7 instructions.
if (instructions.count() < 7) return@forEach
// find the methods which tap the seekbar
for (it in result.classDef.methods) {
if (it.implementation == null) continue
// The 7th instruction has the opcode CONST_4.
val instruction = instructions.elementAt(6)
if (instruction.opcode != Opcode.CONST_4) return@forEach
val instructions = it.implementation!!.instructions
// here we make sure we actually find the method because it has more than 7 instructions
if (instructions.count() < 7) continue
// the literal for this instruction has to be either 1 or 2.
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
// we know that the 7th instruction has the opcode CONST_4
val instruction = instructions.elementAt(6)
if (instruction.opcode != Opcode.CONST_4) continue
// Based on the literal, determine which method is which.
if (literal == 1) this["P"] = method
if (literal == 2) this["O"] = method
}
}
}
// the literal for this instruction has to be either 1 or 2
val literal = (instruction as Instruction11n).narrowLiteral
seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
// method founds
if (literal == 1) tapSeekMethods["P"] = it
if (literal == 2) tapSeekMethods["O"] = it
}
SeekbarTappingFingerprint.result?.let {
val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
// replace map because we don't need the upper one anymore
result = SeekbarTappingFingerprint.result!!
it.mutableMethod.apply {
val thisInstanceRegister = instruction<Instruction35c>(insertIndex - 1).registerC
val implementation = result.mutableMethod.implementation!!
val freeRegister = 0
val xAxisRegister = 2
// if tap-seeking is enabled, do not invoke the two methods below
val pMethod = tapSeekMethods["P"]!!
val oMethod = tapSeekMethods["O"]!!
val pMethod = seekbarTappingMethods["P"]!!
val oMethod = seekbarTappingMethods["O"]!!
val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
fun Method.toInvokeInstructionString() =
"invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $definingClass->$name(I)V"
// get the required register
val instruction = implementation.instructions[insertIndex - 1]
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register")
val register = (instruction as Instruction35c).registerC
addInstructions(
insertIndex,
"""
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
move-result v$freeRegister
if-eqz v$freeRegister, :disabled
${oMethod.toInvokeInstructionString()}
${pMethod.toInvokeInstructionString()}
""",
listOf(ExternalLabel("disabled", instruction(insertIndex)))
)
}
} ?: return SeekbarTappingFingerprint.toErrorResult()
val elseLabel = implementation.newLabelForIndex(insertIndex)
// the instructions are written in reverse order.
result.mutableMethod.addInstructions(
insertIndex, """
invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
"""
)
// if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
implementation.addInstruction(
insertIndex, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
)
result.mutableMethod.addInstructions(
insertIndex, """
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->isTapSeekingEnabled()Z
move-result v0
"""
)
return PatchResultSuccess()
}
}
}

View File

@@ -0,0 +1,38 @@
package app.revanced.patches.youtube.interaction.seekbar.patch
import app.revanced.patcher.annotation.Version
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])
@Version("0.0.1")
class EnableSeekbarTappingResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
SwitchPreference(
"revanced_seekbar_tapping",
StringResource("revanced_seekbar_tapping_title", "Enable seekbar tapping"),
StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
)
)
accessibilityPlayerProgressTime = ResourceMappingPatch.resourceMappings.find {
it.name == "accessibility_player_progress_time"
}?.id ?: return PatchResultError("Failed to find required resource")
return PatchResultSuccess()
}
internal companion object {
var accessibilityPlayerProgressTime = -1L
}
}

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SwipeControlsCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoCaptionsCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideButtonsCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoplayButtonCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideCaptionsButtonCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class NavigationButtonsCompatibility

View File

@@ -2,22 +2,6 @@ package app.revanced.patches.youtube.layout.buttons.player.background.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerButtonBackgroundCompatibility

View File

@@ -3,10 +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()
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HidePlayerButtonsCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AlbumCardsCompatibility

View File

@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.artistcards.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideArtistCardCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class BreakingNewsCompatibility

View File

@@ -1,24 +0,0 @@
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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class CommentsCompatibility

View File

@@ -0,0 +1,8 @@
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"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideCommentsCompatibility

View File

@@ -1,17 +0,0 @@
package app.revanced.patches.youtube.layout.hide.comments.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.hide.comments.resource.patch.CommentsResourcePatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object ShortsCommentsButtonFingerprint : MethodFingerprint(
"V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("Z", "Z", "L"),
customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal && (it as WideLiteralInstruction).wideLiteral == CommentsResourcePatch.shortsCommentsButtonId
} == true
}
)

View File

@@ -1,69 +0,0 @@
package app.revanced.patches.youtube.layout.hide.comments.bytecode.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
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.patch.annotations.Patch
import app.revanced.patches.youtube.layout.hide.comments.annotations.CommentsCompatibility
import app.revanced.patches.youtube.layout.hide.comments.bytecode.fingerprints.ShortsCommentsButtonFingerprint
import app.revanced.patches.youtube.layout.hide.comments.resource.patch.CommentsResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@DependsOn([IntegrationsPatch::class, CommentsResourcePatch::class])
@Name("comments")
@Description("Hides components related to comments.")
@CommentsCompatibility
@Version("0.0.1")
class CommentsPatch : BytecodePatch(
listOf(
ShortsCommentsButtonFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
val checkCastAnchorFingerprint = object : MethodFingerprint(
opcodes = listOf(
Opcode.CONST,
Opcode.CONST_HIGH16,
Opcode.IF_EQZ,
Opcode.CONST,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
)
) {}
ShortsCommentsButtonFingerprint.result?.let {
it.mutableMethod.apply {
val checkCastAnchorIndex = checkCastAnchorFingerprint.also { result ->
if (!result.resolve(context, this, it.classDef))
throw checkCastAnchorFingerprint.toErrorResult()
}.result!!.scanResult.patternScanResult!!.endIndex
val shortsCommentsButtonRegister = instruction<OneRegisterInstruction>(checkCastAnchorIndex).registerA
val insertIndex = checkCastAnchorIndex + 1
addInstructions(
insertIndex,
"""
invoke-static { v$shortsCommentsButtonRegister }, Lapp/revanced/integrations/patches/HideShortsCommentsButtonPatch;->hideShortsCommentsButton(Landroid/view/View;)V
"""
)
}
} ?: return ShortsCommentsButtonFingerprint.toErrorResult()
return PatchResultSuccess()
}
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.comments.resource.patch
package app.revanced.patches.youtube.layout.hide.comments.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
@@ -7,22 +8,21 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.comments.annotations.CommentsCompatibility
import app.revanced.patches.youtube.layout.hide.comments.annotations.HideCommentsCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("comments-resource-patch")
@CommentsCompatibility
@Patch
@Name("comments")
@Description("Hides components related to comments.")
@HideCommentsCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class CommentsResourcePatch : ResourcePatch {
companion object {
internal var shortsCommentsButtonId: Long = -1
}
class CommentsPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
@@ -40,22 +40,12 @@ class CommentsResourcePatch : ResourcePatch {
StringResource("revanced_hide_preview_comment_title", "Hide preview comment"),
StringResource("revanced_hide_preview_comment_on", "Preview comment is hidden"),
StringResource("revanced_hide_preview_comment_off", "Preview comment is shown")
),
SwitchPreference(
"revanced_hide_shorts_comments_button",
StringResource("revanced_hide_shorts_comments_button_title", "Hide shorts comments button"),
StringResource("revanced_hide_shorts_comments_button_on", "Shorts comments button is hidden"),
StringResource("revanced_hide_shorts_comments_button_off", "Shorts comments button is shown")
),
)
),
StringResource("revanced_comments_preference_screen_summary", "Manage the visibility of comments section components")
)
)
shortsCommentsButtonId = ResourceMappingPatch.resourceMappings.single {
it.type == "drawable" && it.name == "ic_right_comment_32c"
}.id
return PatchResultSuccess()
}
}

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class CrowdfundingBoxCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideEndscreenCardsCompatibility

View File

@@ -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"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideFilterBar

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideFloatingMicrophoneButtonCompatibility

View File

@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.getpremium.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideGetPremiumCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideInfocardsCompatibility

View File

@@ -3,23 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideLoadMoreButtonCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideEmailAddressCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideSeekbarCompatibility

View File

@@ -0,0 +1,8 @@
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"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideShortsComponentsCompatibility

View File

@@ -0,0 +1,18 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object BottomNavigationBarFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.MOVE_RESULT_OBJECT, // Refers to bottom navigation bar
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
),
strings = listOf(
"navigation_endpoint_interaction_logging_extension",
"reel_watch_fragment_watch_while",
),
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object CreateShortsButtonsFingerprint : MethodFingerprint(
parameters = listOf("Z", "Z", "L"),
customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any {
if (it.opcode != Opcode.CONST) return@any false
val literal = (it as WideLiteralInstruction).wideLiteral
literal == HideShortsComponentsResourcePatch.reelPlayerRightLargeIconSize
} ?: false
}
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object ReelConstructorFingerprint : MethodFingerprint(
opcodes = listOf(Opcode.INVOKE_VIRTUAL),
customFingerprint = { method, _ ->
method.implementation?.instructions?.any {
if (it.opcode != Opcode.CONST) return@any false
val literal = (it as WideLiteralInstruction).wideLiteral
literal == HideShortsComponentsResourcePatch.reelMultipleItemShelfId
} ?: false
}
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object RenderBottomNavigationBarFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.MONITOR_ENTER,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MONITOR_EXIT,
Opcode.RETURN_VOID,
Opcode.MOVE_EXCEPTION,
Opcode.MONITOR_EXIT,
Opcode.THROW,
)
)

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object RenderBottomNavigationBarParentFingerprint : MethodFingerprint(
parameters = listOf("I", "I", "L", "L", "J", "L"),
strings = listOf("aa")
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object SetPivotBarVisibilityFingerprint : MethodFingerprint(
parameters = listOf("Z"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.RETURN_VOID,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
)
)

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SetPivotBarVisibilityParentFingerprint : MethodFingerprint(
parameters = listOf("Z"),
strings = listOf("FEnotifications_inbox")
)

View File

@@ -0,0 +1,146 @@
package app.revanced.patches.youtube.layout.hide.shorts.bytecode.patch
import app.revanced.extensions.findIndexForIdResource
import app.revanced.extensions.injectHideViewCall
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction
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.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.youtube.layout.hide.shorts.annotations.HideShortsComponentsCompatibility
import app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints.*
import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch
@DependsOn(
[
IntegrationsPatch::class,
LithoFilterPatch::class,
HideShortsComponentsResourcePatch::class,
ResourceMappingPatch::class
]
)
@Name("hide-shorts-components")
@Description("Hides components from YouTube Shorts.")
@HideShortsComponentsCompatibility
@Version("0.0.1")
class HideShortsComponentsPatch : BytecodePatch(
listOf(
CreateShortsButtonsFingerprint,
ReelConstructorFingerprint,
BottomNavigationBarFingerprint,
RenderBottomNavigationBarParentFingerprint,
SetPivotBarVisibilityParentFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
// region Hide the Shorts shelf.
ReelConstructorFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
val viewRegister = instruction<TwoRegisterInstruction>(insertIndex).registerA
injectHideViewCall(
insertIndex,
viewRegister,
CLASS_DESCRIPTOR,
"hideShortsShelf"
)
}
} ?: return ReelConstructorFingerprint.toErrorResult()
// endregion
// region Hide the Shorts buttons.
// Some Shorts buttons are views, hide them by setting their visibility to GONE.
CreateShortsButtonsFingerprint.result?.let {
ShortsButtons.values().forEach { button -> button.injectHideCall(it.mutableMethod) }
} ?: return CreateShortsButtonsFingerprint.toErrorResult()
// endregion
// region Hide the navigation bar.
// Hook to get the pivotBar view.
SetPivotBarVisibilityParentFingerprint.result?.let {
if (!SetPivotBarVisibilityFingerprint.resolve(context, it.classDef))
throw SetPivotBarVisibilityFingerprint.toErrorResult()
SetPivotBarVisibilityFingerprint.result!!.let { result ->
result.mutableMethod.apply {
val checkCastIndex = result.scanResult.patternScanResult!!.endIndex
val viewRegister = instruction<OneRegisterInstruction>(checkCastIndex).registerA
addInstruction(
checkCastIndex + 1,
"sput-object v$viewRegister, $CLASS_DESCRIPTOR->pivotBar:" +
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
)
}
}
} ?: return SetPivotBarVisibilityParentFingerprint.toErrorResult()
// Hook to hide the navigation bar when Shorts are being played.
RenderBottomNavigationBarParentFingerprint.result?.let {
if (!RenderBottomNavigationBarFingerprint.resolve(context, it.classDef))
throw RenderBottomNavigationBarFingerprint.toErrorResult()
RenderBottomNavigationBarFingerprint.result!!.mutableMethod.apply {
addInstruction(0, "invoke-static { }, $CLASS_DESCRIPTOR->hideNavigationBar()V")
}
} ?: return RenderBottomNavigationBarParentFingerprint.toErrorResult()
// Required to prevent a black bar from appearing at the bottom of the screen.
BottomNavigationBarFingerprint.result?.let {
it.mutableMethod.apply {
val moveResultIndex = it.scanResult.patternScanResult!!.startIndex
val viewRegister = instruction<OneRegisterInstruction>(moveResultIndex).registerA
val insertIndex = moveResultIndex + 1
addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, $CLASS_DESCRIPTOR->" +
"hideNavigationBar(Landroid/view/View;)Landroid/view/View;"
)
}
} ?: return BottomNavigationBarFingerprint.toErrorResult()
// endregion
return PatchResultSuccess()
}
private companion object {
private const val CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
private enum class ShortsButtons(private val resourceName: String, private val methodName: String) {
COMMENTS("reel_dyn_comment", "hideShortsCommentsButton"),
REMIX("reel_dyn_remix", "hideShortsRemixButton"),
SHARE("reel_dyn_share", "hideShortsShareButton");
fun injectHideCall(method: MutableMethod) {
val referencedIndex = method.findIndexForIdResource(resourceName)
val setIdIndex = referencedIndex + 1
val viewRegister = method.instruction<FiveRegisterInstruction>(setIdIndex).registerC
method.injectHideViewCall(setIdIndex, viewRegister, CLASS_DESCRIPTOR, methodName)
}
}
}
}

View File

@@ -0,0 +1,89 @@
package app.revanced.patches.youtube.layout.hide.shorts.resource.patch
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class HideShortsComponentsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
"revanced_shorts",
StringResource("revanced_shorts_title", "Shorts components"),
listOf(
SwitchPreference(
"revanced_hide_shorts",
StringResource("revanced_hide_shorts_enabled_title", "Hide shorts"),
StringResource("revanced_hide_shorts_on", "Shorts are hidden"),
StringResource("revanced_hide_shorts_off", "Shorts are shown")
),
SwitchPreference(
"revanced_hide_shorts_join_button",
StringResource("revanced_hide_shorts_join_button_title", "Hide join button"),
StringResource("revanced_hide_shorts_join_button_on", "Join button is hidden"),
StringResource("revanced_hide_shorts_join_button_off", "Join button is shown")
),
SwitchPreference(
"revanced_hide_shorts_subscribe_button",
StringResource("revanced_hide_shorts_subscribe_button_title", "Hide subscribe button"),
StringResource("revanced_hide_shorts_subscribe_button_on", "Subscribe button is hidden"),
StringResource("revanced_hide_shorts_subscribe_button_off", "Subscribe button is shown")
),
SwitchPreference(
"revanced_hide_shorts_thanks_button",
StringResource("revanced_hide_shorts_thanks_button_title", "Hide thanks button"),
StringResource("revanced_hide_shorts_thanks_button_on", "Thanks button is hidden"),
StringResource("revanced_hide_shorts_thanks_button_off", "Thanks button is shown")
),
SwitchPreference(
"revanced_hide_shorts_comments_button",
StringResource("revanced_hide_shorts_comments_button_title", "Hide comments button"),
StringResource("revanced_hide_shorts_comments_button_on", "Comments button is hidden"),
StringResource("revanced_hide_shorts_comments_button_off", "Comments button is shown")
),
SwitchPreference(
"revanced_hide_shorts_remix_button",
StringResource("revanced_hide_shorts_remix_button_title", "Hide remix button"),
StringResource("revanced_hide_shorts_remix_button_on", "Remix button is hidden"),
StringResource("revanced_hide_shorts_remix_button_off", "Remix button is shown")
),
SwitchPreference(
"revanced_hide_shorts_share_button",
StringResource("revanced_hide_shorts_share_button_title", "Hide share button"),
StringResource("revanced_hide_shorts_share_button_on", "Share button is hidden"),
StringResource("revanced_hide_shorts_share_button_off", "Share button is shown")
),
SwitchPreference(
"revanced_hide_shorts_navigation_bar",
StringResource("revanced_hide_shorts_navigation_bar_title", "Hide navigation bar"),
StringResource("revanced_hide_shorts_navigation_bar_on", "Navigation bar is hidden"),
StringResource("revanced_hide_shorts_navigation_bar_off", "Navigation bar is shown")
),
),
StringResource("revanced_shorts_summary", "Manage the visibility of Shorts components")
)
)
fun String.getId() = ResourceMappingPatch.resourceMappings.single { it.name == this }.id
reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
reelPlayerRightLargeIconSize = "reel_player_right_large_icon_size".getId()
return PatchResultSuccess()
}
companion object {
var reelMultipleItemShelfId: Long = -1
var reelPlayerRightLargeIconSize = -1L
}
}

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideTimeCompatibility

View File

@@ -0,0 +1,8 @@
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"))])
@Target(AnnotationTarget.CLASS)
internal annotation class WatchInVRCompatibility

View File

@@ -1,24 +0,0 @@
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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class WatchinVRCompatibility

View File

@@ -12,7 +12,7 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.watchinvr.annotations.WatchinVRCompatibility
import app.revanced.patches.youtube.layout.hide.watchinvr.annotations.WatchInVRCompatibility
import app.revanced.patches.youtube.layout.hide.watchinvr.fingerprints.WatchInVRFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@@ -21,7 +21,7 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
@Name("hide-watch-in-vr")
@Description("Hides the option to watch in VR from the player settings flyout panel.")
@WatchinVRCompatibility
@WatchInVRCompatibility
@Version("0.0.1")
class WatchInVRPatch : BytecodePatch(
listOf(

View File

@@ -0,0 +1,8 @@
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"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideWatermarkCompatibility

View File

@@ -1,24 +0,0 @@
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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class HideWatermarkCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class FullscreenPanelsCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerPopupPanelsCompatibility

View File

@@ -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.15.40", "18.16.37"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class ReturnYouTubeDislikeCompatibility

View File

@@ -13,8 +13,7 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
access = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.MOVE_OBJECT, // available unused register
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16, // available unused register
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,

View File

@@ -99,7 +99,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
.scanResult.patternScanResult!!.startIndex
val insertIndex = atomicReferenceStartIndex + 8
val insertIndex = atomicReferenceStartIndex + 7
textComponentContextFingerprintResult.mutableMethod.apply {
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
@@ -111,7 +111,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
instruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB
val atomicReferenceRegister =
instruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 5).registerC
instruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 4).registerC
val moveCharSequenceInstruction = instruction<TwoRegisterInstruction>(insertIndex)
val charSequenceRegister = moveCharSequenceInstruction.registerB

View File

@@ -26,16 +26,11 @@ class ReturnYouTubeDislikeResourcePatch : ResourcePatch {
}
override fun execute(context: ResourceContext): PatchResult {
val youtubePackage = "com.google.android.youtube"
SettingsPatch.addPreference(
Preference(
StringResource("revanced_ryd_settings_title", "Return YouTube Dislike"),
StringResource("revanced_ryd_settings_summary", "Settings for Return YouTube Dislike"),
Preference.Intent(
youtubePackage,
"ryd_settings",
"com.google.android.libraries.social.licenses.LicenseActivity"
)
SettingsPatch.createReVancedSettingsIntent("ryd_settings")
)
)
// merge strings

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class WideSearchbarCompatibility

View File

@@ -3,8 +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.15.40", "18.16.37"))]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SponsorBlockCompatibility

View File

@@ -103,17 +103,18 @@ class SponsorBlockBytecodePatch : BytecodePatch(
val seekbarMethodInstructions = seekbarMethod.implementation!!.instructions
/*
* Get the instance of the seekbar rectangle
* Get left and right of seekbar rectangle
*/
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
if (instruction.opcode != Opcode.MOVE_OBJECT_FROM16) continue
seekbarMethod.addInstruction(
index + 1,
"invoke-static/range {p0 .. p0}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
)
break
val moveRectangleToRegisterIndex = seekbarMethodInstructions.indexOfFirst {
it.opcode == Opcode.MOVE_OBJECT_FROM16
}
seekbarMethod.addInstruction(
moveRectangleToRegisterIndex + 1,
"invoke-static/range {p0 .. p0}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
)
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_STATIC) continue
@@ -125,38 +126,15 @@ class SponsorBlockBytecodePatch : BytecodePatch(
// set the thickness of the segment
seekbarMethod.addInstruction(
insertIndex,
"invoke-static {v${invokeInstruction.registerC}}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
"invoke-static {v${invokeInstruction.registerC}}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
)
break
}
/*
* Set rectangle absolute left and right positions
*/
val drawRectangleInstructions = seekbarMethodInstructions.withIndex().filter { (_, instruction) ->
instruction is ReferenceInstruction && (instruction.reference as? MethodReference)?.name == "drawRect"
}.map { (index, instruction) -> // TODO: improve code
index to (instruction as FiveRegisterInstruction).registerD
}
val (indexRight, rectangleRightRegister) = drawRectangleInstructions[0]
val (indexLeft, rectangleLeftRegister) = drawRectangleInstructions[3]
// order of operation is important here due to the code above which has to be improved
// the reason for that is that we get the index, add instructions and then the offset would be wrong
seekbarMethod.addInstruction(
indexLeft + 1,
"invoke-static {v$rectangleLeftRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V"
)
seekbarMethod.addInstruction(
indexRight + 1,
"invoke-static {v$rectangleRightRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V"
)
/*
* Draw segment
*/
// Find the drawCircle call and draw the segment before it
for (i in seekbarMethodInstructions.size - 1 downTo 0) {
val invokeInstruction = seekbarMethodInstructions[i] as? ReferenceInstruction ?: continue

View File

@@ -10,7 +10,6 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
@@ -18,22 +17,16 @@ import app.revanced.util.resources.ResourceUtils.copyXmlNode
import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("sponsorblock-resource-patch")
@SponsorBlockCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class SponsorBlockResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
val youtubePackage = "com.google.android.youtube"
SettingsPatch.addPreference(
Preference(
StringResource("sb_settings", "SponsorBlock"),
StringResource("revanced_sponsorblock_settings_title", "SponsorBlock"),
StringResource("revanced_sponsorblock_settings_summary", "SponsorBlock related settings"),
Preference.Intent(
youtubePackage,
"sponsorblock_settings",
"com.google.android.libraries.social.licenses.LicenseActivity"
)
SettingsPatch.createReVancedSettingsIntent("sponsorblock_settings")
)
)
val classLoader = this.javaClass.classLoader

View File

@@ -3,23 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SpoofAppVersionCompatibility

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class StartupShortsResetCompatibility

View File

@@ -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.15.40", "18.16.37"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class TabletMiniPlayerCompatibility

View File

@@ -8,8 +8,8 @@ import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
@Patch
@Name("theme")
@@ -45,5 +45,14 @@ class ThemeBytecodePatch : BytecodePatch() {
description = "The background color of the light theme. Can be a hex color or a resource reference.",
)
)
var splashScreenBackgroundColor: String? by option(
PatchOption.StringOption(
key = "splashScreenBackgroundColor",
default = "@android:color/black",
title = "Background color for the splash screen",
description = "The background color of the splash screen. Can be a hex color or a resource reference.",
)
)
}
}

View File

@@ -1,7 +1,9 @@
package app.revanced.patches.youtube.layout.theme.resource
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
@@ -9,9 +11,8 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import org.w3c.dom.Element
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@@ -29,35 +30,80 @@ class ThemeResourcePatch : ResourcePatch {
),
)
val darkThemeBackgroundColor = darkThemeBackgroundColor!!
val lightThemeBackgroundColor = lightThemeBackgroundColor!!
// Edit theme colors via resources.
context.xmlEditor["res/values/colors.xml"].use { editor ->
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
for (i in 0 until resourcesNode.childNodes.length) {
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
val children = resourcesNode.childNodes
for (i in 0 until children.length) {
val node = children.item(i) as? Element ?: continue
node.textContent = when (node.getAttribute("name")) {
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3",
"yt_black4", "yt_status_bar_background_dark", "material_grey_850" -> darkThemeBackgroundColor
?: continue
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
"yt_white2", "yt_white3", "yt_white4",
-> lightThemeBackgroundColor
-> lightThemeBackgroundColor ?: continue
else -> continue
}
}
}
// Copy the resource file to change the splash screen color.
context.copyResources(
"theme", ResourceUtils.ResourceGroup("values-night-v31", "styles.xml")
)
splashScreenBackgroundColor ?: return PatchResultSuccess()
// Edit splash screen background color for Android 11 and below.
context.xmlEditor["res/values/styles.xml"].use {
val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
val children = resourcesNode.childNodes
for (i in 0 until children.length) {
val node = children.item(i) as? Element ?: continue
if (node.tagName != "style") continue
val name = node.getAttribute("name")
if (name != LAUNCHER_STYLE_NAME) continue
it.file.createElement("item").apply {
setAttribute("name", "android:windowSplashScreenBackground")
textContent = splashScreenBackgroundColor
}.also(node::appendChild)
break
}
}
// Edit splash screen background color for Android 12+.
// Add the splash screen background color to the colors.xml file.
context.xmlEditor["res/values/colors.xml"].use {
val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
it.file.createElement("color").apply {
setAttribute("name", COLOR_NAME)
setAttribute("category", "color")
textContent = splashScreenBackgroundColor
}.also(resourcesNode::appendChild)
}
// Point to the splash screen background color.
context.xmlEditor["res/drawable/quantum_launchscreen_youtube.xml"].use {
val node = it.file.getElementsByTagName("layer-list").item(0) as Element
val backgroundColorItem = node.childNodes.item(1) as Element
backgroundColorItem.apply {
setAttribute("android:drawable", "@color/$COLOR_NAME")
}
}
return PatchResultSuccess()
}
}
private companion object {
private const val LAUNCHER_STYLE_NAME = "Base.Theme.YouTube.Launcher"
private const val COLOR_NAME = "splash_background_color"
}
}

View File

@@ -3,22 +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(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoRepeatCompatibility

Some files were not shown because too many files have changed in this diff Show More