mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-15 15:33:13 +00:00
Compare commits
26 Commits
v2.174.0-d
...
v2.174.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
769b1932d4 | ||
|
|
324d4b83d3 | ||
|
|
97822d6ee7 | ||
|
|
67674170da | ||
|
|
76711f0785 | ||
|
|
4178ca3be1 | ||
|
|
c681316ee1 | ||
|
|
b56844dc6b | ||
|
|
d4843d185a | ||
|
|
52029ee987 | ||
|
|
80661dbf43 | ||
|
|
e9b2b72681 | ||
|
|
b4110fb798 | ||
|
|
3cfbe206dc | ||
|
|
1d0bf1b289 | ||
|
|
99de705e8e | ||
|
|
d746f32594 | ||
|
|
ebf144e2c8 | ||
|
|
8e627c682f | ||
|
|
af82eb633c | ||
|
|
acb9b5fe6b | ||
|
|
7e2502c26b | ||
|
|
1fcdc74056 | ||
|
|
91ee6b7750 | ||
|
|
3a905484c0 | ||
|
|
677c0f8145 |
61
CHANGELOG.md
61
CHANGELOG.md
@@ -1,3 +1,64 @@
|
||||
# [2.174.0-dev.39](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.38...v2.174.0-dev.39) (2023-05-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **reddit:** remove compatibility version constraints ([#2226](https://github.com/revanced/revanced-patches/issues/2226)) ([f1288e4](https://github.com/revanced/revanced-patches/commit/f1288e4bb8fb1b9f394d73fd814d97db8704b8e0))
|
||||
|
||||
# [2.174.0-dev.38](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.37...v2.174.0-dev.38) (2023-05-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **trakt:** add `unlock-pro` patch ([#2210](https://github.com/revanced/revanced-patches/issues/2210)) ([1e8dcae](https://github.com/revanced/revanced-patches/commit/1e8dcae6f540455b8698703bbded5f52fd0c6300))
|
||||
|
||||
# [2.174.0-dev.37](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.36...v2.174.0-dev.37) (2023-05-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **reddit:** add `sanitize-sharing-links` patch ([#2192](https://github.com/revanced/revanced-patches/issues/2192)) ([9593e4b](https://github.com/revanced/revanced-patches/commit/9593e4b5db604957545b4ab6747c82fb815ac08b))
|
||||
|
||||
# [2.174.0-dev.36](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.35...v2.174.0-dev.36) (2023-05-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **twitter:** correctly resolve to integrations methods ([c655416](https://github.com/revanced/revanced-patches/commit/c655416a91f0a32cfe82b1384f5958cace891833))
|
||||
|
||||
# [2.174.0-dev.35](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.34...v2.174.0-dev.35) (2023-05-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/minimized-playback:** update settings description ([#2191](https://github.com/revanced/revanced-patches/issues/2191)) ([a561a9a](https://github.com/revanced/revanced-patches/commit/a561a9afc233e466459546fcc8452800ec56e057))
|
||||
* **youtube/settings:** fix non functional back button in settings ([#2178](https://github.com/revanced/revanced-patches/issues/2178)) ([46da834](https://github.com/revanced/revanced-patches/commit/46da83430f69b451f971bf5e9261e9d64d1a365c))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add capability to filter from protobuf buffer ([b738b6b](https://github.com/revanced/revanced-patches/commit/b738b6bf3506f222844ef4bca99a91f78d331391))
|
||||
* use consistent names for patches ([6347146](https://github.com/revanced/revanced-patches/commit/634714690086168e63d6aa9475893135cb58db68))
|
||||
* **youtube/copy-video-url:** add tap and hold functionality to copy video url buttons ([#2174](https://github.com/revanced/revanced-patches/issues/2174)) ([95bbf46](https://github.com/revanced/revanced-patches/commit/95bbf46e77a608bd7ba8f0073d50fef01012d4df))
|
||||
* **youtube/hide-shorts-components:** hide navigation bar ([24f376a](https://github.com/revanced/revanced-patches/commit/24f376a4b8d6bdccc32ffff0d983f22eb4940791))
|
||||
* **youtube:** add `hide-shorts-components` patch ([64868f4](https://github.com/revanced/revanced-patches/commit/64868f41be9f567cb54d9214fafbf849d08b64d2))
|
||||
* **youtube:** constrain patches to `18.16.37` ([758b300](https://github.com/revanced/revanced-patches/commit/758b3005919e11d9dd4f19bf110e9d282f8d1925))
|
||||
* **youtube:** support version `18.19.35` ([491f292](https://github.com/revanced/revanced-patches/commit/491f292182a419cb5399de768560ae4daa7c86cb))
|
||||
|
||||
# [2.174.0-dev.34](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.33...v2.174.0-dev.34) (2023-05-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **vsco:** add `unlock-pro` patch ([#2168](https://github.com/revanced/revanced-patches/issues/2168)) ([7ffd1a0](https://github.com/revanced/revanced-patches/commit/7ffd1a09a7bcf09bc7e7d5f3c8c8613ca34c8c59))
|
||||
|
||||
# [2.174.0-dev.33](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.32...v2.174.0-dev.33) (2023-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/spoof-signature-verification:** adjusting summary text ([#2169](https://github.com/revanced/revanced-patches/issues/2169)) ([4ccb1ee](https://github.com/revanced/revanced-patches/commit/4ccb1ee0b988bc0ddd6a0c986975b17caa828770))
|
||||
|
||||
# [2.174.0-dev.32](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.31...v2.174.0-dev.32) (2023-05-16)
|
||||
|
||||
|
||||
|
||||
132
README.md
132
README.md
@@ -9,60 +9,61 @@ The official ReVanced Patches.
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `always-autorepeat` | Always repeats the playing video again. | 18.16.37 |
|
||||
| `client-spoof` | Spoofs a patched client to allow playback. | 18.16.37 |
|
||||
| `comments` | Hides components related to comments. | 18.16.37 |
|
||||
| `copy-video-url` | Adds buttons in player to copy video links. | 18.16.37 |
|
||||
| `always-autorepeat` | Always repeats the playing video again. | 18.19.35 |
|
||||
| `client-spoof` | Spoofs a patched client to allow playback. | 18.19.35 |
|
||||
| `comments` | Hides components related to comments. | 18.19.35 |
|
||||
| `copy-video-url` | Adds buttons in player to copy video links. | 18.19.35 |
|
||||
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
|
||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 18.16.37 |
|
||||
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.16.37 |
|
||||
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.16.37 |
|
||||
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.16.37 |
|
||||
| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.16.37 |
|
||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 18.19.35 |
|
||||
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.19.35 |
|
||||
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.19.35 |
|
||||
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.19.35 |
|
||||
| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
|
||||
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
|
||||
| `downloads` | Adds a download button to the YouTube video player. | 18.16.37 |
|
||||
| `downloads` | Adds a download button to the YouTube video player. | 18.19.35 |
|
||||
| `enable-debugging` | Adds debugging options. | all |
|
||||
| `general-ads` | Removes general ads. | 18.16.37 |
|
||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.16.37 |
|
||||
| `hide-album-cards` | Hides the album cards below the artist description. | 18.16.37 |
|
||||
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.16.37 |
|
||||
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.16.37 |
|
||||
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.16.37 |
|
||||
| `hide-captions-button` | Hides the captions button on video player. | 18.16.37 |
|
||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
|
||||
| `hide-ads` | Removes general ads. | 18.19.35 |
|
||||
| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
|
||||
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.19.35 |
|
||||
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
|
||||
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
|
||||
| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
|
||||
| `hide-cast-button` | Hides the cast button in the video player. | all |
|
||||
| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.16.37 |
|
||||
| `hide-email-address` | Hides the email address in the account switcher. | 18.16.37 |
|
||||
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.16.37 |
|
||||
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.16.37 |
|
||||
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.16.37 |
|
||||
| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.16.37 |
|
||||
| `hide-info-cards` | Hides info cards in videos. | 18.16.37 |
|
||||
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.16.37 |
|
||||
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | all |
|
||||
| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.19.35 |
|
||||
| `hide-email-address` | Hides the email address in the account switcher. | 18.19.35 |
|
||||
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.19.35 |
|
||||
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.19.35 |
|
||||
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.19.35 |
|
||||
| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.19.35 |
|
||||
| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
|
||||
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
|
||||
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
|
||||
| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
|
||||
| `hide-seekbar` | Hides the seekbar. | 18.16.37 |
|
||||
| `hide-timestamp` | Hides timestamp in video player. | 18.16.37 |
|
||||
| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.16.37 |
|
||||
| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.16.37 |
|
||||
| `hide-watermark` | Hides creator's watermarks on videos. | 18.16.37 |
|
||||
| `minimized-playback` | Enables minimized and background playback. | 18.16.37 |
|
||||
| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.16.37 |
|
||||
| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.16.37 |
|
||||
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.16.37 |
|
||||
| `hide-seekbar` | Hides the seekbar. | 18.19.35 |
|
||||
| `hide-shorts-components` | Hides components from YouTube Shorts. | 18.19.35 |
|
||||
| `hide-timestamp` | Hides timestamp in video player. | 18.19.35 |
|
||||
| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.19.35 |
|
||||
| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.19.35 |
|
||||
| `hide-watermark` | Hides creator's watermarks on videos. | 18.19.35 |
|
||||
| `minimized-playback` | Enables minimized and background playback. | 18.19.35 |
|
||||
| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.19.35 |
|
||||
| `old-quality-layout` | Enables the original video quality flyout in the video player settings. | 18.19.35 |
|
||||
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
|
||||
| `premium-heading` | Shows premium branding on the home screen. | all |
|
||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.16.37 |
|
||||
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.16.37 |
|
||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.16.37 |
|
||||
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.16.37 |
|
||||
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.16.37 |
|
||||
| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.16.37 |
|
||||
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.16.37 |
|
||||
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.16.37 |
|
||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
|
||||
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.19.35 |
|
||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.19.35 |
|
||||
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.19.35 |
|
||||
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.19.35 |
|
||||
| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.19.35 |
|
||||
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.19.35 |
|
||||
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.19.35 |
|
||||
| `theme` | Applies a custom theme. | all |
|
||||
| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.16.37 |
|
||||
| `video-ads` | Removes ads in the video player. | 18.16.37 |
|
||||
| `video-speed` | Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout. | 18.16.37 |
|
||||
| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.16.37 |
|
||||
| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.19.35 |
|
||||
| `video-ads` | Removes ads in the video player. | 18.19.35 |
|
||||
| `video-speed` | Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout. | 18.19.35 |
|
||||
| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.19.35 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music)
|
||||
@@ -140,6 +141,17 @@ The official ReVanced Patches.
|
||||
| `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `hide-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
|
||||
| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | all |
|
||||
| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
|
||||
| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
|
||||
<details>
|
||||
|
||||
@@ -160,16 +172,6 @@ The official ReVanced Patches.
|
||||
| `hide-inbox-ads` | Hides ads in inbox. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | 2023.12.0 |
|
||||
| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | 2023.12.0 |
|
||||
| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
|
||||
<details>
|
||||
|
||||
@@ -340,6 +342,14 @@ The official ReVanced Patches.
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
|
||||
<details>
|
||||
|
||||
@@ -372,6 +382,14 @@ The official ReVanced Patches.
|
||||
| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.vsco.cam`](https://play.google.com/store/apps/details?id=com.vsco.cam)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
|
||||
<details>
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
kotlin.code.style = official
|
||||
version = 2.174.0-dev.32
|
||||
version = 2.174.0-dev.39
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,11 +1,15 @@
|
||||
package app.revanced.extensions
|
||||
|
||||
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.Method
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import org.jf.dexlib2.util.MethodUtil
|
||||
import org.w3c.dom.Node
|
||||
|
||||
@@ -15,7 +19,7 @@ import org.w3c.dom.Node
|
||||
*
|
||||
* @return A [PatchResultError] for the [MethodFingerprint].
|
||||
*/
|
||||
fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
|
||||
internal fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
|
||||
|
||||
/**
|
||||
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
|
||||
@@ -23,7 +27,7 @@ fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $nam
|
||||
* @param method The [Method] to find.
|
||||
* @return The [MutableMethod].
|
||||
*/
|
||||
fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
|
||||
internal fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
|
||||
MethodUtil.methodSignaturesMatch(it, method)
|
||||
}
|
||||
|
||||
@@ -32,7 +36,7 @@ fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
|
||||
*
|
||||
* @param transform the transformation function. original method goes in, transformed method goes out
|
||||
*/
|
||||
fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
|
||||
internal fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
|
||||
val transformedMethods = methods.map { it.transform() }
|
||||
methods.clear()
|
||||
methods.addAll(transformedMethods)
|
||||
@@ -41,4 +45,29 @@ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod)
|
||||
internal fun Node.doRecursively(action: (Node) -> Unit) {
|
||||
action(this)
|
||||
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
|
||||
}
|
||||
|
||||
internal fun MutableMethod.injectHideViewCall(
|
||||
insertIndex: Int,
|
||||
viewRegister: Int,
|
||||
classDescriptor: String,
|
||||
targetMethod: String
|
||||
) = addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V"
|
||||
)
|
||||
|
||||
internal fun MutableMethod.findIndexForIdResource(resourceName: String): Int {
|
||||
fun getIdResourceId(resourceName: String) = ResourceMappingPatch.resourceMappings.single {
|
||||
it.type == "id" && it.name == resourceName
|
||||
}.id
|
||||
|
||||
val resourceId = getIdResourceId(resourceName)
|
||||
return implementation!!.instructions.indexOfFirst {
|
||||
if (it.opcode != Opcode.CONST) return@indexOfFirst false
|
||||
|
||||
val literal = (it as WideLiteralInstruction).wideLiteral
|
||||
|
||||
return@indexOfFirst resourceId == literal
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,7 @@ import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.reddit.frontpage", arrayOf(
|
||||
"2023.05.0",
|
||||
"2023.06.0",
|
||||
"2023.07.0",
|
||||
"2023.07.1",
|
||||
"2023.08.0",
|
||||
"2023.09.0",
|
||||
"2023.09.1",
|
||||
"2023.10.0",
|
||||
"2023.11.0",
|
||||
"2023.12.0"
|
||||
)
|
||||
"com.reddit.frontpage"
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package app.revanced.patches.reddit.ad.general.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.reddit.frontpage", arrayOf(
|
||||
"2021.45.0",
|
||||
"2022.43.0",
|
||||
"2023.05.0",
|
||||
"2023.06.0",
|
||||
"2023.07.0",
|
||||
"2023.07.1",
|
||||
"2023.08.0",
|
||||
"2023.09.0",
|
||||
"2023.09.1",
|
||||
"2023.10.0",
|
||||
"2023.11.0",
|
||||
"2023.12.0"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class GeneralAdsCompatibility
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.reddit.ad.general.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.reddit.frontpage"
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideAdsCompatibility
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.reddit.ad.general.annotations.GeneralAdsCompatibility
|
||||
import app.revanced.patches.reddit.ad.general.annotations.HideAdsCompatibility
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
@@ -16,11 +16,11 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
||||
|
||||
@Patch
|
||||
@Name("general-reddit-ads")
|
||||
@Name("hide-ads")
|
||||
@Description("Removes general ads from the Reddit frontpage and subreddits.")
|
||||
@GeneralAdsCompatibility
|
||||
@HideAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class GeneralAdsPatch : BytecodePatch() {
|
||||
class HideAdsPatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
context.classes.forEach { classDef ->
|
||||
classDef.methods.forEach methodLoop@{ method ->
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.reddit.misc.tracking.url.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.reddit.frontpage"
|
||||
)]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SanitizeUrlQueryCompatibility
|
||||
@@ -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;") }
|
||||
)
|
||||
@@ -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;"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -13,7 +13,7 @@ import app.revanced.patches.shared.misc.fix.verticalscroll.annotations.VerticalS
|
||||
import app.revanced.patches.shared.misc.fix.verticalscroll.fingerprints.CanScrollVerticallyFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Description("Fixes issues with scrolling on the home screen when the first component is of type EmptyComponent.")
|
||||
@Description("Fixes issues with refreshing the feed when the first component is of type EmptyComponent.")
|
||||
@VerticalScrollCompatibility
|
||||
@Version("0.0.1")
|
||||
class VerticalScrollPatch : BytecodePatch(
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.trakt.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("tv.trakt.trakt")])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class UnlockProCompatibility
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.trakt.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object IsVIPEPFingerprint : MethodFingerprint(
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
if (!methodDef.definingClass.endsWith("RealmUserSettings;")) return@custom false
|
||||
|
||||
methodDef.name == "isVIPEP"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.trakt.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object IsVIPFingerprint : MethodFingerprint(
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
if (!methodDef.definingClass.endsWith("RealmUserSettings;")) return@custom false
|
||||
|
||||
methodDef.name == "isVIP"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.trakt.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object RealmUserSettingsFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("RealmUserSettings;")
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
package app.revanced.patches.trakt.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.trakt.annotations.UnlockProCompatibility
|
||||
import app.revanced.patches.trakt.fingerprints.IsVIPEPFingerprint
|
||||
import app.revanced.patches.trakt.fingerprints.IsVIPFingerprint
|
||||
import app.revanced.patches.trakt.fingerprints.RealmUserSettingsFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("unlock-pro")
|
||||
@Description("Unlocks pro features.")
|
||||
@UnlockProCompatibility
|
||||
@Version("0.0.1")
|
||||
class UnlockProPatch : BytecodePatch(
|
||||
listOf(RealmUserSettingsFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
RealmUserSettingsFingerprint.result?.classDef?.let { realUserSettingsClass ->
|
||||
arrayOf(IsVIPFingerprint, IsVIPEPFingerprint).onEach { fingerprint ->
|
||||
// Resolve both fingerprints on the same class.
|
||||
if (!fingerprint.resolve(context, realUserSettingsClass))
|
||||
throw fingerprint.toErrorResult()
|
||||
}.forEach { fingerprint ->
|
||||
// Return true for both VIP check methods.
|
||||
fingerprint.result?.mutableMethod?.addInstructions(0, RETURN_TRUE_INSTRUCTIONS)
|
||||
?: return fingerprint.toErrorResult()
|
||||
}
|
||||
} ?: return RealmUserSettingsFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val RETURN_TRUE_INSTRUCTIONS =
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
invoke-static {v0}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
|
||||
move-result-object v1
|
||||
return-object v1
|
||||
"""
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,9 @@ import org.jf.dexlib2.Opcode
|
||||
|
||||
object JsonHookPatchFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ -> methodDef.name == "<clinit>" },
|
||||
opcodes = listOf(Opcode.IGET_OBJECT)
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_INTERFACE, // Add dummy hook to hooks list.
|
||||
// Add hooks to the hooks list.
|
||||
Opcode.INVOKE_STATIC // Call buildList.
|
||||
)
|
||||
)
|
||||
@@ -5,13 +5,18 @@ import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.RequiresIntegrations
|
||||
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonHookPatchFingerprint
|
||||
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonInputStreamFingerprint
|
||||
import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint
|
||||
import java.io.Closeable
|
||||
import java.io.InvalidClassException
|
||||
|
||||
@Name("json-hook")
|
||||
@@ -20,16 +25,16 @@ import java.io.InvalidClassException
|
||||
@RequiresIntegrations
|
||||
class JsonHookPatch : BytecodePatch(
|
||||
listOf(LoganSquareFingerprint)
|
||||
) {
|
||||
), Closeable {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
// Make sure the integrations are present.
|
||||
val jsonHookPatch = context.findClass { it.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
|
||||
?: return PatchResultError("Could not find integrations.")
|
||||
JsonHookPatchFingerprint.also {
|
||||
// Make sure the integrations are present.
|
||||
val jsonHookPatch = context.findClass { classDef -> classDef.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
|
||||
?: throw PatchResultError("Could not find integrations.")
|
||||
|
||||
// Allow patch to inject hooks into the patches integrations.
|
||||
jsonHookPatchFingerprintResult = JsonHookPatchFingerprint.also {
|
||||
it.resolve(context, jsonHookPatch.immutableClass)
|
||||
}.result ?: return PatchResultError("Unexpected integrations.")
|
||||
if (!it.resolve(context, jsonHookPatch.immutableClass))
|
||||
throw PatchResultError("Unexpected integrations.")
|
||||
}.let { hooks = JsonHookPatchHook(it) }
|
||||
|
||||
// Conveniently find the type to hook a method in, via a named field.
|
||||
val jsonFactory = LoganSquareFingerprint.result
|
||||
@@ -64,30 +69,10 @@ class JsonHookPatch : BytecodePatch(
|
||||
*
|
||||
* @param context The [BytecodeContext] of the current patch.
|
||||
* @param descriptor The class descriptor of the hook.
|
||||
* @throws ClassNotFoundException If the class could not be found.
|
||||
*/
|
||||
internal class Hook(context: BytecodeContext, private val descriptor: String) {
|
||||
private var added = false
|
||||
|
||||
/**
|
||||
* Add the hook.
|
||||
*/
|
||||
internal fun add() {
|
||||
if (added) return
|
||||
|
||||
jsonHookPatchFingerprintResult.apply {
|
||||
mutableMethod.apply {
|
||||
addInstructions(
|
||||
scanResult.patternScanResult!!.startIndex,
|
||||
"""
|
||||
sget-object v1, $descriptor->INSTANCE:$descriptor
|
||||
invoke-virtual {v0, v1}, Lkotlin/collections/builders/ListBuilder;->add(Ljava/lang/Object;)Z
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
added = true
|
||||
}
|
||||
internal class Hook(context: BytecodeContext, internal val descriptor: String) {
|
||||
internal var added = false
|
||||
|
||||
init {
|
||||
context.findClass { it.type == descriptor }?.let {
|
||||
@@ -102,15 +87,67 @@ class JsonHookPatch : BytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
|
||||
/**
|
||||
* A hook for the [JsonHookPatch].
|
||||
*
|
||||
* @param jsonHookPatchFingerprint The [JsonHookPatchFingerprint] to hook.
|
||||
*/
|
||||
internal class JsonHookPatchHook(jsonHookPatchFingerprint: MethodFingerprint): Closeable {
|
||||
private val jsonHookPatchFingerprintResult = jsonHookPatchFingerprint.result!!
|
||||
private val jsonHookPatchIndex = jsonHookPatchFingerprintResult.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
|
||||
/**
|
||||
* Add a hook to the [JsonHookPatch].
|
||||
* Will not add the hook if it's already added.
|
||||
*
|
||||
* @param hook The [Hook] to add.
|
||||
*/
|
||||
fun addHook(hook: Hook) {
|
||||
if (hook.added) return
|
||||
|
||||
const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
|
||||
jsonHookPatchFingerprintResult.mutableMethod.apply {
|
||||
// Insert hooks right before calling buildList.
|
||||
val insertIndex = jsonHookPatchIndex
|
||||
|
||||
const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
sget-object v1, ${hook.descriptor}->INSTANCE:${hook.descriptor}
|
||||
invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private lateinit var jsonHookPatchFingerprintResult: MethodFingerprintResult
|
||||
hook.added = true
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
// Remove hooks.add(dummyHook).
|
||||
jsonHookPatchFingerprintResult.mutableMethod.apply {
|
||||
val addDummyHookIndex = jsonHookPatchIndex - 2
|
||||
|
||||
removeInstructions(addDummyHookIndex, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() = hooks.close()
|
||||
|
||||
internal companion object {
|
||||
private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
|
||||
|
||||
private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
|
||||
|
||||
private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
|
||||
|
||||
private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
|
||||
|
||||
/**
|
||||
* The [JsonHookPatchHook] of the [JsonHookPatch].
|
||||
*
|
||||
* @see JsonHookPatchHook
|
||||
*/
|
||||
internal lateinit var hooks: JsonHookPatchHook
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,13 +4,13 @@ import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
|
||||
|
||||
@DependsOn([JsonHookPatch::class])
|
||||
abstract class BaseHookPatchPatch(private val hookClassDescriptor: String) : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) = try {
|
||||
PatchResultSuccess().also { JsonHookPatch.Hook(context, hookClassDescriptor).add() }
|
||||
JsonHookPatch.hooks.addHook(JsonHookPatch.Hook(context, hookClassDescriptor))
|
||||
|
||||
PatchResultSuccess()
|
||||
} catch (ex: Exception) {
|
||||
PatchResultError(ex)
|
||||
}
|
||||
|
||||
@@ -15,8 +15,4 @@ import app.revanced.patches.twitter.misc.hook.patch.ads.annotations.HideAdsCompa
|
||||
@Description("Hides ads.")
|
||||
@HideAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideAdsPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) {
|
||||
private companion object {
|
||||
const val HOOK_CLASS_DESCRIPTOR = "Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;"
|
||||
}
|
||||
}
|
||||
class HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
|
||||
@@ -15,9 +15,6 @@ import app.revanced.patches.twitter.misc.hook.patch.recommendation.annotations.H
|
||||
@Description("Hides recommended users.")
|
||||
@HideRecommendedUsersCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideRecommendedUsersPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) {
|
||||
private companion object {
|
||||
const val HOOK_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
|
||||
}
|
||||
}
|
||||
class HideRecommendedUsersPatch : BaseHookPatchPatch(
|
||||
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
|
||||
)
|
||||
@@ -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;")
|
||||
}
|
||||
)
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
@@ -1,47 +1,32 @@
|
||||
package app.revanced.patches.youtube.ad.general.bytecode.patch
|
||||
|
||||
import app.revanced.extensions.findMutableMethodOf
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.extensions.injectHideViewCall
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.instruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
|
||||
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
|
||||
import app.revanced.patches.youtube.ad.general.bytecode.fingerprints.ReelConstructorFingerprint
|
||||
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch
|
||||
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
|
||||
import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
|
||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
|
||||
@Patch
|
||||
@DependsOn([GeneralAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
|
||||
@Name("general-ads")
|
||||
@DependsOn([HideAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
|
||||
@Name("hide-ads")
|
||||
@Description("Removes general ads.")
|
||||
@GeneralAdsCompatibility
|
||||
@HideAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class GeneralAdsPatch : BytecodePatch(
|
||||
listOf(ReelConstructorFingerprint)
|
||||
) {
|
||||
class HideAdsPatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
fun String.buildHideCall(viewRegister: Int) = "invoke-static { v$viewRegister }, " +
|
||||
"Lapp/revanced/integrations/patches/GeneralAdsPatch;" +
|
||||
"->" +
|
||||
"$this(Landroid/view/View;)V"
|
||||
|
||||
fun MutableMethod.injectHideCall(insertIndex: Int, viewRegister: Int, method: String) =
|
||||
this.addInstruction(insertIndex, method.buildHideCall(viewRegister))
|
||||
|
||||
context.classes.forEach { classDef ->
|
||||
classDef.methods.forEach { method ->
|
||||
with(method.implementation) {
|
||||
@@ -49,7 +34,7 @@ class GeneralAdsPatch : BytecodePatch(
|
||||
if (instruction.opcode != org.jf.dexlib2.Opcode.CONST)
|
||||
return@forEachIndexed
|
||||
// Instruction to store the id adAttribution into a register
|
||||
if ((instruction as Instruction31i).wideLiteral != GeneralAdsResourcePatch.adAttributionId)
|
||||
if ((instruction as Instruction31i).wideLiteral != HideAdsResourcePatch.adAttributionId)
|
||||
return@forEachIndexed
|
||||
|
||||
val insertIndex = index + 1
|
||||
@@ -64,25 +49,18 @@ class GeneralAdsPatch : BytecodePatch(
|
||||
context.proxy(classDef)
|
||||
.mutableClass
|
||||
.findMutableMethodOf(method)
|
||||
.injectHideCall(insertIndex, viewRegister, "hideAdAttributionView")
|
||||
.injectHideViewCall(
|
||||
insertIndex,
|
||||
viewRegister,
|
||||
"Lapp/revanced/integrations/patches/components/AdsFilter;",
|
||||
"hideAdAttributionView"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReelConstructorFingerprint.result?.let {
|
||||
// iput-object v$viewRegister, ...
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val viewRegister = instruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
injectHideCall(insertIndex, viewRegister, "hideReelView")
|
||||
}
|
||||
} ?: return ReelConstructorFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.*
|
||||
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
|
||||
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
|
||||
@@ -20,13 +20,9 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.P
|
||||
ResourceMappingPatch::class
|
||||
]
|
||||
)
|
||||
@GeneralAdsCompatibility
|
||||
@HideAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class GeneralAdsResourcePatch : ResourcePatch {
|
||||
internal companion object {
|
||||
var adAttributionId: Long = -1
|
||||
var reelMultipleItemShelfId: Long = -1
|
||||
}
|
||||
class HideAdsResourcePatch : ResourcePatch {
|
||||
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
PreferenceScreen.LAYOUT.addPreferences(
|
||||
@@ -105,12 +101,6 @@ class GeneralAdsResourcePatch : ResourcePatch {
|
||||
StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
|
||||
StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_shorts",
|
||||
StringResource("revanced_hide_shorts_title", "Hide shorts"),
|
||||
StringResource("revanced_hide_shorts_summary_on", "Shorts are hidden"),
|
||||
StringResource("revanced_hide_shorts_summary_off", "Shorts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_community_guidelines",
|
||||
StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
|
||||
@@ -263,11 +253,12 @@ class GeneralAdsResourcePatch : ResourcePatch {
|
||||
)
|
||||
)
|
||||
|
||||
fun String.getId() = ResourceMappingPatch.resourceMappings.single { it.name == this }.id
|
||||
|
||||
adAttributionId = "ad_attribution".getId()
|
||||
reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
|
||||
adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
var adAttributionId: Long = -1
|
||||
}
|
||||
}
|
||||
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.ad.video.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class VideoAdsCompatibility
|
||||
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.interaction.copyvideourl.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class CopyVideoUrlCompatibility
|
||||
@@ -26,8 +26,7 @@ import app.revanced.patches.youtube.video.information.patch.VideoInformationPatc
|
||||
@Version("0.0.1")
|
||||
class CopyVideoUrlBytecodePatch : BytecodePatch() {
|
||||
private companion object {
|
||||
const val INTEGRATIONS_PACKAGE = "Lapp/revanced/integrations"
|
||||
const val INTEGRATIONS_PLAYER_PACKAGE = "$INTEGRATIONS_PACKAGE/videoplayer"
|
||||
const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
|
||||
val BUTTONS_DESCRIPTORS = listOf(
|
||||
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
|
||||
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
|
||||
@@ -38,10 +37,8 @@ class CopyVideoUrlBytecodePatch : BytecodePatch() {
|
||||
|
||||
// Initialize buttons and inject visibility control
|
||||
BUTTONS_DESCRIPTORS.forEach { descriptor ->
|
||||
val initializeButtonDescriptor = "$descriptor->initializeButton(Ljava/lang/Object;)V"
|
||||
val visibilityDescriptor = "$descriptor->changeVisibility(Z)V"
|
||||
PlayerControlsBytecodePatch.initializeControl(initializeButtonDescriptor)
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(visibilityDescriptor)
|
||||
PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
|
||||
@@ -14,6 +14,7 @@ import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomCon
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.util.resources.ResourceUtils
|
||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||
import app.revanced.util.resources.ResourceUtils.mergeStrings
|
||||
|
||||
@Name("copy-video-url-resource")
|
||||
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
|
||||
@@ -28,13 +29,13 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
|
||||
SwitchPreference(
|
||||
"revanced_copy_video_url",
|
||||
StringResource("revanced_copy_video_url_title", "Show copy video URL button"),
|
||||
StringResource("revanced_copy_video_url_summary_on", "Button is shown, click to copy video URL without timestamp"),
|
||||
StringResource("revanced_copy_video_url_summary_on", "Button is shown. Tap to copy video URL. Tap and hold to copy video URL with timestamp"),
|
||||
StringResource("revanced_copy_video_url_summary_off", "Button is not shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_copy_video_url_timestamp",
|
||||
StringResource("revanced_copy_video_url_timestamp_title", "Show copy timestamp URL button"),
|
||||
StringResource("revanced_copy_video_url_timestamp_summary_on", "Button is shown, click to copy video URL with timestamp"),
|
||||
StringResource("revanced_copy_video_url_timestamp_summary_on", "Button is shown. Tap to copy video URL with timestamp. Tap and hold to copy video without timestamp"),
|
||||
StringResource("revanced_copy_video_url_timestamp_summary_off", "Button is not shown")
|
||||
)
|
||||
),
|
||||
@@ -48,6 +49,9 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
|
||||
"revanced_yt_copy_timestamp.xml"
|
||||
))
|
||||
|
||||
// merge strings
|
||||
context.mergeStrings("copyvideourl/host/values/strings.xml")
|
||||
|
||||
BottomControlsResourcePatch.addControls("copyvideourl/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
|
||||
|
||||
return PatchResultSuccess()
|
||||
|
||||
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.interaction.downloads.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class DownloadsCompatibility
|
||||
|
||||
|
||||
@@ -21,23 +21,24 @@ import app.revanced.patches.youtube.video.information.patch.VideoInformationPatc
|
||||
@DownloadsCompatibility
|
||||
@Version("0.0.1")
|
||||
class DownloadsBytecodePatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
val integrationsPackage = "app/revanced/integrations"
|
||||
val classDescriptor = "L$integrationsPackage/videoplayer/DownloadButton;"
|
||||
private companion object {
|
||||
const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/DownloadButton;"
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
/*
|
||||
initialize the control
|
||||
*/
|
||||
|
||||
val initializeDownloadsDescriptor = "$classDescriptor->initializeButton(Ljava/lang/Object;)V"
|
||||
PlayerControlsBytecodePatch.initializeControl(initializeDownloadsDescriptor)
|
||||
PlayerControlsBytecodePatch.initializeControl(
|
||||
"$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
|
||||
|
||||
/*
|
||||
add code to change the visibility of the control
|
||||
*/
|
||||
|
||||
val changeVisibilityDescriptor = "$classDescriptor->changeVisibility(Z)V"
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(changeVisibilityDescriptor)
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(
|
||||
"$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.interaction.seekbar.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SeekbarTappingCompatibility
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
@@ -1,34 +1,34 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
|
||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||
object SeekbarTappingFingerprint : MethodFingerprint(
|
||||
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_WIDE,
|
||||
Opcode.IGET,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.DIV_INT_2ADDR,
|
||||
Opcode.ADD_INT,
|
||||
Opcode.SUB_INT_2ADDR,
|
||||
Opcode.INT_TO_FLOAT,
|
||||
Opcode.CMPG_FLOAT,
|
||||
Opcode.IF_GTZ,
|
||||
Opcode.INT_TO_FLOAT,
|
||||
Opcode.CMPG_FLOAT,
|
||||
Opcode.IF_GTZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
returnType = "Z",
|
||||
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
// Insert seekbar tapping instructions here.
|
||||
Opcode.RETURN,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
),
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
if (methodDef.name != "onTouchEvent") return@custom false
|
||||
|
||||
methodDef.implementation!!.instructions.any { instruction ->
|
||||
if (instruction.opcode != Opcode.CONST) return@any false
|
||||
|
||||
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
|
||||
|
||||
// onTouchEvent method contains a CONST instruction
|
||||
// with this literal making it unique with the rest of the properties of this fingerprint.
|
||||
literal == Integer.MAX_VALUE
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
@@ -1,109 +1,95 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.instruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.AccessibilityPlayerProgressTimeFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import org.jf.dexlib2.iface.Method
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction11n
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
|
||||
@Name("seekbar-tapping")
|
||||
@Description("Enables tap-to-seek on the seekbar of the video player.")
|
||||
@SeekbarTappingCompatibility
|
||||
@Version("0.0.1")
|
||||
class EnableSeekbarTappingPatch : BytecodePatch(
|
||||
listOf(
|
||||
SeekbarTappingParentFingerprint, SeekbarTappingFingerprint
|
||||
)
|
||||
listOf(AccessibilityPlayerProgressTimeFingerprint, SeekbarTappingFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_tap_seeking",
|
||||
StringResource("revanced_tap_seeking_title", "Enable seekbar tapping"),
|
||||
StringResource("revanced_tap_seeking_summary_on", "Seekbar tapping is enabled"),
|
||||
StringResource("revanced_tap_seeking_summary_off", "Seekbar tapping is disabled")
|
||||
)
|
||||
)
|
||||
// Find the required methods to tap the seekbar.
|
||||
val seekbarTappingMethods =
|
||||
AccessibilityPlayerProgressTimeFingerprint.result?.classDef?.methods?.let { methods ->
|
||||
buildMap {
|
||||
// find the methods which tap the seekbar
|
||||
methods.forEach { method ->
|
||||
if (method.implementation == null) return@forEach
|
||||
|
||||
var result = SeekbarTappingParentFingerprint.result!!
|
||||
val instructions = method.implementation!!.instructions
|
||||
|
||||
val tapSeekMethods = mutableMapOf<String, Method>()
|
||||
// The method has more than 7 instructions.
|
||||
if (instructions.count() < 7) return@forEach
|
||||
|
||||
// find the methods which tap the seekbar
|
||||
for (it in result.classDef.methods) {
|
||||
if (it.implementation == null) continue
|
||||
// The 7th instruction has the opcode CONST_4.
|
||||
val instruction = instructions.elementAt(6)
|
||||
if (instruction.opcode != Opcode.CONST_4) return@forEach
|
||||
|
||||
val instructions = it.implementation!!.instructions
|
||||
// here we make sure we actually find the method because it has more than 7 instructions
|
||||
if (instructions.count() < 7) continue
|
||||
// the literal for this instruction has to be either 1 or 2.
|
||||
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
|
||||
|
||||
// we know that the 7th instruction has the opcode CONST_4
|
||||
val instruction = instructions.elementAt(6)
|
||||
if (instruction.opcode != Opcode.CONST_4) continue
|
||||
// Based on the literal, determine which method is which.
|
||||
if (literal == 1) this["P"] = method
|
||||
if (literal == 2) this["O"] = method
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the literal for this instruction has to be either 1 or 2
|
||||
val literal = (instruction as Instruction11n).narrowLiteral
|
||||
seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
|
||||
|
||||
// method founds
|
||||
if (literal == 1) tapSeekMethods["P"] = it
|
||||
if (literal == 2) tapSeekMethods["O"] = it
|
||||
}
|
||||
SeekbarTappingFingerprint.result?.let {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
|
||||
|
||||
// replace map because we don't need the upper one anymore
|
||||
result = SeekbarTappingFingerprint.result!!
|
||||
it.mutableMethod.apply {
|
||||
val thisInstanceRegister = instruction<Instruction35c>(insertIndex - 1).registerC
|
||||
|
||||
val implementation = result.mutableMethod.implementation!!
|
||||
val freeRegister = 0
|
||||
val xAxisRegister = 2
|
||||
|
||||
// if tap-seeking is enabled, do not invoke the two methods below
|
||||
val pMethod = tapSeekMethods["P"]!!
|
||||
val oMethod = tapSeekMethods["O"]!!
|
||||
val pMethod = seekbarTappingMethods["P"]!!
|
||||
val oMethod = seekbarTappingMethods["O"]!!
|
||||
|
||||
val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
|
||||
fun Method.toInvokeInstructionString() =
|
||||
"invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $definingClass->$name(I)V"
|
||||
|
||||
// get the required register
|
||||
val instruction = implementation.instructions[insertIndex - 1]
|
||||
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register")
|
||||
val register = (instruction as Instruction35c).registerC
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
${oMethod.toInvokeInstructionString()}
|
||||
${pMethod.toInvokeInstructionString()}
|
||||
""",
|
||||
listOf(ExternalLabel("disabled", instruction(insertIndex)))
|
||||
)
|
||||
}
|
||||
} ?: return SeekbarTappingFingerprint.toErrorResult()
|
||||
|
||||
val elseLabel = implementation.newLabelForIndex(insertIndex)
|
||||
// the instructions are written in reverse order.
|
||||
result.mutableMethod.addInstructions(
|
||||
insertIndex, """
|
||||
invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
|
||||
invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
|
||||
"""
|
||||
)
|
||||
|
||||
// if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
|
||||
implementation.addInstruction(
|
||||
insertIndex, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
|
||||
)
|
||||
result.mutableMethod.addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->isTapSeekingEnabled()Z
|
||||
move-result v0
|
||||
"""
|
||||
)
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.interaction.swipecontrols.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SwipeControlsCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.autocaptions.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AutoCaptionsCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.action.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideButtonsCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.autoplay.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AutoplayButtonCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.captions.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideCaptionsButtonCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.navigation.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class NavigationButtonsCompatibility
|
||||
@@ -2,22 +2,6 @@ package app.revanced.patches.youtube.layout.buttons.player.background.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerButtonBackgroundCompatibility
|
||||
|
||||
@@ -3,10 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.player.hide.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf()
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HidePlayerButtonsCompatibility
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.albumcards.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AlbumCardsCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.artistcards.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideArtistCardCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.breakingnews.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class BreakingNewsCompatibility
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.youtube.layout.hide.comments.resource.patch
|
||||
package app.revanced.patches.youtube.layout.hide.comments.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
@@ -7,22 +8,21 @@ import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.layout.hide.comments.annotations.CommentsCompatibility
|
||||
import app.revanced.patches.youtube.layout.hide.comments.annotations.HideCommentsCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@Name("comments-resource-patch")
|
||||
@CommentsCompatibility
|
||||
@Patch
|
||||
@Name("comments")
|
||||
@Description("Hides components related to comments.")
|
||||
@HideCommentsCompatibility
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@Version("0.0.1")
|
||||
class CommentsResourcePatch : ResourcePatch {
|
||||
companion object {
|
||||
internal var shortsCommentsButtonId: Long = -1
|
||||
}
|
||||
|
||||
class CommentsPatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
PreferenceScreen(
|
||||
@@ -40,22 +40,12 @@ class CommentsResourcePatch : ResourcePatch {
|
||||
StringResource("revanced_hide_preview_comment_title", "Hide preview comment"),
|
||||
StringResource("revanced_hide_preview_comment_on", "Preview comment is hidden"),
|
||||
StringResource("revanced_hide_preview_comment_off", "Preview comment is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_shorts_comments_button",
|
||||
StringResource("revanced_hide_shorts_comments_button_title", "Hide shorts comments button"),
|
||||
StringResource("revanced_hide_shorts_comments_button_on", "Shorts comments button is hidden"),
|
||||
StringResource("revanced_hide_shorts_comments_button_off", "Shorts comments button is shown")
|
||||
),
|
||||
)
|
||||
),
|
||||
StringResource("revanced_comments_preference_screen_summary", "Manage the visibility of comments section components")
|
||||
)
|
||||
)
|
||||
|
||||
shortsCommentsButtonId = ResourceMappingPatch.resourceMappings.single {
|
||||
it.type == "drawable" && it.name == "ic_right_comment_32c"
|
||||
}.id
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class CrowdfundingBoxCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.endscreencards.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideEndscreenCardsCompatibility
|
||||
|
||||
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.filterbar.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideFilterBar
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.floatingmicrophone.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideFloatingMicrophoneButtonCompatibility
|
||||
|
||||
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.getpremium.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideGetPremiumCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.infocards.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideInfocardsCompatibility
|
||||
|
||||
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideLoadMoreButtonCompatibility
|
||||
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.personalinformation.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideEmailAddressCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.seekbar.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideSeekbarCompatibility
|
||||
@@ -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
|
||||
@@ -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",
|
||||
),
|
||||
)
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
@@ -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,
|
||||
)
|
||||
)
|
||||
@@ -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")
|
||||
)
|
||||
@@ -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,
|
||||
)
|
||||
)
|
||||
@@ -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")
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.time.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideTimeCompatibility
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -12,7 +12,7 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.layout.hide.watchinvr.annotations.WatchinVRCompatibility
|
||||
import app.revanced.patches.youtube.layout.hide.watchinvr.annotations.WatchInVRCompatibility
|
||||
import app.revanced.patches.youtube.layout.hide.watchinvr.fingerprints.WatchInVRFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
@@ -21,7 +21,7 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("hide-watch-in-vr")
|
||||
@Description("Hides the option to watch in VR from the player settings flyout panel.")
|
||||
@WatchinVRCompatibility
|
||||
@WatchInVRCompatibility
|
||||
@Version("0.0.1")
|
||||
class WatchInVRPatch : BytecodePatch(
|
||||
listOf(
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.panels.fullscreen.remove.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class FullscreenPanelsCompatibility
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.panels.popup.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class PlayerPopupPanelsCompatibility
|
||||
|
||||
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class ReturnYouTubeDislikeCompatibility
|
||||
@@ -13,8 +13,7 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
|
||||
access = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_OBJECT, // available unused register
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16, // available unused register
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
|
||||
@@ -99,7 +99,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
|
||||
.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
val insertIndex = atomicReferenceStartIndex + 8
|
||||
val insertIndex = atomicReferenceStartIndex + 7
|
||||
|
||||
textComponentContextFingerprintResult.mutableMethod.apply {
|
||||
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
|
||||
@@ -111,7 +111,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
instruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB
|
||||
|
||||
val atomicReferenceRegister =
|
||||
instruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 5).registerC
|
||||
instruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 4).registerC
|
||||
|
||||
val moveCharSequenceInstruction = instruction<TwoRegisterInstruction>(insertIndex)
|
||||
val charSequenceRegister = moveCharSequenceInstruction.registerB
|
||||
|
||||
@@ -26,16 +26,11 @@ class ReturnYouTubeDislikeResourcePatch : ResourcePatch {
|
||||
}
|
||||
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
val youtubePackage = "com.google.android.youtube"
|
||||
SettingsPatch.addPreference(
|
||||
Preference(
|
||||
StringResource("revanced_ryd_settings_title", "Return YouTube Dislike"),
|
||||
StringResource("revanced_ryd_settings_summary", "Settings for Return YouTube Dislike"),
|
||||
Preference.Intent(
|
||||
youtubePackage,
|
||||
"ryd_settings",
|
||||
"com.google.android.libraries.social.licenses.LicenseActivity"
|
||||
)
|
||||
SettingsPatch.createReVancedSettingsIntent("ryd_settings")
|
||||
)
|
||||
)
|
||||
// merge strings
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.searchbar.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class WideSearchbarCompatibility
|
||||
@@ -3,8 +3,6 @@ package app.revanced.patches.youtube.layout.sponsorblock.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SponsorBlockCompatibility
|
||||
@@ -103,17 +103,18 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
val seekbarMethodInstructions = seekbarMethod.implementation!!.instructions
|
||||
|
||||
/*
|
||||
* Get the instance of the seekbar rectangle
|
||||
* Get left and right of seekbar rectangle
|
||||
*/
|
||||
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
|
||||
if (instruction.opcode != Opcode.MOVE_OBJECT_FROM16) continue
|
||||
seekbarMethod.addInstruction(
|
||||
index + 1,
|
||||
"invoke-static/range {p0 .. p0}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
|
||||
)
|
||||
break
|
||||
val moveRectangleToRegisterIndex = seekbarMethodInstructions.indexOfFirst {
|
||||
it.opcode == Opcode.MOVE_OBJECT_FROM16
|
||||
}
|
||||
|
||||
seekbarMethod.addInstruction(
|
||||
moveRectangleToRegisterIndex + 1,
|
||||
"invoke-static/range {p0 .. p0}, " +
|
||||
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
|
||||
)
|
||||
|
||||
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
|
||||
if (instruction.opcode != Opcode.INVOKE_STATIC) continue
|
||||
|
||||
@@ -125,38 +126,15 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
// set the thickness of the segment
|
||||
seekbarMethod.addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static {v${invokeInstruction.registerC}}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
|
||||
"invoke-static {v${invokeInstruction.registerC}}, " +
|
||||
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
/*
|
||||
* Set rectangle absolute left and right positions
|
||||
*/
|
||||
val drawRectangleInstructions = seekbarMethodInstructions.withIndex().filter { (_, instruction) ->
|
||||
instruction is ReferenceInstruction && (instruction.reference as? MethodReference)?.name == "drawRect"
|
||||
}.map { (index, instruction) -> // TODO: improve code
|
||||
index to (instruction as FiveRegisterInstruction).registerD
|
||||
}
|
||||
|
||||
val (indexRight, rectangleRightRegister) = drawRectangleInstructions[0]
|
||||
val (indexLeft, rectangleLeftRegister) = drawRectangleInstructions[3]
|
||||
|
||||
// order of operation is important here due to the code above which has to be improved
|
||||
// the reason for that is that we get the index, add instructions and then the offset would be wrong
|
||||
seekbarMethod.addInstruction(
|
||||
indexLeft + 1,
|
||||
"invoke-static {v$rectangleLeftRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V"
|
||||
)
|
||||
seekbarMethod.addInstruction(
|
||||
indexRight + 1,
|
||||
"invoke-static {v$rectangleRightRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V"
|
||||
)
|
||||
|
||||
/*
|
||||
* Draw segment
|
||||
*/
|
||||
|
||||
// Find the drawCircle call and draw the segment before it
|
||||
for (i in seekbarMethodInstructions.size - 1 downTo 0) {
|
||||
val invokeInstruction = seekbarMethodInstructions[i] as? ReferenceInstruction ?: continue
|
||||
|
||||
@@ -10,7 +10,6 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.Preference
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.util.resources.ResourceUtils
|
||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||
@@ -18,22 +17,16 @@ import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
||||
import app.revanced.util.resources.ResourceUtils.mergeStrings
|
||||
|
||||
@Name("sponsorblock-resource-patch")
|
||||
@SponsorBlockCompatibility
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@Version("0.0.1")
|
||||
class SponsorBlockResourcePatch : ResourcePatch {
|
||||
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
val youtubePackage = "com.google.android.youtube"
|
||||
SettingsPatch.addPreference(
|
||||
Preference(
|
||||
StringResource("sb_settings", "SponsorBlock"),
|
||||
StringResource("revanced_sponsorblock_settings_title", "SponsorBlock"),
|
||||
StringResource("revanced_sponsorblock_settings_summary", "SponsorBlock related settings"),
|
||||
Preference.Intent(
|
||||
youtubePackage,
|
||||
"sponsorblock_settings",
|
||||
"com.google.android.libraries.social.licenses.LicenseActivity"
|
||||
)
|
||||
SettingsPatch.createReVancedSettingsIntent("sponsorblock_settings")
|
||||
)
|
||||
)
|
||||
val classLoader = this.javaClass.classLoader
|
||||
|
||||
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.layout.spoofappversion.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SpoofAppVersionCompatibility
|
||||
|
||||
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.startupshortsreset.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class StartupShortsResetCompatibility
|
||||
|
||||
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.tabletminiplayer.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class TabletMiniPlayerCompatibility
|
||||
|
||||
@@ -8,8 +8,8 @@ import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
|
||||
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
|
||||
import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
|
||||
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
|
||||
|
||||
@Patch
|
||||
@Name("theme")
|
||||
@@ -45,5 +45,14 @@ class ThemeBytecodePatch : BytecodePatch() {
|
||||
description = "The background color of the light theme. Can be a hex color or a resource reference.",
|
||||
)
|
||||
)
|
||||
|
||||
var splashScreenBackgroundColor: String? by option(
|
||||
PatchOption.StringOption(
|
||||
key = "splashScreenBackgroundColor",
|
||||
default = "@android:color/black",
|
||||
title = "Background color for the splash screen",
|
||||
description = "The background color of the splash screen. Can be a hex color or a resource reference.",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package app.revanced.patches.youtube.layout.theme.resource
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.InputType
|
||||
@@ -9,9 +11,8 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
|
||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
|
||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.util.resources.ResourceUtils
|
||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@@ -29,35 +30,80 @@ class ThemeResourcePatch : ResourcePatch {
|
||||
),
|
||||
)
|
||||
|
||||
val darkThemeBackgroundColor = darkThemeBackgroundColor!!
|
||||
val lightThemeBackgroundColor = lightThemeBackgroundColor!!
|
||||
|
||||
// Edit theme colors via resources.
|
||||
context.xmlEditor["res/values/colors.xml"].use { editor ->
|
||||
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
for (i in 0 until resourcesNode.childNodes.length) {
|
||||
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
|
||||
val children = resourcesNode.childNodes
|
||||
for (i in 0 until children.length) {
|
||||
val node = children.item(i) as? Element ?: continue
|
||||
|
||||
node.textContent = when (node.getAttribute("name")) {
|
||||
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3",
|
||||
"yt_black4", "yt_status_bar_background_dark", "material_grey_850" -> darkThemeBackgroundColor
|
||||
?: continue
|
||||
|
||||
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
|
||||
"yt_white2", "yt_white3", "yt_white4",
|
||||
-> lightThemeBackgroundColor
|
||||
-> lightThemeBackgroundColor ?: continue
|
||||
|
||||
else -> continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the resource file to change the splash screen color.
|
||||
context.copyResources(
|
||||
"theme", ResourceUtils.ResourceGroup("values-night-v31", "styles.xml")
|
||||
)
|
||||
splashScreenBackgroundColor ?: return PatchResultSuccess()
|
||||
|
||||
// Edit splash screen background color for Android 11 and below.
|
||||
context.xmlEditor["res/values/styles.xml"].use {
|
||||
val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
val children = resourcesNode.childNodes
|
||||
for (i in 0 until children.length) {
|
||||
val node = children.item(i) as? Element ?: continue
|
||||
|
||||
if (node.tagName != "style") continue
|
||||
|
||||
val name = node.getAttribute("name")
|
||||
if (name != LAUNCHER_STYLE_NAME) continue
|
||||
|
||||
it.file.createElement("item").apply {
|
||||
setAttribute("name", "android:windowSplashScreenBackground")
|
||||
textContent = splashScreenBackgroundColor
|
||||
}.also(node::appendChild)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Edit splash screen background color for Android 12+.
|
||||
|
||||
// Add the splash screen background color to the colors.xml file.
|
||||
context.xmlEditor["res/values/colors.xml"].use {
|
||||
val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
it.file.createElement("color").apply {
|
||||
setAttribute("name", COLOR_NAME)
|
||||
setAttribute("category", "color")
|
||||
textContent = splashScreenBackgroundColor
|
||||
}.also(resourcesNode::appendChild)
|
||||
}
|
||||
|
||||
// Point to the splash screen background color.
|
||||
context.xmlEditor["res/drawable/quantum_launchscreen_youtube.xml"].use {
|
||||
val node = it.file.getElementsByTagName("layer-list").item(0) as Element
|
||||
|
||||
val backgroundColorItem = node.childNodes.item(1) as Element
|
||||
backgroundColorItem.apply {
|
||||
setAttribute("android:drawable", "@color/$COLOR_NAME")
|
||||
}
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
}
|
||||
private companion object {
|
||||
private const val LAUNCHER_STYLE_NAME = "Base.Theme.YouTube.Launcher"
|
||||
private const val COLOR_NAME = "splash_background_color"
|
||||
}
|
||||
}
|
||||
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.autorepeat.annotations
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37",
|
||||
"18.15.40",
|
||||
"18.16.37"
|
||||
)
|
||||
)]
|
||||
)
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class AutoRepeatCompatibility
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user