chore: merge branch dev
to main
(#2240)
This commit is contained in:
commit
a01e6cad69
125
CHANGELOG.md
125
CHANGELOG.md
|
@ -1,3 +1,128 @@
|
||||||
|
# [2.175.0-dev.16](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.15...v2.175.0-dev.16) (2023-05-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **spoof-wifi-connection:** use updated instruction indices ([#2199](https://github.com/revanced/revanced-patches/issues/2199)) ([76fb700](https://github.com/revanced/revanced-patches/commit/76fb700884dae5b71a57f9530fad9d4a98ba0af0))
|
||||||
|
|
||||||
|
# [2.175.0-dev.15](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.14...v2.175.0-dev.15) (2023-05-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/remember-video-quality:** fix typo in video resolutions ([#2323](https://github.com/revanced/revanced-patches/issues/2323)) ([a99cef8](https://github.com/revanced/revanced-patches/commit/a99cef87b40b67a5feb97999fb4f2925ea80b42e))
|
||||||
|
|
||||||
|
# [2.175.0-dev.14](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.13...v2.175.0-dev.14) (2023-05-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/theme:** use dynamic background color for custom splash screen ([#2319](https://github.com/revanced/revanced-patches/issues/2319)) ([28594f3](https://github.com/revanced/revanced-patches/commit/28594f3eeaf99fa32ee57214ebbc4342529c6694))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **tiktok:** remove compatibility version constraints ([#2306](https://github.com/revanced/revanced-patches/issues/2306)) ([a12c4bb](https://github.com/revanced/revanced-patches/commit/a12c4bb1610234d19b4ac86cd57bb09335566b68))
|
||||||
|
|
||||||
|
# [2.175.0-dev.13](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.12...v2.175.0-dev.13) (2023-05-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **settings:** sort setting preferences using lowercase ([#2312](https://github.com/revanced/revanced-patches/issues/2312)) ([2743a95](https://github.com/revanced/revanced-patches/commit/2743a95b417a6023799035e30631e7b3a68bcc45))
|
||||||
|
|
||||||
|
# [2.175.0-dev.12](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.11...v2.175.0-dev.12) (2023-05-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/integrations:** fix playback of embedded videos ([#2304](https://github.com/revanced/revanced-patches/issues/2304)) ([1dffbaf](https://github.com/revanced/revanced-patches/commit/1dffbaf0aa73f0f703516648d5cd935000fa2770))
|
||||||
|
|
||||||
|
# [2.175.0-dev.11](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.10...v2.175.0-dev.11) (2023-05-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **scbeasy:** add `remove-debugging-detection` patch ([#2287](https://github.com/revanced/revanced-patches/issues/2287)) ([53d91e3](https://github.com/revanced/revanced-patches/commit/53d91e32183663b0aa70994cc4e1d8ae5eb8c8e4))
|
||||||
|
|
||||||
|
# [2.175.0-dev.10](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.9...v2.175.0-dev.10) (2023-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **youtube/hide-shorts-components:** hide channel bar & sound button ([749c83d](https://github.com/revanced/revanced-patches/commit/749c83d068c2201ed6f29047d5428d1072924960))
|
||||||
|
* **youtube/navigation-buttons:** use a better preference screen title ([5d7772b](https://github.com/revanced/revanced-patches/commit/5d7772be942c72e05644eca3f68d2bd6b9762d26))
|
||||||
|
|
||||||
|
# [2.175.0-dev.9](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.8...v2.175.0-dev.9) (2023-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **youtube/hide-seekbar:** more fine grained hiding of seekbar ([#2252](https://github.com/revanced/revanced-patches/issues/2252)) ([0f07bf4](https://github.com/revanced/revanced-patches/commit/0f07bf467a4aa06c9bcdf60a2498d88eea8c1429))
|
||||||
|
|
||||||
|
# [2.175.0-dev.8](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.7...v2.175.0-dev.8) (2023-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **youtube/hide-shorts-components:** hide shorts info panel ([#2278](https://github.com/revanced/revanced-patches/issues/2278)) ([a5b323d](https://github.com/revanced/revanced-patches/commit/a5b323d1d9e5b175c93f0b29732eb1123b83bab7))
|
||||||
|
|
||||||
|
# [2.175.0-dev.7](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.6...v2.175.0-dev.7) (2023-05-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **remove-screen-capture-restriction:** remove app constraint ([#2260](https://github.com/revanced/revanced-patches/issues/2260)) ([49ce47c](https://github.com/revanced/revanced-patches/commit/49ce47c3eed6a1626674d0f60ae0fdbe349e804b))
|
||||||
|
|
||||||
|
# [2.175.0-dev.6](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.5...v2.175.0-dev.6) (2023-05-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/hide-shorts-components:** clarify settings switch ([#2276](https://github.com/revanced/revanced-patches/issues/2276)) ([3e6d052](https://github.com/revanced/revanced-patches/commit/3e6d0528b287ded401dacdcea698d4ec97b926ee))
|
||||||
|
|
||||||
|
# [2.175.0-dev.5](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.4...v2.175.0-dev.5) (2023-05-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **nfctoolsse:** add `unlock-pro` patch ([#2272](https://github.com/revanced/revanced-patches/issues/2272)) ([9789ad3](https://github.com/revanced/revanced-patches/commit/9789ad30ff82d9bb99e870dc8053775dc222a010))
|
||||||
|
|
||||||
|
# [2.175.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.3...v2.175.0-dev.4) (2023-05-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/downloads:** rename patch to `external-downloads` ([#2274](https://github.com/revanced/revanced-patches/issues/2274)) ([4480911](https://github.com/revanced/revanced-patches/commit/4480911e0b056f2148616a0c2af6b4ab7c482c3b))
|
||||||
|
|
||||||
|
# [2.175.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.2...v2.175.0-dev.3) (2023-05-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/hide-player-buttons:** fix previous/next button showing if previous video exists ([#2261](https://github.com/revanced/revanced-patches/issues/2261)) ([91d1aab](https://github.com/revanced/revanced-patches/commit/91d1aabd32be1607019bc443fb06284ca3343e9d))
|
||||||
|
|
||||||
|
# [2.175.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.175.0-dev.1...v2.175.0-dev.2) (2023-05-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/hide-info-cards:** fix hide-info-cards setting does not work ([#2246](https://github.com/revanced/revanced-patches/issues/2246)) ([72773ac](https://github.com/revanced/revanced-patches/commit/72773ac56987753fac6c0087d048b4378a3dd360))
|
||||||
|
|
||||||
|
# [2.175.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.174.1-dev.1...v2.175.0-dev.1) (2023-05-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **youtube/general-ads:** merge `hide-get-premium` patch into `general-ads` patch ([5195dd8](https://github.com/revanced/revanced-patches/commit/5195dd8936d63c482dbcb2cd0e7e9aab3c75954e))
|
||||||
|
|
||||||
|
## [2.174.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.174.0...v2.174.1-dev.1) (2023-05-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **youtube/remove-player-controls-background:** use correct patch name and description ([8732a84](https://github.com/revanced/revanced-patches/commit/8732a84422087fca7e9e1635a0b1d8d2cbf034f4))
|
||||||
|
|
||||||
# [2.174.0](https://github.com/revanced/revanced-patches/compare/v2.173.0...v2.174.0) (2023-05-24)
|
# [2.174.0](https://github.com/revanced/revanced-patches/compare/v2.173.0...v2.174.0) (2023-05-24)
|
||||||
|
|
||||||
|
|
||||||
|
|
56
README.md
56
README.md
|
@ -20,8 +20,8 @@ The official ReVanced Patches.
|
||||||
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 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-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
|
||||||
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
|
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
|
||||||
| `downloads` | Adds a download button to the YouTube video player. | 18.19.35 |
|
|
||||||
| `enable-debugging` | Adds debugging options. | all |
|
| `enable-debugging` | Adds debugging options. | all |
|
||||||
|
| `external-downloads` | Adds support to download and save YouTube videos using an external app. | 18.19.35 |
|
||||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
|
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
|
||||||
| `hide-ads` | Removes general ads. | 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-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
|
||||||
|
@ -35,7 +35,6 @@ The official ReVanced Patches.
|
||||||
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 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-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-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-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-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-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
|
||||||
|
@ -52,7 +51,7 @@ The official ReVanced Patches.
|
||||||
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
|
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
|
||||||
| `premium-heading` | Shows premium branding on the home screen. | all |
|
| `premium-heading` | Shows premium branding on the home screen. | all |
|
||||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
|
| `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 |
|
| `remove-player-controls-background` | Removes the background from the video player controls. | 18.19.35 |
|
||||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 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 |
|
| `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 |
|
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.19.35 |
|
||||||
|
@ -90,14 +89,14 @@ The official ReVanced Patches.
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `disable-login-requirement` | Do not force login. | all |
|
| `disable-login-requirement` | Do not force login. | all |
|
||||||
| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
|
| `downloads` | Removes download restrictions and changes the default path to download to. | all |
|
||||||
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
|
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | all |
|
||||||
| `fix-google-login` | Allows logging in with a Google account. | all |
|
| `fix-google-login` | Allows logging in with a Google account. | all |
|
||||||
| `hide-ads` | Removes ads from TikTok. | all |
|
| `hide-ads` | Removes ads from TikTok. | all |
|
||||||
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
||||||
| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
|
| `settings` | Adds ReVanced settings to TikTok. | all |
|
||||||
| `show-seekbar` | Shows progress bar for all video. | all |
|
| `show-seekbar` | Shows progress bar for all video. | all |
|
||||||
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
|
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### [📦 `com.zhiliaoapp.musically`](https://play.google.com/store/apps/details?id=com.zhiliaoapp.musically)
|
### [📦 `com.zhiliaoapp.musically`](https://play.google.com/store/apps/details?id=com.zhiliaoapp.musically)
|
||||||
|
@ -106,14 +105,14 @@ The official ReVanced Patches.
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `disable-login-requirement` | Do not force login. | all |
|
| `disable-login-requirement` | Do not force login. | all |
|
||||||
| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
|
| `downloads` | Removes download restrictions and changes the default path to download to. | all |
|
||||||
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
|
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | all |
|
||||||
| `fix-google-login` | Allows logging in with a Google account. | all |
|
| `fix-google-login` | Allows logging in with a Google account. | all |
|
||||||
| `hide-ads` | Removes ads from TikTok. | all |
|
| `hide-ads` | Removes ads from TikTok. | all |
|
||||||
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
||||||
| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
|
| `settings` | Adds ReVanced settings to TikTok. | all |
|
||||||
| `show-seekbar` | Shows progress bar for all video. | all |
|
| `show-seekbar` | Shows progress bar for all video. | all |
|
||||||
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
|
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### [📦 `tv.twitch.android.app`](https://play.google.com/store/apps/details?id=tv.twitch.android.app)
|
### [📦 `tv.twitch.android.app`](https://play.google.com/store/apps/details?id=tv.twitch.android.app)
|
||||||
|
@ -152,16 +151,6 @@ The official ReVanced Patches.
|
||||||
| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
|
| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
|
|
||||||
<details>
|
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|
||||||
| `disable-capture-restriction` | Allows capturing Spotify's audio output while screen sharing or screen recording. | all |
|
|
||||||
| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
|
|
||||||
| `spotify-theme` | Applies a custom theme. | all |
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
|
### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
|
@ -172,6 +161,15 @@ The official ReVanced Patches.
|
||||||
| `hide-inbox-ads` | Hides ads in inbox. | all |
|
| `hide-inbox-ads` | Hides ads in inbox. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
|
||||||
|
| `spotify-theme` | Applies a custom theme. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
|
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
|
@ -286,6 +284,14 @@ The official ReVanced Patches.
|
||||||
| `remove-broadcasts-restriction` | Enables starting/stopping NetGuard via broadcasts. | all |
|
| `remove-broadcasts-restriction` | Enables starting/stopping NetGuard via broadcasts. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.scb.phone`](https://play.google.com/store/apps/details?id=com.scb.phone)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `remove-debugging-detection` | Removes the USB and wireless debugging checks. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
|
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
|
@ -334,6 +340,14 @@ The official ReVanced Patches.
|
||||||
| `unlock-pro` | Unlocks all pro features. | all |
|
| `unlock-pro` | Unlocks all pro features. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.wakdev.apps.nfctools.se`](https://play.google.com/store/apps/details?id=com.wakdev.apps.nfctools.se)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `unlock-pro` | Unlocks all pro features. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
|
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 2.174.0
|
version = 2.175.0-dev.16
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,66 @@
|
||||||
|
package app.revanced.patches.all.screencapture.removerestriction.bytecode.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.annotations.RequiresIntegrations
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patches.all.screencapture.removerestriction.resource.patch.RemoveCaptureRestrictionResourcePatch
|
||||||
|
import app.revanced.util.patch.*
|
||||||
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
|
import org.jf.dexlib2.iface.Method
|
||||||
|
import org.jf.dexlib2.iface.instruction.Instruction
|
||||||
|
|
||||||
|
@Patch(false)
|
||||||
|
@Name("remove-screen-capture-restriction")
|
||||||
|
@Description("Removes the restriction of capturing audio from apps that normally wouldn't allow it.")
|
||||||
|
@Version("0.0.1")
|
||||||
|
@DependsOn([RemoveCaptureRestrictionResourcePatch::class])
|
||||||
|
@RequiresIntegrations
|
||||||
|
internal class RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
|
||||||
|
// Information about method calls we want to replace
|
||||||
|
enum class MethodCall(
|
||||||
|
override val definedClassName: String,
|
||||||
|
override val methodName: String,
|
||||||
|
override val methodParams: Array<String>,
|
||||||
|
override val returnType: String
|
||||||
|
): IMethodCall {
|
||||||
|
SetAllowedCapturePolicySingle(
|
||||||
|
"Landroid/media/AudioAttributes\$Builder;",
|
||||||
|
"setAllowedCapturePolicy",
|
||||||
|
arrayOf("I"),
|
||||||
|
"Landroid/media/AudioAttributes\$Builder;",
|
||||||
|
),
|
||||||
|
SetAllowedCapturePolicyGlobal(
|
||||||
|
"Landroid/media/AudioManager;",
|
||||||
|
"setAllowedCapturePolicy",
|
||||||
|
arrayOf("I"),
|
||||||
|
"V",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun filterMap(
|
||||||
|
classDef: ClassDef,
|
||||||
|
method: Method,
|
||||||
|
instruction: Instruction,
|
||||||
|
instructionIndex: Int
|
||||||
|
) = filterMapInstruction35c<MethodCall>(
|
||||||
|
INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
|
||||||
|
classDef,
|
||||||
|
instruction,
|
||||||
|
instructionIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) {
|
||||||
|
val (methodType, instruction, instructionIndex) = entry
|
||||||
|
methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
|
||||||
|
"Lapp/revanced/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
|
||||||
|
const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package app.revanced.patches.spotify.audio.resource.patch
|
package app.revanced.patches.all.screencapture.removerestriction.resource.patch
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
|
@ -7,14 +7,12 @@ import app.revanced.patcher.data.ResourceContext
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.ResourcePatch
|
import app.revanced.patcher.patch.ResourcePatch
|
||||||
import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
|
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
@Name("disable-capture-restriction-resource-patch")
|
@Name("remove-screen-capture-restriction-resource-patch")
|
||||||
@Description("Sets allowAudioPlaybackCapture in manifest to true.")
|
@Description("Sets allowAudioPlaybackCapture in manifest to true.")
|
||||||
@DisableCaptureRestrictionCompatibility
|
@Version("0.0.1")
|
||||||
@Version("0.0.2")
|
internal class RemoveCaptureRestrictionResourcePatch : ResourcePatch {
|
||||||
class DisableCaptureRestrictionResourcePatch : ResourcePatch {
|
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
// create an xml editor instance
|
// create an xml editor instance
|
||||||
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
context.xmlEditor["AndroidManifest.xml"].use { dom ->
|
|
@ -0,0 +1,8 @@
|
||||||
|
package app.revanced.patches.nfctoolsse.misc.pro.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("com.wakdev.apps.nfctools.se")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
internal annotation class UnlockProCompatibility
|
|
@ -0,0 +1,10 @@
|
||||||
|
package app.revanced.patches.nfctoolsse.misc.pro.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object IsLicenseRegisteredFingerprint : MethodFingerprint(
|
||||||
|
returnType = "Z",
|
||||||
|
accessFlags = AccessFlags.PUBLIC.value,
|
||||||
|
strings = listOf("kLicenseCheck")
|
||||||
|
)
|
|
@ -0,0 +1,41 @@
|
||||||
|
package app.revanced.patches.nfctoolsse.misc.pro.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.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.nfctoolsse.misc.pro.annotations.UnlockProCompatibility
|
||||||
|
import app.revanced.patches.nfctoolsse.misc.pro.fingerprints.IsLicenseRegisteredFingerprint
|
||||||
|
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("unlock-pro")
|
||||||
|
@Description("Unlocks all pro features.")
|
||||||
|
@Version("0.0.1")
|
||||||
|
@UnlockProCompatibility
|
||||||
|
class UnlockProPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
IsLicenseRegisteredFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
IsLicenseRegisteredFingerprint.result?.mutableMethod?.apply {
|
||||||
|
addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} ?: return IsLicenseRegisteredFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package app.revanced.patches.scbeasy.detection.debugging.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("com.scb.phone")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
internal annotation class RemoveDebuggingDetectionCompatibility
|
|
@ -0,0 +1,8 @@
|
||||||
|
package app.revanced.patches.scbeasy.detection.debugging.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
|
||||||
|
object DebuggingDetectionFingerprint : MethodFingerprint(
|
||||||
|
returnType = "Z",
|
||||||
|
strings = listOf("adb_enabled")
|
||||||
|
)
|
|
@ -0,0 +1,31 @@
|
||||||
|
package app.revanced.patches.scbeasy.detection.debugging.patch
|
||||||
|
|
||||||
|
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.scbeasy.detection.debugging.annotations.RemoveDebuggingDetectionCompatibility
|
||||||
|
import app.revanced.patches.scbeasy.detection.debugging.fingerprints.DebuggingDetectionFingerprint
|
||||||
|
|
||||||
|
@Patch(false)
|
||||||
|
@Name("remove-debugging-detection")
|
||||||
|
@Description("Removes the USB and wireless debugging checks.")
|
||||||
|
@RemoveDebuggingDetectionCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class RemoveDebuggingDetectionPatch : BytecodePatch(
|
||||||
|
listOf(DebuggingDetectionFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
DebuggingDetectionFingerprint.result!!.mutableMethod.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x0
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,8 +35,8 @@ internal abstract class AbstractPreferenceScreen(
|
||||||
return PreferenceScreen(
|
return PreferenceScreen(
|
||||||
key,
|
key,
|
||||||
StringResource("${key}_title", title),
|
StringResource("${key}_title", title),
|
||||||
preferences.sortedBy { it.title.value } +
|
preferences.sortedBy { it.title.value.lowercase() } +
|
||||||
categories.sortedBy { it.title }.map { it.transform() },
|
categories.sortedBy { it.title.lowercase() }.map { it.transform() },
|
||||||
summary?.let { summary ->
|
summary?.let { summary ->
|
||||||
StringResource("${key}_summary", summary)
|
StringResource("${key}_summary", summary)
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ internal abstract class AbstractPreferenceScreen(
|
||||||
return PreferenceCategory(
|
return PreferenceCategory(
|
||||||
key,
|
key,
|
||||||
StringResource("${key}_title", title),
|
StringResource("${key}_title", title),
|
||||||
preferences.sortedBy { it.title.value }
|
preferences.sortedBy { it.title.value.lowercase() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
package app.revanced.patches.spotify.audio.annotation
|
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Compatibility
|
|
||||||
import app.revanced.patcher.annotation.Package
|
|
||||||
|
|
||||||
@Compatibility(
|
|
||||||
[Package("com.spotify.music")]
|
|
||||||
)
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
internal annotation class DisableCaptureRestrictionCompatibility
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
package app.revanced.patches.spotify.audio.bytecode.patch
|
|
||||||
|
|
||||||
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.instruction
|
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
|
||||||
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.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
|
|
||||||
import app.revanced.patches.spotify.audio.fingerprints.DisableCaptureRestrictionAudioDriverFingerprint
|
|
||||||
import app.revanced.patches.spotify.audio.resource.patch.DisableCaptureRestrictionResourcePatch
|
|
||||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
|
|
||||||
@Patch
|
|
||||||
@Name("disable-capture-restriction")
|
|
||||||
@DependsOn([DisableCaptureRestrictionResourcePatch::class])
|
|
||||||
@Description("Allows capturing Spotify's audio output while screen sharing or screen recording.")
|
|
||||||
@DisableCaptureRestrictionCompatibility
|
|
||||||
@Version("0.0.2")
|
|
||||||
class DisableCaptureRestrictionBytecodePatch : BytecodePatch(
|
|
||||||
listOf(
|
|
||||||
DisableCaptureRestrictionAudioDriverFingerprint
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
|
||||||
val method = DisableCaptureRestrictionAudioDriverFingerprint.result!!.mutableMethod
|
|
||||||
|
|
||||||
method.apply {
|
|
||||||
// Replace constant
|
|
||||||
val original = instruction(0) as OneRegisterInstruction
|
|
||||||
replaceInstruction(
|
|
||||||
0,
|
|
||||||
"const/4 v${original.registerA}, $ALLOW_CAPTURE_BY_ALL"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
const val ALLOW_CAPTURE_BY_ALL = 0x01
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package app.revanced.patches.spotify.audio.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
|
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference
|
|
||||||
|
|
||||||
object DisableCaptureRestrictionAudioDriverFingerprint : MethodFingerprint(
|
|
||||||
"L",
|
|
||||||
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC or AccessFlags.BRIDGE,
|
|
||||||
listOf("L"),
|
|
||||||
listOf(
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.RETURN_OBJECT
|
|
||||||
),
|
|
||||||
customFingerprint = { methodDef, _ ->
|
|
||||||
// Check for method call to AudioAttributes$Builder.setAllowedCapturePolicy Android API
|
|
||||||
methodDef.implementation?.instructions?.any {
|
|
||||||
((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "setAllowedCapturePolicy"
|
|
||||||
} == true
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[
|
[
|
||||||
Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
|
Package("com.ss.android.ugc.trill"),
|
||||||
Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
|
Package("com.zhiliaoapp.musically")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|
|
@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[
|
[
|
||||||
Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
|
Package("com.ss.android.ugc.trill"),
|
||||||
Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
|
Package("com.zhiliaoapp.musically")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|
|
@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[
|
[
|
||||||
Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
|
Package("com.ss.android.ugc.trill"),
|
||||||
Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
|
Package("com.zhiliaoapp.musically")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package app.revanced.patches.tiktok.misc.settings.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object AboutPageFingerprint : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.CONST, // copyrightPolicyLabel resource id
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CONST_STRING
|
||||||
|
),
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.definingClass == "Lcom/ss/android/ugc/aweme/setting/page/AboutPage;" &&
|
||||||
|
methodDef.name == "onViewCreated"
|
||||||
|
}
|
||||||
|
)
|
|
@ -1,37 +0,0 @@
|
||||||
package app.revanced.patches.tiktok.misc.settings.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import org.jf.dexlib2.Opcode
|
|
||||||
|
|
||||||
@FuzzyPatternScanMethod(4)
|
|
||||||
object AboutViewFingerprint : MethodFingerprint(
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.NEW_INSTANCE,
|
|
||||||
Opcode.INVOKE_DIRECT,
|
|
||||||
Opcode.INVOKE_DIRECT_RANGE,
|
|
||||||
Opcode.INVOKE_DIRECT,
|
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
Opcode.NEW_INSTANCE,
|
|
||||||
Opcode.NEW_INSTANCE,
|
|
||||||
Opcode.CONST,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.SGET_OBJECT,
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.NEW_INSTANCE,
|
|
||||||
Opcode.INVOKE_DIRECT,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.CONST_STRING,
|
|
||||||
Opcode.INVOKE_DIRECT_RANGE,
|
|
||||||
Opcode.INVOKE_DIRECT,
|
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
Opcode.CONST,
|
|
||||||
Opcode.SGET_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.CONST
|
|
||||||
)
|
|
||||||
)
|
|
|
@ -8,7 +8,6 @@ import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.instruction
|
import app.revanced.patcher.extensions.instruction
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
import app.revanced.patcher.patch.PatchResultError
|
||||||
|
@ -17,14 +16,14 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
|
import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
|
||||||
import app.revanced.patches.tiktok.misc.settings.annotations.SettingsCompatibility
|
import app.revanced.patches.tiktok.misc.settings.annotations.SettingsCompatibility
|
||||||
import app.revanced.patches.tiktok.misc.settings.fingerprints.AboutViewFingerprint
|
import app.revanced.patches.tiktok.misc.settings.fingerprints.AboutPageFingerprint
|
||||||
import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityOnCreateFingerprint
|
import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityOnCreateFingerprint
|
||||||
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsOnViewCreatedFingerprint
|
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsOnViewCreatedFingerprint
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
import org.jf.dexlib2.iface.reference.StringReference
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@DependsOn([IntegrationsPatch::class])
|
@DependsOn([IntegrationsPatch::class])
|
||||||
|
@ -34,84 +33,92 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class SettingsPatch : BytecodePatch(
|
class SettingsPatch : BytecodePatch(
|
||||||
listOf(
|
listOf(
|
||||||
|
AboutPageFingerprint,
|
||||||
AdPersonalizationActivityOnCreateFingerprint,
|
AdPersonalizationActivityOnCreateFingerprint,
|
||||||
SettingsOnViewCreatedFingerprint,
|
SettingsOnViewCreatedFingerprint,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
SettingsOnViewCreatedFingerprint.result?.let {
|
SettingsOnViewCreatedFingerprint.result?.mutableMethod?.apply {
|
||||||
AboutViewFingerprint.resolve(context, it.method, it.classDef)
|
val instructions = implementation!!.instructions
|
||||||
}
|
|
||||||
// Patch Settings UI to add 'Revanced Settings'.
|
// Find the indices that need to be patched.
|
||||||
val targetIndexes = findOptionsOnClickIndex()
|
val copyrightPolicyLabelId = AboutPageFingerprint.result?.let {
|
||||||
with(SettingsOnViewCreatedFingerprint.result!!.mutableMethod) {
|
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
for (index in targetIndexes) {
|
it.mutableMethod.instruction<WideLiteralInstruction>(startIndex).wideLiteral
|
||||||
if (
|
} ?: return AboutPageFingerprint.toErrorResult()
|
||||||
instruction(index).opcode != Opcode.NEW_INSTANCE ||
|
|
||||||
instruction(index - 4).opcode != Opcode.MOVE_RESULT_OBJECT
|
val copyrightIndex = instructions.indexOfFirst {
|
||||||
)
|
(it as? ReferenceInstruction)?.reference.toString() == "copyright_policy"
|
||||||
return PatchResultError("Hardcode offset changed.")
|
} - 6
|
||||||
patchOptionNameAndOnClickEvent(index, context)
|
|
||||||
}
|
|
||||||
}
|
val copyrightPolicyIndex = instructions.indexOfFirst {
|
||||||
// Implement settings screen in `AdPersonalizationActivity`
|
(it as? WideLiteralInstruction)?.wideLiteral == copyrightPolicyLabelId
|
||||||
with(AdPersonalizationActivityOnCreateFingerprint.result!!.mutableMethod) {
|
} + 2
|
||||||
for ((index, instruction) in implementation!!.instructions.withIndex()) {
|
|
||||||
if (instruction.opcode != Opcode.INVOKE_SUPER) continue
|
// Replace an existing settings entry with ReVanced settings entry.
|
||||||
val thisRegister = (instruction as Instruction35c).registerC
|
arrayOf(
|
||||||
addInstructions(
|
copyrightIndex,
|
||||||
index + 1,
|
copyrightPolicyIndex
|
||||||
|
).forEach { index ->
|
||||||
|
val instruction = instruction(index)
|
||||||
|
if (instruction.opcode != Opcode.MOVE_RESULT_OBJECT)
|
||||||
|
return PatchResultError("Hardcoded offset changed.")
|
||||||
|
|
||||||
|
val settingsEntryStringRegister = (instruction as OneRegisterInstruction).registerA
|
||||||
|
|
||||||
|
// Replace the settings entry string with a custom one.
|
||||||
|
replaceInstruction(
|
||||||
|
index,
|
||||||
"""
|
"""
|
||||||
invoke-static {v$thisRegister}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->initializeSettings(Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;)V
|
const-string v$settingsEntryStringRegister, "ReVanced Settings"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
// Replace the OnClickListener class with a custom one.
|
||||||
|
val onClickListener = instruction<ReferenceInstruction>(index + 4).reference.toString()
|
||||||
|
|
||||||
|
context.findClass(onClickListener)?.mutableClass?.methods?.first {
|
||||||
|
it.name == "onClick"
|
||||||
|
}?.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->startSettingsActivity()V
|
||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
)
|
) ?: return PatchResultError("Could not find the onClick method.")
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} ?: return SettingsOnViewCreatedFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
// Initialize the settings menu once the replaced setting entry is clicked.
|
||||||
|
AdPersonalizationActivityOnCreateFingerprint.result?.mutableMethod?.apply {
|
||||||
|
val initializeSettingsIndex = implementation!!.instructions.indexOfFirst {
|
||||||
|
it.opcode == Opcode.INVOKE_SUPER
|
||||||
|
} + 1
|
||||||
|
|
||||||
|
val thisRegister = instruction<FiveRegisterInstruction>(initializeSettingsIndex - 1).registerC
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
initializeSettingsIndex,
|
||||||
|
"""
|
||||||
|
invoke-static {v$thisRegister}, $INITIALIZE_SETTINGS_METHOD_DESCRIPTOR
|
||||||
|
return-void
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} ?: return AdPersonalizationActivityOnCreateFingerprint.toErrorResult()
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findOptionsOnClickIndex(): IntArray {
|
private companion object {
|
||||||
val results = IntArray(2)
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
SettingsOnViewCreatedFingerprint.result?.apply {
|
"Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
|
||||||
for ((index, instruction) in mutableMethod.implementation!!.instructions.withIndex()) {
|
|
||||||
// Old UI settings option to replace to 'Revanced Settings'
|
|
||||||
if (instruction.opcode == Opcode.CONST_STRING) {
|
|
||||||
val string = ((instruction as ReferenceInstruction).reference as StringReference).string
|
|
||||||
if (string == "copyright_policy") {
|
|
||||||
results[0] = index - 2
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New UI settings option to replace to 'Revanced Settings'
|
private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
|
||||||
results[1] = AboutViewFingerprint.result!!.scanResult.patternScanResult!!.startIndex
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
|
||||||
} ?: throw SettingsOnViewCreatedFingerprint.toErrorResult()
|
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
|
||||||
return results
|
")V"
|
||||||
}
|
|
||||||
|
|
||||||
private fun patchOptionNameAndOnClickEvent(index: Int, context: BytecodeContext) {
|
|
||||||
with(SettingsOnViewCreatedFingerprint.result!!.mutableMethod) {
|
|
||||||
// Patch option name
|
|
||||||
val overrideRegister = instruction<OneRegisterInstruction>(index - 4).registerA
|
|
||||||
replaceInstruction(
|
|
||||||
index - 4,
|
|
||||||
"""
|
|
||||||
const-string v$overrideRegister, "Revanced Settings"
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
// Patch option OnClick Event
|
|
||||||
val type = instruction<ReferenceInstruction>(index).reference.toString()
|
|
||||||
context.findClass(type)!!.mutableClass.methods.first { type == "onClick" }.addInstructions(
|
|
||||||
0,
|
|
||||||
"""
|
|
||||||
invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->startSettingsActivity()V
|
|
||||||
return-void
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[
|
[
|
||||||
Package("com.ss.android.ugc.trill", arrayOf("27.8.3")),
|
Package("com.ss.android.ugc.trill"),
|
||||||
Package("com.zhiliaoapp.musically", arrayOf("27.8.3"))
|
Package("com.zhiliaoapp.musically")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|
|
@ -14,13 +14,21 @@ import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
|
import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
|
||||||
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
|
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
|
||||||
import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
|
import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
|
||||||
|
import app.revanced.patches.youtube.ad.getpremium.bytecode.patch.HideGetPremiumPatch
|
||||||
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
|
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
|
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@DependsOn([HideAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
|
@DependsOn(
|
||||||
|
[
|
||||||
|
HideGetPremiumPatch::class,
|
||||||
|
HideAdsResourcePatch::class,
|
||||||
|
VerticalScrollPatch::class,
|
||||||
|
FixBackToExitGesturePatch::class
|
||||||
|
]
|
||||||
|
)
|
||||||
@Name("hide-ads")
|
@Name("hide-ads")
|
||||||
@Description("Removes general ads.")
|
@Description("Removes general ads.")
|
||||||
@HideAdsCompatibility
|
@HideAdsCompatibility
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package app.revanced.patches.youtube.layout.hide.getpremium.annotations
|
package app.revanced.patches.youtube.ad.getpremium.annotations
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Compatibility
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
import app.revanced.patcher.annotation.Package
|
import app.revanced.patcher.annotation.Package
|
|
@ -1,4 +1,4 @@
|
||||||
package app.revanced.patches.youtube.layout.hide.getpremium.bytecode.fingerprints
|
package app.revanced.patches.youtube.ad.getpremium.bytecode.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
|
@ -1,7 +1,6 @@
|
||||||
package app.revanced.patches.youtube.layout.hide.getpremium.bytecode.patch
|
package app.revanced.patches.youtube.ad.getpremium.bytecode.patch
|
||||||
|
|
||||||
import app.revanced.extensions.toErrorResult
|
import app.revanced.extensions.toErrorResult
|
||||||
import app.revanced.patcher.annotation.Description
|
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
@ -11,33 +10,35 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.annotations.DependsOn
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
|
||||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||||
import app.revanced.patches.youtube.layout.hide.getpremium.annotations.HideGetPremiumCompatibility
|
import app.revanced.patches.youtube.ad.getpremium.annotations.HideGetPremiumCompatibility
|
||||||
import app.revanced.patches.youtube.layout.hide.getpremium.bytecode.fingerprints.GetPremiumViewFingerprint
|
import app.revanced.patches.youtube.ad.getpremium.bytecode.fingerprints.GetPremiumViewFingerprint
|
||||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
|
||||||
@Patch
|
|
||||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||||
@Name("hide-get-premium")
|
@Name("hide-get-premium")
|
||||||
@Description("Hides advertisement for YouTube Premium under the video player.")
|
|
||||||
@HideGetPremiumCompatibility
|
@HideGetPremiumCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class HideGetPremiumPatch : BytecodePatch(
|
class HideGetPremiumPatch : BytecodePatch(listOf(GetPremiumViewFingerprint,)) {
|
||||||
listOf(
|
|
||||||
GetPremiumViewFingerprint,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_hide_get_premium",
|
"revanced_hide_get_premium",
|
||||||
StringResource("revanced_hide_get_premium_title", "Hide YouTube Premium advertisement"),
|
StringResource(
|
||||||
StringResource("revanced_hide_get_premium_summary_on", "YouTube Premium advertisement are hidden"),
|
"revanced_hide_get_premium_title",
|
||||||
StringResource("revanced_hide_get_premium_summary_off", "YouTube Premium advertisement are shown")
|
"Hide YouTube Premium advertisement under video player"
|
||||||
|
),
|
||||||
|
StringResource(
|
||||||
|
"revanced_hide_get_premium_summary_on",
|
||||||
|
"YouTube Premium advertisement are hidden"
|
||||||
|
),
|
||||||
|
StringResource(
|
||||||
|
"revanced_hide_get_premium_summary_off",
|
||||||
|
"YouTube Premium advertisement are shown"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,5 +5,5 @@ import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
internal annotation class DownloadsCompatibility
|
internal annotation class ExternalDownloadsCompatibility
|
||||||
|
|
|
@ -9,20 +9,20 @@ import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.annotations.DependsOn
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility
|
import app.revanced.patches.youtube.interaction.downloads.annotation.ExternalDownloadsCompatibility
|
||||||
import app.revanced.patches.youtube.interaction.downloads.resource.patch.DownloadsResourcePatch
|
import app.revanced.patches.youtube.interaction.downloads.resource.patch.ExternalDownloadsResourcePatch
|
||||||
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
|
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
|
||||||
import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
|
import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("downloads")
|
@Name("external-downloads")
|
||||||
@DependsOn([DownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoInformationPatch::class])
|
@DependsOn([ExternalDownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoInformationPatch::class])
|
||||||
@Description("Adds a download button to the YouTube video player.")
|
@Description("Adds support to download and save YouTube videos using an external app.")
|
||||||
@DownloadsCompatibility
|
@ExternalDownloadsCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class DownloadsBytecodePatch : BytecodePatch() {
|
class ExternalDownloadsBytecodePatch : BytecodePatch() {
|
||||||
private companion object {
|
private companion object {
|
||||||
const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/DownloadButton;"
|
const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/ExternalDownloadButton;"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
|
@ -14,50 +14,42 @@ import app.revanced.util.resources.ResourceUtils
|
||||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||||
import app.revanced.util.resources.ResourceUtils.mergeStrings
|
import app.revanced.util.resources.ResourceUtils.mergeStrings
|
||||||
|
|
||||||
@Name("downloads-resource-patch")
|
@Name("external-downloads-resource-patch")
|
||||||
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
|
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class DownloadsResourcePatch : ResourcePatch {
|
class ExternalDownloadsResourcePatch : ResourcePatch {
|
||||||
|
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
"revanced_external_downloader_preference_screen",
|
"revanced_external_downloader_preference_screen",
|
||||||
StringResource("revanced_external_downloader_preference_screen_title", "Download settings"),
|
StringResource("revanced_external_downloader_preference_screen_title", "External download settings"),
|
||||||
listOf(
|
listOf(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_external_downloader",
|
"revanced_external_downloader",
|
||||||
StringResource("revanced_external_downloader_title", "Show download button"),
|
StringResource("revanced_external_downloader_title", "Show external download button"),
|
||||||
StringResource("revanced_external_downloader_summary_on", "Download button is shown"),
|
StringResource("revanced_external_downloader_summary_on", "Download button shown in player"),
|
||||||
StringResource("revanced_external_downloader_summary_off", "Download button is not shown")
|
StringResource("revanced_external_downloader_summary_off", "Download button not shown in player")
|
||||||
),
|
),
|
||||||
TextPreference(
|
TextPreference(
|
||||||
"revanced_external_downloader_name",
|
"revanced_external_downloader_name",
|
||||||
StringResource("revanced_external_downloader_name_title", "Downloader package name"),
|
StringResource("revanced_external_downloader_name_title", "Downloader package name"),
|
||||||
StringResource("revanced_external_downloader_name_summary", "Package name of the downloader app such as NewPipe\\'s or PowerTube\\'s"),
|
StringResource("revanced_external_downloader_name_summary", "Package name of your installed external downloader app, such as NewPipe or PowerTube"),
|
||||||
InputType.TEXT
|
InputType.TEXT
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
StringResource("revanced_external_downloader_preference_screen_summary", "Settings related to downloads")
|
StringResource("revanced_external_downloader_preference_screen_summary", "Settings for using an external downloader")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
/*
|
// Copy strings
|
||||||
* Copy strings
|
|
||||||
*/
|
|
||||||
|
|
||||||
context.mergeStrings("downloads/host/values/strings.xml")
|
context.mergeStrings("downloads/host/values/strings.xml")
|
||||||
|
|
||||||
/*
|
// Copy resources
|
||||||
* Copy resources
|
|
||||||
*/
|
|
||||||
|
|
||||||
context.copyResources("downloads", ResourceUtils.ResourceGroup("drawable", "revanced_yt_download_button.xml"))
|
context.copyResources("downloads", ResourceUtils.ResourceGroup("drawable", "revanced_yt_download_button.xml"))
|
||||||
|
|
||||||
/*
|
// Add download button node
|
||||||
* Add download button node
|
|
||||||
*/
|
|
||||||
|
|
||||||
BottomControlsResourcePatch.addControls("downloads/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
|
BottomControlsResourcePatch.addControls("downloads/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
|
@ -42,7 +42,7 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
"revanced_navigation_buttons_preference_screen",
|
"revanced_navigation_buttons_preference_screen",
|
||||||
StringResource("revanced_navigation_buttons_preference_screen_title", "Navigation button settings"),
|
StringResource("revanced_navigation_buttons_preference_screen_title", "Navigation buttons"),
|
||||||
listOf(
|
listOf(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_hide_home_button",
|
"revanced_hide_home_button",
|
||||||
|
|
|
@ -31,6 +31,7 @@ class HidePlayerButtonsPatch : BytecodePatch(
|
||||||
) {
|
) {
|
||||||
private object ParameterOffsets {
|
private object ParameterOffsets {
|
||||||
const val HAS_NEXT = 5
|
const val HAS_NEXT = 5
|
||||||
|
const val HAS_PREVIOUS = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
@ -58,13 +59,16 @@ class HidePlayerButtonsPatch : BytecodePatch(
|
||||||
|
|
||||||
// overriding this parameter register hides the previous and next buttons
|
// overriding this parameter register hides the previous and next buttons
|
||||||
val hasNextParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_NEXT
|
val hasNextParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_NEXT
|
||||||
|
val hasPreviousParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_PREVIOUS
|
||||||
|
|
||||||
mutableMethod.addInstructions(
|
mutableMethod.addInstructions(
|
||||||
callIndex,
|
callIndex,
|
||||||
"""
|
"""
|
||||||
invoke-static { }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->hideButtons()Z
|
invoke-static { v$hasNextParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
|
||||||
move-result v$hasNextParameterRegister
|
move-result v$hasNextParameterRegister
|
||||||
xor-int/lit8 v$hasNextParameterRegister, v$hasNextParameterRegister, 1
|
|
||||||
|
invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
|
||||||
|
move-result v$hasPreviousParameterRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
} ?: return PlayerControlsVisibilityModelFingerprint.toErrorResult()
|
} ?: return PlayerControlsVisibilityModelFingerprint.toErrorResult()
|
||||||
|
|
|
@ -23,10 +23,10 @@ class HideInfocardsResourcePatch : ResourcePatch {
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_hide_infocards",
|
"revanced_hide_info_cards",
|
||||||
StringResource("revanced_hide_infocards_title", "Hide info cards"),
|
StringResource("revanced_hide_info_cards_title", "Hide info cards"),
|
||||||
StringResource("revanced_hide_infocards_summary_on", "Info cards are hidden"),
|
StringResource("revanced_hide_info_cards_summary_on", "Info cards are hidden"),
|
||||||
StringResource("revanced_hide_infocards_summary_off", "Info cards are shown")
|
StringResource("revanced_hide_info_cards_summary_off", "Info cards are shown")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||||
import app.revanced.patches.youtube.layout.hide.seekbar.annotations.HideSeekbarCompatibility
|
import app.revanced.patches.youtube.layout.hide.seekbar.annotations.HideSeekbarCompatibility
|
||||||
import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
|
import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
|
||||||
|
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
|
||||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
|
|
||||||
|
@ -24,7 +25,10 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
@DependsOn([
|
@DependsOn([
|
||||||
IntegrationsPatch::class,
|
IntegrationsPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
SeekbarColorBytecodePatch::class // Used to hide the seekbar in the feed and watch history
|
// Does not alter the behavior of the seek bar by default.
|
||||||
|
SeekbarColorBytecodePatch::class,
|
||||||
|
// Used to add preferences to the seekbar settings menu.
|
||||||
|
SeekbarPreferencesPatch::class
|
||||||
])
|
])
|
||||||
@Name("hide-seekbar")
|
@Name("hide-seekbar")
|
||||||
@Description("Hides the seekbar.")
|
@Description("Hides the seekbar.")
|
||||||
|
@ -34,12 +38,18 @@ class HideSeekbarPatch : BytecodePatch(
|
||||||
listOf(SeekbarFingerprint)
|
listOf(SeekbarFingerprint)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SeekbarPreferencesPatch.addPreferences(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_hide_seekbar",
|
"revanced_hide_seekbar",
|
||||||
StringResource("revanced_hide_seekbar_title", "Hide seekbar"),
|
StringResource("revanced_hide_seekbar_title", "Hide seekbar in video player"),
|
||||||
StringResource("revanced_hide_seekbar_summary_on", "Seekbar is hidden"),
|
StringResource("revanced_hide_seekbar_summary_on", "Video player seekbar is hidden"),
|
||||||
StringResource("revanced_hide_seekbar_summary_off", "Seekbar is shown")
|
StringResource("revanced_hide_seekbar_summary_off", "Video player seekbar is shown")
|
||||||
|
),
|
||||||
|
SwitchPreference(
|
||||||
|
"revanced_hide_seekbar_thumbnail",
|
||||||
|
StringResource("revanced_hide_seekbar_thumbnail_title", "Hide seekbar in video thumbnails"),
|
||||||
|
StringResource("revanced_hide_seekbar_thumbnail_summary_on", "Thumbnail seekbar is hidden"),
|
||||||
|
StringResource("revanced_hide_seekbar_thumbnail_summary_off", "Thumbnail seekbar is shown")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,12 @@ class HideShortsComponentsResourcePatch : ResourcePatch {
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||||
PreferenceScreen(
|
PreferenceScreen(
|
||||||
"revanced_shorts",
|
"revanced_shorts_preference_screen",
|
||||||
StringResource("revanced_shorts_title", "Shorts components"),
|
StringResource("revanced_shorts_preference_screen_title", "Shorts components"),
|
||||||
listOf(
|
listOf(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_hide_shorts",
|
"revanced_hide_shorts",
|
||||||
StringResource("revanced_hide_shorts_enabled_title", "Hide shorts"),
|
StringResource("revanced_hide_shorts_title", "Hide shorts in feed"),
|
||||||
StringResource("revanced_hide_shorts_on", "Shorts are hidden"),
|
StringResource("revanced_hide_shorts_on", "Shorts are hidden"),
|
||||||
StringResource("revanced_hide_shorts_off", "Shorts are shown")
|
StringResource("revanced_hide_shorts_off", "Shorts are shown")
|
||||||
),
|
),
|
||||||
|
@ -63,14 +63,32 @@ class HideShortsComponentsResourcePatch : ResourcePatch {
|
||||||
StringResource("revanced_hide_shorts_share_button_on", "Share button is hidden"),
|
StringResource("revanced_hide_shorts_share_button_on", "Share button is hidden"),
|
||||||
StringResource("revanced_hide_shorts_share_button_off", "Share button is shown")
|
StringResource("revanced_hide_shorts_share_button_off", "Share button is shown")
|
||||||
),
|
),
|
||||||
|
SwitchPreference(
|
||||||
|
"revanced_hide_shorts_info_panel",
|
||||||
|
StringResource("revanced_hide_shorts_info_panel_title", "Hide info panel"),
|
||||||
|
StringResource("revanced_hide_shorts_info_panel_on", "Info panel is hidden"),
|
||||||
|
StringResource("revanced_hide_shorts_info_panel_off", "Info panel is shown")
|
||||||
|
),
|
||||||
|
SwitchPreference(
|
||||||
|
"revanced_hide_shorts_channel_bar",
|
||||||
|
StringResource("revanced_hide_shorts_channel_bar_title", "Hide channel bar"),
|
||||||
|
StringResource("revanced_hide_shorts_channel_bar_on", "Channel bar is hidden"),
|
||||||
|
StringResource("revanced_hide_shorts_channel_bar_off", "Channel bar is shown")
|
||||||
|
),
|
||||||
|
SwitchPreference(
|
||||||
|
"revanced_hide_shorts_sound_button",
|
||||||
|
StringResource("revanced_hide_shorts_sound_button_title", "Hide sound button"),
|
||||||
|
StringResource("revanced_hide_shorts_sound_button_on", "Sound button is hidden"),
|
||||||
|
StringResource("revanced_hide_shorts_sound_button_off", "Sound button is shown")
|
||||||
|
),
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_hide_shorts_navigation_bar",
|
"revanced_hide_shorts_navigation_bar",
|
||||||
StringResource("revanced_hide_shorts_navigation_bar_title", "Hide 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_on", "Navigation bar is hidden"),
|
||||||
StringResource("revanced_hide_shorts_navigation_bar_off", "Navigation bar is shown")
|
StringResource("revanced_hide_shorts_navigation_bar_off", "Navigation bar is shown")
|
||||||
),
|
)
|
||||||
),
|
),
|
||||||
StringResource("revanced_shorts_summary", "Manage the visibility of Shorts components")
|
StringResource("revanced_shorts_preference_screen_summary", "Manage the visibility of Shorts components")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package app.revanced.patches.youtube.layout.buttons.player.background.annotations
|
package app.revanced.patches.youtube.layout.player.background.annotations
|
||||||
import app.revanced.patcher.annotation.Compatibility
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
import app.revanced.patcher.annotation.Package
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
internal annotation class PlayerButtonBackgroundCompatibility
|
internal annotation class PlayerControlsBackgroundCompatibility
|
|
@ -1,4 +1,4 @@
|
||||||
package app.revanced.patches.youtube.layout.buttons.player.background.patch
|
package app.revanced.patches.youtube.layout.player.background.patch
|
||||||
|
|
||||||
import app.revanced.extensions.doRecursively
|
import app.revanced.extensions.doRecursively
|
||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
|
@ -9,15 +9,15 @@ import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.ResourcePatch
|
import app.revanced.patcher.patch.ResourcePatch
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.youtube.layout.buttons.player.background.annotations.PlayerButtonBackgroundCompatibility
|
import app.revanced.patches.youtube.layout.player.background.annotations.PlayerControlsBackgroundCompatibility
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
@Patch(false)
|
@Patch(false)
|
||||||
@Name("remove-player-button-background")
|
@Name("remove-player-controls-background")
|
||||||
@Description("Removes the background from the video player buttons.")
|
@Description("Removes the background from the video player controls.")
|
||||||
@PlayerButtonBackgroundCompatibility
|
@PlayerControlsBackgroundCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class PlayerButtonBackgroundPatch : ResourcePatch {
|
class PlayerControlsBackgroundPatch : ResourcePatch {
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
|
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
|
||||||
editor.file.doRecursively node@{ node ->
|
editor.file.doRecursively node@{ node ->
|
|
@ -15,9 +15,9 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility
|
import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility
|
||||||
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
|
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
|
||||||
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
|
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
|
||||||
|
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
|
||||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch
|
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch
|
||||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook
|
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook
|
||||||
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
|
|
||||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||||
import app.revanced.util.patch.indexOfFirstConstantInstruction
|
import app.revanced.util.patch.indexOfFirstConstantInstruction
|
||||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
@ -37,7 +37,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
|
||||||
addInstructions(
|
addInstructions(
|
||||||
registerIndex + 1,
|
registerIndex + 1,
|
||||||
"""
|
"""
|
||||||
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue(I)I
|
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
|
||||||
move-result v$colorRegister
|
move-result v$colorRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@ -47,7 +47,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
|
||||||
addInstructions(
|
addInstructions(
|
||||||
registerIndex + 1,
|
registerIndex + 1,
|
||||||
"""
|
"""
|
||||||
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue(I)I
|
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
|
||||||
move-result v$colorRegister
|
move-result v$colorRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@ -66,7 +66,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
|
||||||
addInstructions(
|
addInstructions(
|
||||||
0,
|
0,
|
||||||
"""
|
"""
|
||||||
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorOverride(I)I
|
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarClickedColor(I)I
|
||||||
move-result v$colorRegister
|
move-result v$colorRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@ -74,7 +74,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
|
||||||
}
|
}
|
||||||
} ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
|
} ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
|
||||||
|
|
||||||
lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getSeekbarColorOverride")
|
lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getLithoColor")
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package app.revanced.patches.youtube.layout.seekbar.resource
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.ResourceContext
|
||||||
|
import app.revanced.patcher.patch.*
|
||||||
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||||
|
import app.revanced.patches.shared.settings.preference.BasePreference
|
||||||
|
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
|
||||||
|
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||||
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
|
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||||
|
class SeekbarPreferencesPatch : ResourcePatch, Closeable {
|
||||||
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
|
|
||||||
|
// Nothing to do here. All work is done in close method.
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||||
|
PreferenceScreen(
|
||||||
|
"revanced_seekbar_preference_screen",
|
||||||
|
StringResource("revanced_seekbar_preference_screen_title", "Seekbar settings"),
|
||||||
|
seekbarPreferences
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val seekbarPreferences = mutableListOf<BasePreference>()
|
||||||
|
|
||||||
|
internal fun addPreferences(vararg preferencesToAdd: BasePreference) {
|
||||||
|
seekbarPreferences.addAll(preferencesToAdd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,7 @@ class ThemeBytecodePatch : BytecodePatch() {
|
||||||
var splashScreenBackgroundColor: String? by option(
|
var splashScreenBackgroundColor: String? by option(
|
||||||
PatchOption.StringOption(
|
PatchOption.StringOption(
|
||||||
key = "splashScreenBackgroundColor",
|
key = "splashScreenBackgroundColor",
|
||||||
default = "@android:color/black",
|
default = "?android:attr/colorBackground",
|
||||||
title = "Background color for the splash screen",
|
title = "Background color for the splash screen",
|
||||||
description = "The background color of the splash screen. Can be a hex color or a resource reference.",
|
description = "The background color of the splash screen. Can be a hex color or a resource reference.",
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,25 +9,23 @@ import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||||
import app.revanced.patches.shared.settings.preference.impl.InputType
|
import app.revanced.patches.shared.settings.preference.impl.InputType
|
||||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||||
|
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
|
||||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
|
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
|
||||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
|
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
|
||||||
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
|
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
|
||||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class, SeekbarPreferencesPatch::class])
|
||||||
class ThemeResourcePatch : ResourcePatch {
|
class ThemeResourcePatch : ResourcePatch {
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
SeekbarPreferencesPatch.addPreferences(
|
||||||
TextPreference(
|
TextPreference(
|
||||||
"revanced_seekbar_color",
|
"revanced_seekbar_color",
|
||||||
StringResource("revanced_seekbar_color_title", "Seekbar color"),
|
StringResource("revanced_seekbar_color_title", "Seekbar color"),
|
||||||
StringResource(
|
StringResource("revanced_seekbar_color_summary", "The color of the seekbar"),
|
||||||
"revanced_seekbar_color_summary",
|
|
||||||
"The color of the seekbar"
|
|
||||||
),
|
|
||||||
InputType.TEXT_CAP_CHARACTERS
|
InputType.TEXT_CAP_CHARACTERS
|
||||||
),
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Edit theme colors via resources.
|
// Edit theme colors via resources.
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For embedded playback.
|
||||||
|
* It appears this hook may no longer be needed as one of the constructor parameters is the already hooked
|
||||||
|
* [EmbeddedPlayerControlsOverlayFingerprint]
|
||||||
|
*/
|
||||||
|
object APIPlayerServiceFingerprint : IntegrationsFingerprint(
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
customFingerprint = { methodDef, _ -> methodDef.definingClass == "Lcom/google/android/apps/youtube/embeddedplayer/service/service/jar/ApiPlayerService;" },
|
||||||
|
// Integrations context is the first method parameter.
|
||||||
|
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
|
||||||
|
)
|
|
@ -2,6 +2,10 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints
|
||||||
|
|
||||||
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
|
|
||||||
object InitFingerprint : IntegrationsFingerprint(
|
/**
|
||||||
|
* Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
|
||||||
|
*/
|
||||||
|
object ApplicationInitFingerprint : IntegrationsFingerprint(
|
||||||
strings = listOf("Application creation", "Application.onCreate"),
|
strings = listOf("Application creation", "Application.onCreate"),
|
||||||
|
// Integrations context is the Activity itself.
|
||||||
)
|
)
|
|
@ -4,12 +4,19 @@ import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For embedded playback inside Google Play store (and probably other situations as well).
|
||||||
|
*
|
||||||
|
* Note: this fingerprint may no longer be needed, as it appears
|
||||||
|
* [RemoteEmbedFragmentFingerprint] may be set before this hook is called.
|
||||||
|
*/
|
||||||
object EmbeddedPlayerControlsOverlayFingerprint : IntegrationsFingerprint(
|
object EmbeddedPlayerControlsOverlayFingerprint : IntegrationsFingerprint(
|
||||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
|
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
parameters = listOf("L", "L", "L"),
|
parameters = listOf("Landroid/content/Context;", "L", "L"),
|
||||||
customFingerprint = { methodDef, _ ->
|
customFingerprint = { methodDef, _ ->
|
||||||
methodDef.definingClass.startsWith("Lcom/google/android/apps/youtube/embeddedplayer/service/ui/overlays/controlsoverlay/remoteloaded/")
|
methodDef.definingClass.startsWith("Lcom/google/android/apps/youtube/embeddedplayer/service/ui/overlays/controlsoverlay/remoteloaded/")
|
||||||
},
|
},
|
||||||
|
// Integrations context is the first method parameter.
|
||||||
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
|
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
|
||||||
)
|
)
|
|
@ -0,0 +1,20 @@
|
||||||
|
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For embedded playback inside the Google app (such as the in app 'discover' tab).
|
||||||
|
*
|
||||||
|
* Note: this fingerprint may or may not be needed, as
|
||||||
|
* [RemoteEmbedFragmentFingerprint] might be set before this is called.
|
||||||
|
*/
|
||||||
|
object EmbeddedPlayerFingerprint : IntegrationsFingerprint(
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
returnType = "L",
|
||||||
|
parameters = listOf("L", "L", "Landroid/content/Context;"),
|
||||||
|
strings = listOf("android.hardware.type.television"), // String is also found in other classes
|
||||||
|
// Integrations context is the third method parameter.
|
||||||
|
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size + 2 }
|
||||||
|
)
|
|
@ -0,0 +1,19 @@
|
||||||
|
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For embedded playback. Likely covers Google Play store and other Google products.
|
||||||
|
*/
|
||||||
|
object RemoteEmbedFragmentFingerprint : IntegrationsFingerprint(
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf("Landroid/content/Context;", "L", "L"),
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.definingClass == "Lcom/google/android/apps/youtube/embeddedplayer/service/jar/client/RemoteEmbedFragment;"
|
||||||
|
},
|
||||||
|
// Integrations context is the first method parameter.
|
||||||
|
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
|
||||||
|
)
|
|
@ -0,0 +1,19 @@
|
||||||
|
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For embedded playback inside 3rd party android app (such as 3rd party Reddit apps).
|
||||||
|
*/
|
||||||
|
object RemoteEmbeddedPlayerFingerprint : IntegrationsFingerprint(
|
||||||
|
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf("Landroid/content/Context;", "L", "L", "Z"),
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.definingClass == "Lcom/google/android/youtube/api/jar/client/RemoteEmbeddedPlayer;"
|
||||||
|
},
|
||||||
|
// Integrations context is the first method parameter.
|
||||||
|
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
|
||||||
|
)
|
|
@ -1,8 +0,0 @@
|
||||||
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
|
||||||
|
|
||||||
object ServiceFingerprint : IntegrationsFingerprint(
|
|
||||||
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "<init>" },
|
|
||||||
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
|
|
||||||
)
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Old API activity to embed YouTube into 3rd party Android apps.
|
||||||
|
*
|
||||||
|
* In 2023 supported was ended and is no longer available,
|
||||||
|
* but this may still be used by older apps:
|
||||||
|
* https://developers.google.com/youtube/android/player
|
||||||
|
*/
|
||||||
|
object StandalonePlayerActivityFingerprint : IntegrationsFingerprint(
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.definingClass == "Lcom/google/android/youtube/api/StandalonePlayerActivity;"
|
||||||
|
&& methodDef.name == "onCreate"
|
||||||
|
},
|
||||||
|
// Integrations context is the Activity itself.
|
||||||
|
)
|
|
@ -1,10 +0,0 @@
|
||||||
package app.revanced.patches.youtube.misc.integrations.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
|
|
||||||
|
|
||||||
object StandalonePlayerFingerprint : IntegrationsFingerprint(
|
|
||||||
strings = listOf(
|
|
||||||
"Invalid PlaybackStartDescriptor. Returning the instance itself.",
|
|
||||||
"com.google.android.music",
|
|
||||||
),
|
|
||||||
)
|
|
|
@ -4,15 +4,26 @@ import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.patch.annotations.RequiresIntegrations
|
import app.revanced.patcher.patch.annotations.RequiresIntegrations
|
||||||
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
|
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
|
||||||
import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility
|
import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility
|
||||||
import app.revanced.patches.youtube.misc.integrations.fingerprints.InitFingerprint
|
|
||||||
import app.revanced.patches.youtube.misc.integrations.fingerprints.EmbeddedPlayerControlsOverlayFingerprint
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.EmbeddedPlayerControlsOverlayFingerprint
|
||||||
import app.revanced.patches.youtube.misc.integrations.fingerprints.ServiceFingerprint
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.EmbeddedPlayerFingerprint
|
||||||
import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerFingerprint
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.ApplicationInitFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.RemoteEmbedFragmentFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.RemoteEmbeddedPlayerFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.APIPlayerServiceFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerActivityFingerprint
|
||||||
|
|
||||||
@Name("integrations")
|
@Name("integrations")
|
||||||
@IntegrationsCompatibility
|
@IntegrationsCompatibility
|
||||||
@RequiresIntegrations
|
@RequiresIntegrations
|
||||||
class IntegrationsPatch : AbstractIntegrationsPatch(
|
class IntegrationsPatch : AbstractIntegrationsPatch(
|
||||||
"Lapp/revanced/integrations/utils/ReVancedUtils;",
|
"Lapp/revanced/integrations/utils/ReVancedUtils;",
|
||||||
listOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint, EmbeddedPlayerControlsOverlayFingerprint),
|
listOf(
|
||||||
|
ApplicationInitFingerprint,
|
||||||
|
StandalonePlayerActivityFingerprint,
|
||||||
|
RemoteEmbeddedPlayerFingerprint,
|
||||||
|
RemoteEmbedFragmentFingerprint,
|
||||||
|
EmbeddedPlayerControlsOverlayFingerprint,
|
||||||
|
EmbeddedPlayerFingerprint,
|
||||||
|
APIPlayerServiceFingerprint,
|
||||||
|
),
|
||||||
)
|
)
|
|
@ -51,7 +51,7 @@ class RememberVideoQualityPatch : BytecodePatch(
|
||||||
StringResource("revanced_video_quality_default_entry_5", "720p"),
|
StringResource("revanced_video_quality_default_entry_5", "720p"),
|
||||||
StringResource("revanced_video_quality_default_entry_6", "480p"),
|
StringResource("revanced_video_quality_default_entry_6", "480p"),
|
||||||
StringResource("revanced_video_quality_default_entry_7", "360p"),
|
StringResource("revanced_video_quality_default_entry_7", "360p"),
|
||||||
StringResource("revanced_video_quality_default_entry_8", "280p"),
|
StringResource("revanced_video_quality_default_entry_8", "240p"),
|
||||||
StringResource("revanced_video_quality_default_entry_9", "144p"),
|
StringResource("revanced_video_quality_default_entry_9", "144p"),
|
||||||
)
|
)
|
||||||
val entryValues = listOf(
|
val entryValues = listOf(
|
||||||
|
@ -62,7 +62,7 @@ class RememberVideoQualityPatch : BytecodePatch(
|
||||||
StringResource("revanced_video_quality_default_entry_value_5", "720"),
|
StringResource("revanced_video_quality_default_entry_value_5", "720"),
|
||||||
StringResource("revanced_video_quality_default_entry_value_6", "480"),
|
StringResource("revanced_video_quality_default_entry_value_6", "480"),
|
||||||
StringResource("revanced_video_quality_default_entry_value_7", "360"),
|
StringResource("revanced_video_quality_default_entry_value_7", "360"),
|
||||||
StringResource("revanced_video_quality_default_entry_value_8", "280"),
|
StringResource("revanced_video_quality_default_entry_value_8", "240"),
|
||||||
StringResource("revanced_video_quality_default_entry_value_9", "144"),
|
StringResource("revanced_video_quality_default_entry_value_9", "144"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,39 +21,44 @@ internal abstract class AbstractTransformInstructionsPatch<T> : BytecodePatch()
|
||||||
|
|
||||||
abstract fun transform(mutableMethod: MutableMethod, entry: T)
|
abstract fun transform(mutableMethod: MutableMethod, entry: T)
|
||||||
|
|
||||||
|
// Returns the patch indices as a Sequence, which will execute lazily.
|
||||||
|
private fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? {
|
||||||
|
return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
|
||||||
|
filterMap(classDef, method, instruction, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
// Find all instructions
|
// Find all methods to patch
|
||||||
buildMap {
|
buildMap {
|
||||||
context.classes.forEach { classDef ->
|
context.classes.forEach { classDef ->
|
||||||
classDef.methods.let { methods ->
|
val methods = buildList {
|
||||||
buildMap methodList@{
|
classDef.methods.forEach { method ->
|
||||||
methods.forEach methods@{ method ->
|
// Since the Sequence executes lazily,
|
||||||
with(method.implementation?.instructions ?: return@methods) {
|
// using any() results in only calling
|
||||||
ArrayDeque<T>().also { patchIndices ->
|
// filterMap until the first index has been found.
|
||||||
this.forEachIndexed { index, instruction ->
|
val patchIndices = findPatchIndices(classDef, method)
|
||||||
val result = filterMap(classDef, method, instruction, index)
|
|
||||||
if (result != null) {
|
if (patchIndices?.any() == true) {
|
||||||
patchIndices.add(result)
|
add(method)
|
||||||
}
|
|
||||||
}
|
|
||||||
}.also { if (it.isEmpty()) return@methods }.let { patches ->
|
|
||||||
put(method, patches)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.also { if (it.isEmpty()) return@forEach }.let { methodPatches ->
|
}
|
||||||
put(classDef, methodPatches)
|
|
||||||
|
if (methods.isNotEmpty()) {
|
||||||
|
put(classDef, methods)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.forEach { (classDef, methods) ->
|
}.forEach { (classDef, methods) ->
|
||||||
// And finally transform the instructions...
|
// And finally transform the methods...
|
||||||
with(context.proxy(classDef).mutableClass) {
|
val mutableClass = context.proxy(classDef).mutableClass
|
||||||
methods.forEach { (method, patches) ->
|
|
||||||
val mutableMethod = findMutableMethodOf(method)
|
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
|
||||||
while (!patches.isEmpty()) {
|
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
|
||||||
transform(mutableMethod, patches.removeLast())
|
?: return@methods
|
||||||
}
|
|
||||||
|
while (!patchIndices.isEmpty()) {
|
||||||
|
transform(mutableMethod, patchIndices.removeLast())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yt="http://schemas.android.com/apk/res-auto" android:id="@+id/youtube_controls_bottom_ui_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="ltr">
|
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yt="http://schemas.android.com/apk/res-auto" android:id="@+id/youtube_controls_bottom_ui_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="ltr">
|
||||||
<com.google.android.libraries.youtube.common.ui.TouchImageView android:id="@+id/download_button" android:paddingLeft="12dp" android:paddingTop="22dp" android:paddingRight="12dp" android:paddingBottom="16dp" android:longClickable="false" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/revanced_yt_download_button" android:scaleType="center" yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container" yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" style="@style/YouTubePlayerButton"/>
|
<com.google.android.libraries.youtube.common.ui.TouchImageView android:id="@+id/external_download_button" android:paddingLeft="12dp" android:paddingTop="22dp" android:paddingRight="12dp" android:paddingBottom="16dp" android:longClickable="false" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/revanced_yt_download_button" android:scaleType="center" yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container" yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" style="@style/YouTubePlayerButton"/>
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="downloader_not_installed_warning">is not installed. Please install it.</string>
|
<string name="external_downloader_not_installed_warning">is not installed. Please install it.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue