Compare commits

..

33 Commits

Author SHA1 Message Date
semantic-release-bot
b1f629b81d chore(release): 2.174.0-dev.41 [skip ci]
# [2.174.0-dev.41](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.40...v2.174.0-dev.41) (2023-05-24)

### Bug Fixes

* **youtube/vanced-microg-support:** depend on `client-spoof` patch ([63cdba9](63cdba965b))
2023-05-24 00:04:33 +00:00
oSumAtrIX
63cdba965b fix(youtube/vanced-microg-support): depend on client-spoof patch
If `vanced-microg-support` is applied, YouTube makes use of Vanced MicroG. Since YouTube makes integrity checks for GMS, `client-spoof` patch is required.
2023-05-24 02:00:02 +02:00
oSumAtrIX
596b636a14 build(revanced-patcher): bump version 2023-05-24 01:58:17 +02:00
semantic-release-bot
9a6ed76956 chore(release): 2.174.0-dev.40 [skip ci]
# [2.174.0-dev.40](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.39...v2.174.0-dev.40) (2023-05-23)

### Bug Fixes

* **photomath/unlock-plus:** constrain to last working version ([#2232](https://github.com/revanced/revanced-patches/issues/2232)) ([1dd96b1](1dd96b19d9))
2023-05-23 17:45:41 +00:00
AnonymousWP
1a60e5c6b5 chore: remove scopes from issue templates (#2209) 2023-05-23 19:43:36 +02:00
LisoUseInAIKyrios
1dd96b19d9 fix(photomath/unlock-plus): constrain to last working version (#2232)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-05-23 19:42:49 +02:00
oSumAtrIX
46a93ba634 refactor: move setting to correct preference screen 2023-05-23 01:57:36 +02:00
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
190 changed files with 1574 additions and 1644 deletions

View File

@@ -1,6 +1,6 @@
name: 🐞 Bug report name: 🐞 Bug report
description: Report a very clearly broken issue. description: Report a very clearly broken issue.
title: 'bug: <title>' title: 'bug: '
labels: [bug] labels: [bug]
body: body:
- type: markdown - type: markdown

View File

@@ -1,6 +1,6 @@
name: ⭐ Patch Request name: ⭐ Patch Request
description: Create a detailed patch request. description: Create a detailed patch request.
title: 'feat(patch): ' title: 'feat: '
labels: [patch-request] labels: [patch-request]
body: body:
- type: textarea - type: textarea
@@ -24,7 +24,7 @@ body:
- type: textarea - type: textarea
attributes: attributes:
label: Motivation label: Motivation
description: Why should your patch request should be considered? What makes it valuable to the community? description: Why should your patch request be considered? What makes it valuable to the community?
validations: validations:
required: true required: true
- type: checkboxes - type: checkboxes
@@ -38,4 +38,4 @@ body:
- label: I have written a short but informative title. - label: I have written a short but informative title.
required: true required: true
- label: I filled out all of the requested information in this issue properly. - label: I filled out all of the requested information in this issue properly.
required: true required: true

View File

@@ -1,3 +1,78 @@
# [2.174.0-dev.41](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.40...v2.174.0-dev.41) (2023-05-24)
### Bug Fixes
* **youtube/vanced-microg-support:** depend on `client-spoof` patch ([83a4905](https://github.com/revanced/revanced-patches/commit/83a490575c60adf21db926df3013f539c6d33068))
# [2.174.0-dev.40](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.39...v2.174.0-dev.40) (2023-05-23)
### Bug Fixes
* **photomath/unlock-plus:** constrain to last working version ([#2232](https://github.com/revanced/revanced-patches/issues/2232)) ([4da268e](https://github.com/revanced/revanced-patches/commit/4da268edc006ea496e3b1efd037676f1c40397da))
# [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) # [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)

134
README.md
View File

@@ -9,60 +9,61 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version | | 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:| |:--------:|:--------------:|:-----------------:|
| `always-autorepeat` | Always repeats the playing video again. | 18.16.37 | | `always-autorepeat` | Always repeats the playing video again. | 18.19.35 |
| `client-spoof` | Spoofs a patched client to allow playback. | 18.16.37 | | `client-spoof` | Spoofs a patched client to allow playback. | 18.19.35 |
| `comments` | Hides components related to comments. | 18.16.37 | | `comments` | Hides components related to comments. | 18.19.35 |
| `copy-video-url` | Adds buttons in player to copy video links. | 18.16.37 | | `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-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 | | `custom-video-buffer` | Lets you change the buffers of videos. | 18.19.35 |
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.16.37 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
| `disable-zoom-haptics` | Disables haptics when zooming. | all | | `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 | | `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.19.35 |
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.16.37 | | `hide-ads` | Removes general ads. | 18.19.35 |
| `hide-album-cards` | Hides the album cards below the artist description. | 18.16.37 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `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-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-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.16.37 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.19.35 |
| `hide-info-cards` | Hides info cards in videos. | 18.16.37 | | `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.16.37 | | `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. | all | | `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-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-seekbar` | Hides the seekbar. | 18.19.35 |
| `hide-timestamp` | Hides timestamp in video player. | 18.16.37 | | `hide-shorts-components` | Hides components from YouTube Shorts. | 18.19.35 |
| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.16.37 | | `hide-timestamp` | Hides timestamp in video player. | 18.19.35 |
| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.16.37 | | `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.19.35 |
| `hide-watermark` | Hides creator's watermarks on videos. | 18.16.37 | | `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.19.35 |
| `minimized-playback` | Enables minimized and background playback. | 18.16.37 | | `hide-watermark` | Hides creator's watermarks on videos. | 18.19.35 |
| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.16.37 | | `minimized-playback` | Enables minimized and background playback. | 18.19.35 |
| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.16.37 | | `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.19.35 |
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.16.37 | | `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 | | `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 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `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.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.19.35 |
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.16.37 | | `swipe-controls` | Adds volume and brightness swipe controls. | 18.19.35 |
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.16.37 | | `tablet-mini-player` | Enables the tablet mini player layout. | 18.19.35 |
| `theme` | Applies a custom theme. | all | | `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 | | `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.16.37 | | `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.16.37 | | `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.16.37 | | `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.19.35 |
</details> </details>
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music) ### [📦 `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 | | `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
</details> </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) ### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
<details> <details>
@@ -160,16 +172,6 @@ The official ReVanced Patches.
| `hide-inbox-ads` | Hides ads in inbox. | all | | `hide-inbox-ads` | Hides ads in inbox. | all |
</details> </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) ### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
<details> <details>
@@ -297,7 +299,7 @@ The official ReVanced Patches.
| 💊 Patch | 📜 Description | 🏹 Target Version | | 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:| |:--------:|:--------------:|:-----------------:|
| `unlock-plus` | Unlocks plus features. | all | | `unlock-plus` | Unlocks plus features. | 8.20.0 |
</details> </details>
### [📦 `io.yuka.android`](https://play.google.com/store/apps/details?id=io.yuka.android) ### [📦 `io.yuka.android`](https://play.google.com/store/apps/details?id=io.yuka.android)
@@ -340,6 +342,14 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all pro features. | all | | `unlock-pro` | Unlocks all pro features. | all |
</details> </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) ### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
<details> <details>
@@ -372,6 +382,14 @@ The official ReVanced Patches.
| `unlock-pro` | Unlocks all professional features. | 3.4.9 | | `unlock-pro` | Unlocks all professional features. | 3.4.9 |
</details> </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) ### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
<details> <details>

View File

@@ -27,7 +27,7 @@ repositories {
} }
dependencies { dependencies {
implementation("app.revanced:revanced-patcher:8.0.0") implementation("app.revanced:revanced-patcher:9.0.0")
implementation("app.revanced:multidexlib2:2.5.3-a3836654") implementation("app.revanced:multidexlib2:2.5.3-a3836654")
// Required for meta // Required for meta
implementation("com.google.code.gson:gson:2.10.1") implementation("com.google.code.gson:gson:2.10.1")

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,15 @@
package app.revanced.extensions package app.revanced.extensions
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name 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.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod 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.Method
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.util.MethodUtil import org.jf.dexlib2.util.MethodUtil
import org.w3c.dom.Node import org.w3c.dom.Node
@@ -15,7 +19,7 @@ import org.w3c.dom.Node
* *
* @return A [PatchResultError] for the [MethodFingerprint]. * @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]. * 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. * @param method The [Method] to find.
* @return The [MutableMethod]. * @return The [MutableMethod].
*/ */
fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first { internal fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
MethodUtil.methodSignaturesMatch(it, method) 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 * @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() } val transformedMethods = methods.map { it.transform() }
methods.clear() methods.clear()
methods.addAll(transformedMethods) methods.addAll(transformedMethods)
@@ -41,4 +45,29 @@ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod)
internal fun Node.doRecursively(action: (Node) -> Unit) { internal fun Node.doRecursively(action: (Node) -> Unit) {
action(this) action(this)
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action) 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,7 +5,7 @@ import org.jf.dexlib2.AccessFlags
object BootStateFingerprint : MethodFingerprint( object BootStateFingerprint : MethodFingerprint(
"Z", "Z",
access = AccessFlags.PUBLIC.value, accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("Boot state of device: %s"), strings = listOf("Boot state of device: %s"),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AttestationHelper;") methodDef.definingClass.endsWith("/AttestationHelper;")

View File

@@ -5,7 +5,7 @@ import org.jf.dexlib2.AccessFlags
object BootloaderDetectionFingerprint : MethodFingerprint( object BootloaderDetectionFingerprint : MethodFingerprint(
"Z", "Z",
access = AccessFlags.PUBLIC.value, accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("Creation of attestation key succeeded", "Creation of attestation key failed"), strings = listOf("Creation of attestation key succeeded", "Creation of attestation key failed"),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AttestationHelper;") methodDef.definingClass.endsWith("/AttestationHelper;")

View File

@@ -5,7 +5,7 @@ import org.jf.dexlib2.AccessFlags
object RootDetectionFingerprint : MethodFingerprint( object RootDetectionFingerprint : MethodFingerprint(
"V", "V",
access = AccessFlags.PUBLIC.value, accessFlags = AccessFlags.PUBLIC.value,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;") methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
} }

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object SpoofSignatureFingerprint : MethodFingerprint( object SpoofSignatureFingerprint : MethodFingerprint(
"L", "L",
parameters = listOf("L"), parameters = listOf("L"),
access = AccessFlags.PRIVATE.value, accessFlags = AccessFlags.PRIVATE.value,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey" methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey"
} }

View File

@@ -1,9 +1,8 @@
package app.revanced.patches.inshorts.ad.fingerprints package app.revanced.patches.inshorts.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object InshortsAdsFingerprint : MethodFingerprint( object InshortsAdsFingerprint : MethodFingerprint(
"V", "V",
strings = listOf("GoogleAdLoader","exception in requestAd") strings = listOf("GoogleAdLoader","exception in requestAd"),
) )

View File

@@ -9,13 +9,13 @@ import org.jf.dexlib2.iface.Method
abstract class MediaAdFingerprint( abstract class MediaAdFingerprint(
returnType: String? = "Z", returnType: String? = "Z",
access: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters: Iterable<String>? = listOf(), parameters: Iterable<String>? = listOf(),
opcodes: Iterable<Opcode>?, opcodes: Iterable<Opcode>?,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
) : MethodFingerprint( ) : MethodFingerprint(
returnType, returnType,
access, accessFlags,
parameters, parameters,
opcodes, opcodes,
customFingerprint = customFingerprint customFingerprint = customFingerprint

View File

@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object LicenseValidationFingerprint : MethodFingerprint( object LicenseValidationFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,

View File

@@ -9,7 +9,7 @@ import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) @FuzzyPatternScanMethod(2)
object VerifySignatureFingerprint : MethodFingerprint( object VerifySignatureFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/app/Activity;"), parameters = listOf("Landroid/app/Activity;"),
opcodes = listOf( opcodes = listOf(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,

View File

@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object IsFreeVersionFingerprint : MethodFingerprint( object IsFreeVersionFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Boolean;", returnType = "Ljava/lang/Boolean;",
access = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf("free"), strings = listOf("free"),
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
opcodes = listOf( opcodes = listOf(

View File

@@ -10,7 +10,7 @@ object LoadInboxAdsFingerprint : MethodFingerprint(
"ads_load_begin", "ads_load_begin",
"inbox_ads_fetch_start" "inbox_ads_fetch_start"
), ),
access = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;" methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;"
} }

View File

@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object CheckSignatureFingerprint : MethodFingerprint( object CheckSignatureFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
(methodDef.definingClass == "Lcom/microblink/photomath/main/activity/LauncherActivity;" || (methodDef.definingClass == "Lcom/microblink/photomath/main/activity/LauncherActivity;" ||
methodDef.definingClass == "Lcom/microblink/photomath/PhotoMath;") && methodDef.definingClass == "Lcom/microblink/photomath/PhotoMath;") &&

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.photomath.misc.unlockplus.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.microblink.photomath", arrayOf("8.20.0"))])
@Target(AnnotationTarget.CLASS)
internal annotation class UnlockPlusCompatibilty

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object IsPlusUnlockedFingerprint : MethodFingerprint( object IsPlusUnlockedFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf( strings = listOf(
"genius" "genius"
), ),

View File

@@ -1,10 +1,8 @@
package app.revanced.patches.photomath.misc.unlockplus.patch package app.revanced.patches.photomath.misc.unlockplus.patch
import app.revanced.extensions.toErrorResult import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
@@ -14,13 +12,14 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.photomath.detection.signature.patch.SignatureDetectionPatch import app.revanced.patches.photomath.detection.signature.patch.SignatureDetectionPatch
import app.revanced.patches.photomath.misc.unlockplus.annotations.UnlockPlusCompatibilty
import app.revanced.patches.photomath.misc.unlockplus.fingerprints.IsPlusUnlockedFingerprint import app.revanced.patches.photomath.misc.unlockplus.fingerprints.IsPlusUnlockedFingerprint
@Patch @Patch
@Name("unlock-plus") @Name("unlock-plus")
@DependsOn([SignatureDetectionPatch::class]) @DependsOn([SignatureDetectionPatch::class])
@Description("Unlocks plus features.") @Description("Unlocks plus features.")
@Compatibility([Package("com.microblink.photomath")]) @UnlockPlusCompatibilty
@Version("0.0.1") @Version("0.0.1")
class UnlockPlusPatch : BytecodePatch( class UnlockPlusPatch : BytecodePatch(
listOf( listOf(
@@ -41,4 +40,4 @@ class UnlockPlusPatch : BytecodePatch(
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@@ -5,18 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.reddit.frontpage", arrayOf( "com.reddit.frontpage"
"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) @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.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch 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.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.ReferenceInstruction 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 import org.jf.dexlib2.immutable.reference.ImmutableStringReference
@Patch @Patch
@Name("general-reddit-ads") @Name("hide-ads")
@Description("Removes general ads from the Reddit frontpage and subreddits.") @Description("Removes general ads from the Reddit frontpage and subreddits.")
@GeneralAdsCompatibility @HideAdsCompatibility
@Version("0.0.1") @Version("0.0.1")
class GeneralAdsPatch : BytecodePatch() { class HideAdsPatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef -> context.classes.forEach { classDef ->
classDef.methods.forEach methodLoop@{ method -> 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",
accessFlags = 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

@@ -9,6 +9,7 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint.RegisterResolver
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.ClassDef import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
@@ -27,7 +28,7 @@ abstract class AbstractIntegrationsPatch(
*/ */
abstract class IntegrationsFingerprint( abstract class IntegrationsFingerprint(
returnType: String? = null, returnType: String? = null,
access: Int? = null, accessFlags: Int? = null,
parameters: Iterable<String>? = null, parameters: Iterable<String>? = null,
opcodes: Iterable<Opcode?>? = null, opcodes: Iterable<Opcode?>? = null,
strings: Iterable<String>? = null, strings: Iterable<String>? = null,
@@ -35,7 +36,7 @@ abstract class AbstractIntegrationsPatch(
private val contextRegisterResolver: (Method) -> Int = object : RegisterResolver {} private val contextRegisterResolver: (Method) -> Int = object : RegisterResolver {}
) : MethodFingerprint( ) : MethodFingerprint(
returnType, returnType,
access, accessFlags,
parameters, parameters,
opcodes, opcodes,
strings, strings,

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 app.revanced.patches.shared.misc.fix.verticalscroll.fingerprints.CanScrollVerticallyFingerprint
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction 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 @VerticalScrollCompatibility
@Version("0.0.1") @Version("0.0.1")
class VerticalScrollPatch : BytecodePatch( class VerticalScrollPatch : BytecodePatch(

View File

@@ -6,6 +6,6 @@ import org.jf.dexlib2.AccessFlags
object IsAdsEnabledFingerprint : MethodFingerprint( object IsAdsEnabledFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf("SyncIapHelper") strings = listOf("SyncIapHelper")
) )

View File

@@ -9,7 +9,7 @@ import org.jf.dexlib2.iface.reference.TypeReference
object PiracyDetectionFingerprint : MethodFingerprint( object PiracyDetectionFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PRIVATE or AccessFlags.FINAL, accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
opcodes = listOf( opcodes = listOf(
Opcode.NEW_INSTANCE, Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object FeedApiServiceLIZFingerprint : MethodFingerprint( object FeedApiServiceLIZFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "LIZ" methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "LIZ"
} }

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object SpeedControlParentFingerprint : MethodFingerprint( object SpeedControlParentFingerprint : MethodFingerprint(
returnType = "L", returnType = "L",
access = AccessFlags.PRIVATE or AccessFlags.FINAL, accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
parameters = listOf( parameters = listOf(
"L" "L"
), ),

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object GoogleAuthAvailableFingerprint : MethodFingerprint( object GoogleAuthAvailableFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(), parameters = listOf(),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/bytedance/lobby/google/GoogleAuth;" methodDef.definingClass == "Lcom/bytedance/lobby/google/GoogleAuth;"

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object GoogleOneTapAuthAvailableFingerprint : MethodFingerprint( object GoogleOneTapAuthAvailableFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(), parameters = listOf(),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/bytedance/lobby/google/GoogleOneTapAuth;" methodDef.definingClass == "Lcom/bytedance/lobby/google/GoogleOneTapAuth;"

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

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object InlineActionTypesFingerprint : MethodFingerprint( object InlineActionTypesFingerprint : MethodFingerprint(
returnType = "Ljava/util/List", returnType = "Ljava/util/List",
access = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf( strings = listOf(
"getCurrentMemoizing()", "getCurrentMemoizing()",
"android_animated_reply_icon_enabled", "android_animated_reply_icon_enabled",

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
object TweetStatsContainerConstructorFingerprint : MethodFingerprint( object TweetStatsContainerConstructorFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
object TweetStatsContainerWrapperConstructorFingerprint : MethodFingerprint( object TweetStatsContainerWrapperConstructorFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
object TweetStatsViewDelegateBinderFingerprint : MethodFingerprint( object TweetStatsViewDelegateBinderFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf( opcodes = listOf(
Opcode.NEW_INSTANCE, Opcode.NEW_INSTANCE,
Opcode.CONST_16, Opcode.CONST_16,

View File

@@ -5,5 +5,9 @@ import org.jf.dexlib2.Opcode
object JsonHookPatchFingerprint : MethodFingerprint( object JsonHookPatchFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> methodDef.name == "<clinit>" }, 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.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions 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.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.* 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.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonHookPatchFingerprint 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.JsonInputStreamFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint
import java.io.Closeable
import java.io.InvalidClassException import java.io.InvalidClassException
@Name("json-hook") @Name("json-hook")
@@ -20,16 +25,16 @@ import java.io.InvalidClassException
@RequiresIntegrations @RequiresIntegrations
class JsonHookPatch : BytecodePatch( class JsonHookPatch : BytecodePatch(
listOf(LoganSquareFingerprint) listOf(LoganSquareFingerprint)
) { ), Closeable {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
// Make sure the integrations are present. JsonHookPatchFingerprint.also {
val jsonHookPatch = context.findClass { it.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR } // Make sure the integrations are present.
?: return PatchResultError("Could not find integrations.") 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. if (!it.resolve(context, jsonHookPatch.immutableClass))
jsonHookPatchFingerprintResult = JsonHookPatchFingerprint.also { throw PatchResultError("Unexpected integrations.")
it.resolve(context, jsonHookPatch.immutableClass) }.let { hooks = JsonHookPatchHook(it) }
}.result ?: return PatchResultError("Unexpected integrations.")
// Conveniently find the type to hook a method in, via a named field. // Conveniently find the type to hook a method in, via a named field.
val jsonFactory = LoganSquareFingerprint.result val jsonFactory = LoganSquareFingerprint.result
@@ -64,30 +69,10 @@ class JsonHookPatch : BytecodePatch(
* *
* @param context The [BytecodeContext] of the current patch. * @param context The [BytecodeContext] of the current patch.
* @param descriptor The class descriptor of the hook. * @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) { internal class Hook(context: BytecodeContext, internal val descriptor: String) {
private var added = false internal 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
}
init { init {
context.findClass { it.type == descriptor }?.let { 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.BytecodePatch
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
@DependsOn([JsonHookPatch::class])
abstract class BaseHookPatchPatch(private val hookClassDescriptor: String) : BytecodePatch() { abstract class BaseHookPatchPatch(private val hookClassDescriptor: String) : BytecodePatch() {
override fun execute(context: BytecodeContext) = try { override fun execute(context: BytecodeContext) = try {
PatchResultSuccess().also { JsonHookPatch.Hook(context, hookClassDescriptor).add() } JsonHookPatch.hooks.addHook(JsonHookPatch.Hook(context, hookClassDescriptor))
PatchResultSuccess()
} catch (ex: Exception) { } catch (ex: Exception) {
PatchResultError(ex) PatchResultError(ex)
} }

View File

@@ -15,8 +15,4 @@ import app.revanced.patches.twitter.misc.hook.patch.ads.annotations.HideAdsCompa
@Description("Hides ads.") @Description("Hides ads.")
@HideAdsCompatibility @HideAdsCompatibility
@Version("0.0.1") @Version("0.0.1")
class HideAdsPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) { class HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
private companion object {
const val HOOK_CLASS_DESCRIPTOR = "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.") @Description("Hides recommended users.")
@HideRecommendedUsersCompatibility @HideRecommendedUsersCompatibility
@Version("0.0.1") @Version("0.0.1")
class HideRecommendedUsersPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) { class HideRecommendedUsersPatch : BaseHookPatchPatch(
private companion object { "Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
const val HOOK_CLASS_DESCRIPTOR = )
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
}
}

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.vsco.misc.pro.fingerprints
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 package app.revanced.patches.youtube.ad.general.bytecode.patch
import app.revanced.extensions.findMutableMethodOf 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.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext 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.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch 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.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
import app.revanced.patches.youtube.ad.general.bytecode.fingerprints.ReelConstructorFingerprint import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch 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.Instruction31i
import org.jf.dexlib2.iface.instruction.formats.Instruction35c import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch @Patch
@DependsOn([GeneralAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class]) @DependsOn([HideAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
@Name("general-ads") @Name("hide-ads")
@Description("Removes general ads.") @Description("Removes general ads.")
@GeneralAdsCompatibility @HideAdsCompatibility
@Version("0.0.1") @Version("0.0.1")
class GeneralAdsPatch : BytecodePatch( class HideAdsPatch : BytecodePatch() {
listOf(ReelConstructorFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult { 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 -> context.classes.forEach { classDef ->
classDef.methods.forEach { method -> classDef.methods.forEach { method ->
with(method.implementation) { with(method.implementation) {
@@ -49,7 +34,7 @@ class GeneralAdsPatch : BytecodePatch(
if (instruction.opcode != org.jf.dexlib2.Opcode.CONST) if (instruction.opcode != org.jf.dexlib2.Opcode.CONST)
return@forEachIndexed return@forEachIndexed
// Instruction to store the id adAttribution into a register // 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 return@forEachIndexed
val insertIndex = index + 1 val insertIndex = index + 1
@@ -64,25 +49,18 @@ class GeneralAdsPatch : BytecodePatch(
context.proxy(classDef) context.proxy(classDef)
.mutableClass .mutableClass
.findMutableMethodOf(method) .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() return PatchResultSuccess()
} }
} }

View File

@@ -8,7 +8,7 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.* import app.revanced.patches.shared.settings.preference.impl.*
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.litho.filter.patch.LithoFilterPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen 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 ResourceMappingPatch::class
] ]
) )
@GeneralAdsCompatibility @HideAdsCompatibility
@Version("0.0.1") @Version("0.0.1")
class GeneralAdsResourcePatch : ResourcePatch { class HideAdsResourcePatch : ResourcePatch {
internal companion object {
var adAttributionId: Long = -1
var reelMultipleItemShelfId: Long = -1
}
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
PreferenceScreen.LAYOUT.addPreferences( 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_on", "Feed surveys are hidden"),
StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown") 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( SwitchPreference(
"revanced_hide_community_guidelines", "revanced_hide_community_guidelines",
StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"), StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
@@ -197,7 +187,13 @@ class GeneralAdsResourcePatch : ResourcePatch {
StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"), StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"),
StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"), StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"),
StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown") StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown")
) ),
SwitchPreference(
"revanced_hide_latest_posts_ads",
StringResource("revanced_hide_latest_posts_ads_title", "Hide latest posts"),
StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
),
) )
PreferenceScreen.ADS.addPreferences( PreferenceScreen.ADS.addPreferences(
@@ -219,12 +215,6 @@ class GeneralAdsResourcePatch : ResourcePatch {
StringResource("revanced_hide_paid_content_ads_summary_on", "Paid content is hidden"), StringResource("revanced_hide_paid_content_ads_summary_on", "Paid content is hidden"),
StringResource("revanced_hide_paid_content_ads_summary_off", "Paid content is shown") StringResource("revanced_hide_paid_content_ads_summary_off", "Paid content is shown")
), ),
SwitchPreference(
"revanced_hide_latest_posts_ads",
StringResource("revanced_hide_latest_posts_ads_title", "Hide latest posts"),
StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
),
SwitchPreference( SwitchPreference(
"revanced_hide_self_sponsor_ads", "revanced_hide_self_sponsor_ads",
StringResource("revanced_hide_self_sponsor_ads_title", "Hide self sponsored cards"), StringResource("revanced_hide_self_sponsor_ads_title", "Hide self sponsored cards"),
@@ -263,11 +253,12 @@ class GeneralAdsResourcePatch : ResourcePatch {
) )
) )
fun String.getId() = ResourceMappingPatch.resourceMappings.single { it.name == this }.id adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
adAttributionId = "ad_attribution".getId()
reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
return PatchResultSuccess() 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class VideoAdsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class CopyVideoUrlCompatibility internal annotation class CopyVideoUrlCompatibility

View File

@@ -26,8 +26,7 @@ import app.revanced.patches.youtube.video.information.patch.VideoInformationPatc
@Version("0.0.1") @Version("0.0.1")
class CopyVideoUrlBytecodePatch : BytecodePatch() { class CopyVideoUrlBytecodePatch : BytecodePatch() {
private companion object { private companion object {
const val INTEGRATIONS_PACKAGE = "Lapp/revanced/integrations" const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
const val INTEGRATIONS_PLAYER_PACKAGE = "$INTEGRATIONS_PACKAGE/videoplayer"
val BUTTONS_DESCRIPTORS = listOf( val BUTTONS_DESCRIPTORS = listOf(
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;", "$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;" "$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
@@ -38,10 +37,8 @@ class CopyVideoUrlBytecodePatch : BytecodePatch() {
// Initialize buttons and inject visibility control // Initialize buttons and inject visibility control
BUTTONS_DESCRIPTORS.forEach { descriptor -> BUTTONS_DESCRIPTORS.forEach { descriptor ->
val initializeButtonDescriptor = "$descriptor->initializeButton(Ljava/lang/Object;)V" PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
val visibilityDescriptor = "$descriptor->changeVisibility(Z)V" PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
PlayerControlsBytecodePatch.initializeControl(initializeButtonDescriptor)
PlayerControlsBytecodePatch.injectVisibilityCheckCall(visibilityDescriptor)
} }
return PatchResultSuccess() 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.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("copy-video-url-resource") @Name("copy-video-url-resource")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class]) @DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
@@ -28,13 +29,13 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
SwitchPreference( SwitchPreference(
"revanced_copy_video_url", "revanced_copy_video_url",
StringResource("revanced_copy_video_url_title", "Show copy video URL button"), 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") StringResource("revanced_copy_video_url_summary_off", "Button is not shown")
), ),
SwitchPreference( SwitchPreference(
"revanced_copy_video_url_timestamp", "revanced_copy_video_url_timestamp",
StringResource("revanced_copy_video_url_timestamp_title", "Show copy timestamp URL button"), 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") StringResource("revanced_copy_video_url_timestamp_summary_off", "Button is not shown")
) )
), ),
@@ -48,6 +49,9 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
"revanced_yt_copy_timestamp.xml" "revanced_yt_copy_timestamp.xml"
)) ))
// merge strings
context.mergeStrings("copyvideourl/host/values/strings.xml")
BottomControlsResourcePatch.addControls("copyvideourl/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}") BottomControlsResourcePatch.addControls("copyvideourl/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
return PatchResultSuccess() 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class DownloadsCompatibility internal annotation class DownloadsCompatibility

View File

@@ -21,23 +21,24 @@ import app.revanced.patches.youtube.video.information.patch.VideoInformationPatc
@DownloadsCompatibility @DownloadsCompatibility
@Version("0.0.1") @Version("0.0.1")
class DownloadsBytecodePatch : BytecodePatch() { class DownloadsBytecodePatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult { private companion object {
val integrationsPackage = "app/revanced/integrations" const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/DownloadButton;"
val classDescriptor = "L$integrationsPackage/videoplayer/DownloadButton;" }
override fun execute(context: BytecodeContext): PatchResult {
/* /*
initialize the control initialize the control
*/ */
val initializeDownloadsDescriptor = "$classDescriptor->initializeButton(Ljava/lang/Object;)V" PlayerControlsBytecodePatch.initializeControl(
PlayerControlsBytecodePatch.initializeControl(initializeDownloadsDescriptor) "$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
/* /*
add code to change the visibility of the control add code to change the visibility of the control
*/ */
val changeVisibilityDescriptor = "$classDescriptor->changeVisibility(Z)V" PlayerControlsBytecodePatch.injectVisibilityCheckCall(
PlayerControlsBytecodePatch.injectVisibilityCheckCall(changeVisibilityDescriptor) "$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
return PatchResultSuccess() 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class SeekbarTappingCompatibility 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",
accessFlags = 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 package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode 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( object SeekbarTappingFingerprint : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( returnType = "Z",
Opcode.INVOKE_VIRTUAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
Opcode.MOVE_RESULT_WIDE, parameters = listOf("L"),
Opcode.IGET, opcodes = listOf(
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,
Opcode.IPUT_OBJECT, 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 package app.revanced.patches.youtube.interaction.seekbar.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch 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.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.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.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.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.iface.Method 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 import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch @Patch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) @DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
@Name("seekbar-tapping") @Name("seekbar-tapping")
@Description("Enables tap-to-seek on the seekbar of the video player.") @Description("Enables tap-to-seek on the seekbar of the video player.")
@SeekbarTappingCompatibility @SeekbarTappingCompatibility
@Version("0.0.1") @Version("0.0.1")
class EnableSeekbarTappingPatch : BytecodePatch( class EnableSeekbarTappingPatch : BytecodePatch(
listOf( listOf(AccessibilityPlayerProgressTimeFingerprint, SeekbarTappingFingerprint)
SeekbarTappingParentFingerprint, SeekbarTappingFingerprint
)
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences( // Find the required methods to tap the seekbar.
SwitchPreference( val seekbarTappingMethods =
"revanced_tap_seeking", AccessibilityPlayerProgressTimeFingerprint.result?.classDef?.methods?.let { methods ->
StringResource("revanced_tap_seeking_title", "Enable seekbar tapping"), buildMap {
StringResource("revanced_tap_seeking_summary_on", "Seekbar tapping is enabled"), // find the methods which tap the seekbar
StringResource("revanced_tap_seeking_summary_off", "Seekbar tapping is disabled") 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 // The 7th instruction has the opcode CONST_4.
for (it in result.classDef.methods) { val instruction = instructions.elementAt(6)
if (it.implementation == null) continue if (instruction.opcode != Opcode.CONST_4) return@forEach
val instructions = it.implementation!!.instructions // the literal for this instruction has to be either 1 or 2.
// here we make sure we actually find the method because it has more than 7 instructions val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
if (instructions.count() < 7) continue
// we know that the 7th instruction has the opcode CONST_4 // Based on the literal, determine which method is which.
val instruction = instructions.elementAt(6) if (literal == 1) this["P"] = method
if (instruction.opcode != Opcode.CONST_4) continue if (literal == 2) this["O"] = method
}
}
}
// the literal for this instruction has to be either 1 or 2 seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
val literal = (instruction as Instruction11n).narrowLiteral
// method founds SeekbarTappingFingerprint.result?.let {
if (literal == 1) tapSeekMethods["P"] = it val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
if (literal == 2) tapSeekMethods["O"] = it
}
// replace map because we don't need the upper one anymore it.mutableMethod.apply {
result = SeekbarTappingFingerprint.result!! 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 = seekbarTappingMethods["P"]!!
val pMethod = tapSeekMethods["P"]!! val oMethod = seekbarTappingMethods["O"]!!
val oMethod = tapSeekMethods["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 addInstructions(
val instruction = implementation.instructions[insertIndex - 1] insertIndex,
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register") """
val register = (instruction as Instruction35c).registerC 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() 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class SwipeControlsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class AutoCaptionsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideButtonsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class AutoplayButtonCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideCaptionsButtonCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class NavigationButtonsCompatibility internal annotation class NavigationButtonsCompatibility

View File

@@ -5,6 +5,6 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object PivotBarConstructorFingerprint : MethodFingerprint( object PivotBarConstructorFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf("com.google.android.apps.youtube.app.endpoint.flags") strings = listOf("com.google.android.apps.youtube.app.endpoint.flags")
) )

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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class PlayerButtonBackgroundCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[Package(
"com.google.android.youtube", arrayOf()
)]
)
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class HidePlayerButtonsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class AlbumCardsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideArtistCardCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class BreakingNewsCompatibility 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.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext 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.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn 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.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen 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.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference 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 import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("comments-resource-patch") @Patch
@CommentsCompatibility @Name("comments")
@Description("Hides components related to comments.")
@HideCommentsCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1") @Version("0.0.1")
class CommentsResourcePatch : ResourcePatch { class CommentsPatch : ResourcePatch {
companion object {
internal var shortsCommentsButtonId: Long = -1
}
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen( PreferenceScreen(
@@ -40,22 +40,12 @@ class CommentsResourcePatch : ResourcePatch {
StringResource("revanced_hide_preview_comment_title", "Hide preview comment"), StringResource("revanced_hide_preview_comment_title", "Hide preview comment"),
StringResource("revanced_hide_preview_comment_on", "Preview comment is hidden"), StringResource("revanced_hide_preview_comment_on", "Preview comment is hidden"),
StringResource("revanced_hide_preview_comment_off", "Preview comment is shown") 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") 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() 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class CrowdfundingBoxCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideEndscreenCardsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package 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) @Target(AnnotationTarget.CLASS)
internal annotation class HideFilterBar 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideFloatingMicrophoneButtonCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package 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) @Target(AnnotationTarget.CLASS)
internal annotation class HideGetPremiumCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideInfocardsCompatibility 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.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
[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) @Target(AnnotationTarget.CLASS)
internal annotation class HideLoadMoreButtonCompatibility internal annotation class HideLoadMoreButtonCompatibility

View File

@@ -9,7 +9,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object HideLoadMoreButtonFingerprint : MethodFingerprint( object HideLoadMoreButtonFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L", "L", "L", "L"), parameters = listOf("L", "L", "L", "L"),
opcodes = listOf( opcodes = listOf(
Opcode.CONST, Opcode.CONST,

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

View File

@@ -9,7 +9,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object CreatePlayerOverviewFingerprint : MethodFingerprint( object CreatePlayerOverviewFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PRIVATE or AccessFlags.FINAL, accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
opcodes = listOf( opcodes = listOf(
Opcode.CONST, Opcode.CONST,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,

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

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