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
description: Report a very clearly broken issue.
title: 'bug: <title>'
title: 'bug: '
labels: [bug]
body:
- type: markdown

View File

@@ -1,6 +1,6 @@
name: ⭐ Patch Request
description: Create a detailed patch request.
title: 'feat(patch): '
title: 'feat: '
labels: [patch-request]
body:
- type: textarea
@@ -24,7 +24,7 @@ body:
- type: textarea
attributes:
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:
required: true
- type: checkboxes
@@ -38,4 +38,4 @@ body:
- label: I have written a short but informative title.
required: true
- 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)

134
README.md
View File

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

View File

@@ -27,7 +27,7 @@ repositories {
}
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")
// Required for meta
implementation("com.google.code.gson:gson:2.10.1")

View File

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

View File

@@ -5,7 +5,7 @@ import org.jf.dexlib2.AccessFlags
object BootStateFingerprint : MethodFingerprint(
"Z",
access = AccessFlags.PUBLIC.value,
accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("Boot state of device: %s"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AttestationHelper;")

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,8 @@
package app.revanced.patches.inshorts.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object InshortsAdsFingerprint : MethodFingerprint(
"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(
returnType: String? = "Z",
access: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters: Iterable<String>? = listOf(),
opcodes: Iterable<Opcode>?,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
) : MethodFingerprint(
returnType,
access,
accessFlags,
parameters,
opcodes,
customFingerprint = customFingerprint

View File

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

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ object LoadInboxAdsFingerprint : MethodFingerprint(
"ads_load_begin",
"inbox_ads_fetch_start"
),
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
customFingerprint = { methodDef, _ ->
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(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { methodDef, _ ->
(methodDef.definingClass == "Lcom/microblink/photomath/main/activity/LauncherActivity;" ||
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(
returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf(
"genius"
),

View File

@@ -1,10 +1,8 @@
package app.revanced.patches.photomath.misc.unlockplus.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
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.Patch
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
@Patch
@Name("unlock-plus")
@DependsOn([SignatureDetectionPatch::class])
@Description("Unlocks plus features.")
@Compatibility([Package("com.microblink.photomath")])
@UnlockPlusCompatibilty
@Version("0.0.1")
class UnlockPlusPatch : BytecodePatch(
listOf(
@@ -41,4 +40,4 @@ class UnlockPlusPatch : BytecodePatch(
return PatchResultSuccess()
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.reddit.misc.tracking.url.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object ShareLinkFactoryFingerprint : MethodFingerprint(
returnType = "L",
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.PatchResultError
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.iface.ClassDef
import org.jf.dexlib2.iface.Method
@@ -27,7 +28,7 @@ abstract class AbstractIntegrationsPatch(
*/
abstract class IntegrationsFingerprint(
returnType: String? = null,
access: Int? = null,
accessFlags: Int? = null,
parameters: Iterable<String>? = null,
opcodes: Iterable<Opcode?>? = null,
strings: Iterable<String>? = null,
@@ -35,7 +36,7 @@ abstract class AbstractIntegrationsPatch(
private val contextRegisterResolver: (Method) -> Int = object : RegisterResolver {}
) : MethodFingerprint(
returnType,
access,
accessFlags,
parameters,
opcodes,
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 org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Description("Fixes issues with scrolling on the home screen when the first component is of type EmptyComponent.")
@Description("Fixes issues with refreshing the feed when the first component is of type EmptyComponent.")
@VerticalScrollCompatibility
@Version("0.0.1")
class VerticalScrollPatch : BytecodePatch(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object GoogleOneTapAuthAvailableFingerprint : MethodFingerprint(
returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
customFingerprint = { methodDef, _ ->
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(
returnType = "Ljava/util/List",
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf(
"getCurrentMemoizing()",
"android_animated_reply_icon_enabled",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.ad.video.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class VideoAdsCompatibility

View File

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

View File

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

View File

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

View File

@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.interaction.downloads.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class DownloadsCompatibility

View File

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

View File

@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.interaction.seekbar.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SeekbarTappingCompatibility

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,6 +5,6 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
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")
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.youtube.layout.hide.comments.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideCommentsCompatibility

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object HideLoadMoreButtonFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L", "L", "L", "L"),
opcodes = listOf(
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.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideEmailAddressCompatibility

View File

@@ -9,7 +9,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object CreatePlayerOverviewFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PRIVATE or AccessFlags.FINAL,
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
opcodes = listOf(
Opcode.CONST,
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.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf(
"17.49.37",
"18.03.36",
"18.03.42",
"18.04.35",
"18.04.41",
"18.05.32",
"18.05.35",
"18.05.40",
"18.08.37",
"18.15.40",
"18.16.37"
)
)]
)
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideSeekbarCompatibility

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.youtube.layout.hide.shorts.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideShortsComponentsCompatibility

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