Compare commits

...

20 Commits

Author SHA1 Message Date
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
133 changed files with 1351 additions and 1542 deletions

View File

@@ -1,3 +1,43 @@
# [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) # [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)

124
README.md
View File

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

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 2.174.0-dev.33 version = 2.174.0-dev.37

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -22,4 +22,4 @@ import app.revanced.patcher.annotation.Package
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class GeneralAdsCompatibility internal annotation class HideAdsCompatibility

View File

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

View File

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

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.reddit.misc.tracking.url.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object ShareLinkFactoryFingerprint : MethodFingerprint(
returnType = "L",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.INVOKE_DIRECT,
Opcode.APUT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC, // Returns the URL.
Opcode.MOVE_RESULT_OBJECT
),
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("ShareLinkFactory;") }
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.youtube.ad.general.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideAdsCompatibility

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.shared.misc.fix.spoof.fingerprints package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.shared.misc.fix.spoof.patch package app.revanced.patches.youtube.misc.fix.playback.patch
import app.revanced.extensions.toErrorResult import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
@@ -12,9 +12,8 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.misc.fix.spoof.annotations.ClientSpoofCompatibility import app.revanced.patches.youtube.misc.fix.playback.annotations.ClientSpoofCompatibility
import app.revanced.patches.shared.misc.fix.spoof.fingerprints.UserAgentHeaderBuilderFingerprint import app.revanced.patches.youtube.misc.fix.playback.fingerprints.UserAgentHeaderBuilderFingerprint
import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationPatch
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch @Patch

View File

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

View File

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

View File

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

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