Compare commits

...

57 Commits

Author SHA1 Message Date
semantic-release-bot
0e0763221c chore(release): 2.18.2 [skip ci]
## [2.18.2](https://github.com/revanced/revanced-patches/compare/v2.18.1...v2.18.2) (2022-07-18)

### Bug Fixes

* make all patches toggleable with settings ([#202](https://github.com/revanced/revanced-patches/issues/202)) ([6b515dd](6b515dd59e))
2022-07-18 21:01:38 +00:00
TheJeterLP
6b515dd59e fix: make all patches toggleable with settings (#202) 2022-07-18 22:59:21 +02:00
semantic-release-bot
4ee40a954f chore(release): 2.18.1 [skip ci]
## [2.18.1](https://github.com/revanced/revanced-patches/compare/v2.18.0...v2.18.1) (2022-07-18)

### Bug Fixes

* `minimized-playback` patch for YouTube Kids videos ([#201](https://github.com/revanced/revanced-patches/issues/201)) ([fb96c6e](fb96c6e4bc))
2022-07-18 14:31:50 +00:00
Alberto Ponces
fb96c6e4bc fix: minimized-playback patch for YouTube Kids videos (#201) 2022-07-18 16:29:51 +02:00
semantic-release-bot
c5156fa7e3 chore(release): 2.18.0 [skip ci]
# [2.18.0](https://github.com/revanced/revanced-patches/compare/v2.17.0...v2.18.0) (2022-07-18)

### Features

* `hide-get-premium` patch ([#195](https://github.com/revanced/revanced-patches/issues/195)) ([8b0622f](8b0622f0bf))
2022-07-18 14:25:54 +00:00
Alberto Ponces
8b0622f0bf feat: hide-get-premium patch (#195)
* feat: `hide-get-premium` patch

* fix: improve `hide-get-premium` fingerprints
2022-07-18 16:24:10 +02:00
semantic-release-bot
1e3eddd3f2 chore(release): 2.17.0 [skip ci]
# [2.17.0](https://github.com/revanced/revanced-patches/compare/v2.16.1...v2.17.0) (2022-07-17)

### Bug Fixes

* check if node has attributes before accessing them ([1d12a17](1d12a17999))

### Features

* `sponsorblock` patch ([#101](https://github.com/revanced/revanced-patches/issues/101)) ([db410e1](db410e1be6)), closes [#89](https://github.com/revanced/revanced-patches/issues/89) [#90](https://github.com/revanced/revanced-patches/issues/90)
2022-07-17 23:52:36 +00:00
oSumAtrIX
1d12a17999 fix: check if node has attributes before accessing them 2022-07-18 01:50:46 +02:00
oSumAtrIX
db410e1be6 feat: sponsorblock patch (#101)
* chore(release): 2.5.1-dev.1 [skip ci]

## [2.5.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.5.0...v2.5.1-dev.1) (2022-06-30)

### Bug Fixes

* freezing panels when watching video in fullscreen ([#89](https://github.com/revanced/revanced-patches/issues/89)) ([d3e1419](d3e1419d0e))
* invalid version in compatibility annotation ([#90](https://github.com/revanced/revanced-patches/issues/90)) ([c21e177](c21e177ed1))

* feat: migrate to breaking changes of patcher

* chore(release): 2.6.0-dev.1 [skip ci]

# [2.6.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.5.1-dev.1...v2.6.0-dev.1) (2022-07-02)

### Features

* migrate to breaking changes of patcher ([c95c241](c95c241887))

* refactor: add package for fingerprints

* feat: partial `sponsorblock` patch

* feat: add `Name` annotation to `sponsorblock-resource-patch`

* fix: `sponsorblock-resource-patch`

* refactor: remove unused resources

* refactor: remove `locale-config-fix` dependency

* fix: broken fingerprints

* feat: general fixes on `sponsorblock` patch

* feat: more fixes on `sponsorblock` patch

* feat: update `sponsorblock` patch to 17.26.35

* style: use better wording and fix spelling mistakes

* fix: finish `sponsorblock` patch

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
2022-07-18 01:17:03 +02:00
semantic-release-bot
9969d03116 chore(release): 2.16.1 [skip ci]
## [2.16.1](https://github.com/revanced/revanced-patches/compare/v2.16.0...v2.16.1) (2022-07-17)

### Bug Fixes

* bump youtube version to 17.27.39 ([9d1fecc](9d1fecc2f5))
2022-07-17 15:04:31 +00:00
TheJeterLP
9d1fecc2f5 fix: bump youtube version to 17.27.39 2022-07-17 17:02:43 +02:00
semantic-release-bot
63df96d251 chore(release): 2.16.0 [skip ci]
# [2.16.0](https://github.com/revanced/revanced-patches/compare/v2.15.1...v2.16.0) (2022-07-17)

### Features

* `force-vp9-codec` patch ([#157](https://github.com/revanced/revanced-patches/issues/157)) ([d1266a2](d1266a252d))
2022-07-17 14:34:06 +00:00
TheJeterLP
d1266a252d feat: force-vp9-codec patch (#157) 2022-07-17 16:32:29 +02:00
semantic-release-bot
6ec6d16dbc chore(release): 2.15.1 [skip ci]
## [2.15.1](https://github.com/revanced/revanced-patches/compare/v2.15.0...v2.15.1) (2022-07-17)

### Bug Fixes

* `old-quality-layout` patch ([f940e46](f940e4647e))
* references to integrations in `return-youtube-dislike` patch ([9860658](986065858d))
2022-07-17 14:05:02 +00:00
oSumAtrIX
f940e4647e fix: old-quality-layout patch 2022-07-17 16:03:20 +02:00
oSumAtrIX
cc39b77b49 refactor: use .single for resourceMappings 2022-07-17 16:03:20 +02:00
oSumAtrIX
986065858d fix: references to integrations in return-youtube-dislike patch 2022-07-17 16:03:19 +02:00
TheJeterLP
56475e8f38 refactor: rename HDRAutoBrightnessPatch 2022-07-17 15:07:21 +02:00
Palm
2e0ff07d1a style: better patch descriptions (#193) 2022-07-17 12:36:46 +02:00
oSumAtrIX
a654e25000 refactor: simplify use of dependencies field in Dependencies annotations 2022-07-16 17:32:03 +02:00
oSumAtrIX
a8736a8f70 style: naming for ReturnYouTubeDislike patch 2022-07-16 17:31:40 +02:00
semantic-release-bot
b0d6cee4db chore(release): 2.15.0 [skip ci]
# [2.15.0](https://github.com/revanced/revanced-patches/compare/v2.14.1...v2.15.0) (2022-07-16)

### Features

* `return-youtube-dislikes` patch ([#175](https://github.com/revanced/revanced-patches/issues/175)) ([6bbcdf8](6bbcdf8ebd))
2022-07-16 14:52:58 +00:00
j4k0xb
6bbcdf8ebd feat: return-youtube-dislikes patch (#175)
* feat: ryd

* refactor: use ryd patches class

* feat: add video id dependency patch

* fix: compatibility with 17.26.35

* refactor: named param variable, simpler mutableClass access
2022-07-16 16:50:37 +02:00
semantic-release-bot
6fa8289ca6 chore(release): 2.14.1 [skip ci]
## [2.14.1](https://github.com/revanced/revanced-patches/compare/v2.14.0...v2.14.1) (2022-07-15)

### Bug Fixes

* `codecs-unlock` patch and update Music patches to `5.14.53` ([97dbb43](97dbb43caa))
2022-07-15 12:57:47 +00:00
Alberto Ponces
97dbb43caa fix: codecs-unlock patch and update Music patches to 5.14.53 2022-07-15 14:56:10 +02:00
semantic-release-bot
8cda5663ef chore(release): 2.14.0 [skip ci]
# [2.14.0](https://github.com/revanced/revanced-patches/compare/v2.13.6...v2.14.0) (2022-07-15)

### Features

* `music-video-ads` patch ([#172](https://github.com/revanced/revanced-patches/issues/172)) ([5587c91](5587c91899))
2022-07-15 11:20:04 +00:00
Alberto Ponces
5587c91899 feat: music-video-ads patch (#172) 2022-07-15 13:18:25 +02:00
semantic-release-bot
4e6d82a334 chore(release): 2.13.6 [skip ci]
## [2.13.6](https://github.com/revanced/revanced-patches/compare/v2.13.5...v2.13.6) (2022-07-14)
2022-07-14 16:48:23 +00:00
TheJeterLP
be7302689e build: trigger build 2022-07-14 18:46:33 +02:00
TheJeterLP
14d94d6a44 refactor: prepare for settings patch (#168) 2022-07-14 18:42:22 +02:00
genericness
8d598f5b82 style: casing in description (#174) 2022-07-14 18:40:21 +02:00
semantic-release-bot
918782908b chore(release): 2.13.5 [skip ci]
## [2.13.5](https://github.com/revanced/revanced-patches/compare/v2.13.4...v2.13.5) (2022-07-14)

### Bug Fixes

* `swipe-controls` with active engagement panel ([#177](https://github.com/revanced/revanced-patches/issues/177)) ([524fe19](524fe19840))
2022-07-14 15:23:07 +00:00
Chris
524fe19840 fix: swipe-controls with active engagement panel (#177) 2022-07-14 17:21:26 +02:00
semantic-release-bot
18aafb400b chore(release): 2.13.4 [skip ci]
## [2.13.4](https://github.com/revanced/revanced-patches/compare/v2.13.3...v2.13.4) (2022-07-13)

### Bug Fixes

* constrain `old-quality-layout` to older version ([83ac6b3](83ac6b3e34))
2022-07-13 11:38:21 +00:00
oSumAtrIX
83ac6b3e34 fix: constrain old-quality-layout to older version 2022-07-13 13:36:09 +02:00
oSumAtrIX
890ebf04df docs: change size of headings [skip ci] 2022-07-12 01:13:09 +02:00
oSumAtrIX
6838daf1c3 refactor: rename class and move to sub-package 2022-07-12 00:04:22 +02:00
bogadana
08f4e8532c docs: properly handle semantic versions (#156) [skip ci] 2022-07-11 21:08:47 +02:00
semantic-release-bot
30d25a87da chore(release): 2.13.3 [skip ci]
## [2.13.3](https://github.com/revanced/revanced-patches/compare/v2.13.2...v2.13.3) (2022-07-11)

### Bug Fixes

* `exclusive-audio-playback` patch ([#153](https://github.com/revanced/revanced-patches/issues/153)) ([af0523d](af0523df39))
2022-07-11 18:07:27 +00:00
Alberto Ponces
af0523df39 fix: exclusive-audio-playback patch (#153) 2022-07-11 20:05:03 +02:00
semantic-release-bot
18a3f8e80c chore(release): 2.13.2 [skip ci]
## [2.13.2](https://github.com/revanced/revanced-patches/compare/v2.13.1...v2.13.2) (2022-07-11)

### Bug Fixes

* `hrd-auto-brightness` ([#152](https://github.com/revanced/revanced-patches/issues/152)) ([ce32c6f](ce32c6f3f7))
2022-07-11 17:01:08 +00:00
Chris
ce32c6f3f7 fix: hrd-auto-brightness (#152) 2022-07-11 18:59:26 +02:00
semantic-release-bot
6b706bc93c chore(release): 2.13.1 [skip ci]
## [2.13.1](https://github.com/revanced/revanced-patches/compare/v2.13.0...v2.13.1) (2022-07-11)

### Bug Fixes

* bump youtube version for swipe-controls patch ([6838e25](6838e25764))
2022-07-11 12:41:09 +00:00
TheJeterLP
6838e25764 fix: bump youtube version for swipe-controls patch 2022-07-11 14:39:36 +02:00
semantic-release-bot
f6f8b0ee31 chore(release): 2.13.0 [skip ci]
# [2.13.0](https://github.com/revanced/revanced-patches/compare/v2.12.4...v2.13.0) (2022-07-11)

### Features

* `swipe-controls` rewrite ([#131](https://github.com/revanced/revanced-patches/issues/131)) ([8e26d09](8e26d0933d))
2022-07-11 12:31:53 +00:00
Chris
8e26d0933d feat: swipe-controls rewrite (#131)
* move patch 'fenster' to 'swipe-controls'

* remove 'injectIntoNamedMethod' function

* move updatePlayerType hook into its own patch

* refactor 'swipe-controls' patch

* add resources for new ui to patch

Co-authored-by: TheJeterLP <joey.peter1998@gmail.com>
2022-07-11 14:29:46 +02:00
semantic-release-bot
6f29325a85 chore(release): 2.12.4 [skip ci]
## [2.12.4](https://github.com/revanced/revanced-patches/compare/v2.12.3...v2.12.4) (2022-07-11)

### Bug Fixes

*  `autorepeat-by-default` patch ([#148](https://github.com/revanced/revanced-patches/issues/148)) ([46e163c](46e163caa9))
2022-07-11 06:58:15 +00:00
TheJeterLP
46e163caa9 fix: autorepeat-by-default patch (#148) 2022-07-11 08:56:33 +02:00
semantic-release-bot
af19363997 chore(release): 2.12.3 [skip ci]
## [2.12.3](https://github.com/revanced/revanced-patches/compare/v2.12.2...v2.12.3) (2022-07-11)

### Bug Fixes

* listing of wrong fingerprint class ([#147](https://github.com/revanced/revanced-patches/issues/147)) ([c578e21](c578e210bb))
2022-07-11 05:51:29 +00:00
Alberto Ponces
c578e210bb fix: listing of wrong fingerprint class (#147) 2022-07-11 07:49:40 +02:00
Sculas
980f7f04cc chore: remove assignees [skip ci] 2022-07-10 20:30:47 +02:00
Sculas
baeb0ad0d4 chore: remove assignees [skip ci] 2022-07-10 20:30:35 +02:00
semantic-release-bot
6c4a69fcfb chore(release): 2.12.2 [skip ci]
## [2.12.2](https://github.com/revanced/revanced-patches/compare/v2.12.1...v2.12.2) (2022-07-10)

### Bug Fixes

* display codename for patch names ([7107ee8](7107ee87d9))
* incorrect package name in gradle task ([8ce3a6b](8ce3a6b4e3))
* invalid regex ([b39d60f](b39d60f46c))
2022-07-10 18:00:21 +00:00
oSumAtrIX
4129fcf8a8 refactor: add missing space in generated string 2022-07-10 19:58:32 +02:00
oSumAtrIX
b39d60f46c fix: invalid regex 2022-07-10 19:58:32 +02:00
oSumAtrIX
8ce3a6b4e3 fix: incorrect package name in gradle task 2022-07-10 19:58:32 +02:00
oSumAtrIX
7107ee87d9 fix: display codename for patch names 2022-07-10 19:58:32 +02:00
137 changed files with 2913 additions and 484 deletions

View File

@@ -3,22 +3,22 @@ name: Bug report
about: Create a bug report on patches about: Create a bug report on patches
title: 'problem: `some-patch`' title: 'problem: `some-patch`'
labels: bug labels: bug
assignees: TheJeterLP, oSumAtrIX, Sculas assignees: ''
--- ---
# 🐞 Issue ## 🐞 Issue
<!-- Describe your issue in detail here --> <!-- Describe your issue in detail here -->
# ⚙ Reproduce ## ⚙ Reproduce
<!-- Include your environment and steps to reproduce the issue as detailed as possible --> <!-- Include your environment and steps to reproduce the issue as detailed as possible -->
# 🛠 Solution ## 🛠 Solution
<!-- If applicable, add a possible solution --> <!-- If applicable, add a possible solution -->
# ⚠ Additional context ## ⚠ Additional context
<!-- Add any other context about the problem here --> <!-- Add any other context about the problem here -->

View File

@@ -3,22 +3,22 @@ name: Feature request
about: Suggest a change to some patch. Do not submit suggestions for patches here. about: Suggest a change to some patch. Do not submit suggestions for patches here.
title: 'feat: some feature' title: 'feat: some feature'
labels: feature-request labels: feature-request
assignees: TheJeterLP, oSumAtrIX, Sculas assignees: ''
--- ---
# 🐞 Issue ## 🐞 Issue
<!-- Explain here, what the current problem is and why it lead you to request a feature change --> <!-- Explain here, what the current problem is and why it leads you to request a feature change -->
# ❗ Solution ## ❗ Solution
<!-- Explain how your current issue can be solved --> <!-- Explain how your current issue can be solved -->
# ❓ Motivation ## ❓ Motivation
<!-- Explain why your feature should be considered --> <!-- Explain why your feature should be considered -->
# ⚠ Additional context ## ⚠ Additional context
<!-- Add any other context or screenshots about the feature request here --> <!-- Add any other context or screenshots about the feature request here -->

View File

@@ -1,3 +1,146 @@
## [2.18.2](https://github.com/revanced/revanced-patches/compare/v2.18.1...v2.18.2) (2022-07-18)
### Bug Fixes
* make all patches toggleable with settings ([#202](https://github.com/revanced/revanced-patches/issues/202)) ([7e1d82f](https://github.com/revanced/revanced-patches/commit/7e1d82f1161237632c3a57f109db6b8903006b33))
## [2.18.1](https://github.com/revanced/revanced-patches/compare/v2.18.0...v2.18.1) (2022-07-18)
### Bug Fixes
* `minimized-playback` patch for YouTube Kids videos ([#201](https://github.com/revanced/revanced-patches/issues/201)) ([31e3b42](https://github.com/revanced/revanced-patches/commit/31e3b42c6bbce0d00f049b8a69bafc94900bb3b4))
# [2.18.0](https://github.com/revanced/revanced-patches/compare/v2.17.0...v2.18.0) (2022-07-18)
### Features
* `hide-get-premium` patch ([#195](https://github.com/revanced/revanced-patches/issues/195)) ([639aab4](https://github.com/revanced/revanced-patches/commit/639aab411ee514b50840c15c8e9a1a889854403f))
# [2.17.0](https://github.com/revanced/revanced-patches/compare/v2.16.1...v2.17.0) (2022-07-17)
### Bug Fixes
* check if node has attributes before accessing them ([2d2ed87](https://github.com/revanced/revanced-patches/commit/2d2ed870dacfe092eb6acbcaae5e51775c611322))
### Features
* `sponsorblock` patch ([#101](https://github.com/revanced/revanced-patches/issues/101)) ([36af4cc](https://github.com/revanced/revanced-patches/commit/36af4cc14ff8057c10b99019cb23acc6e5aec3f2)), closes [#89](https://github.com/revanced/revanced-patches/issues/89) [#90](https://github.com/revanced/revanced-patches/issues/90)
## [2.16.1](https://github.com/revanced/revanced-patches/compare/v2.16.0...v2.16.1) (2022-07-17)
### Bug Fixes
* bump youtube version to 17.27.39 ([b93401a](https://github.com/revanced/revanced-patches/commit/b93401a391c0ed4887dd1376ac253f74f98a8d7e))
# [2.16.0](https://github.com/revanced/revanced-patches/compare/v2.15.1...v2.16.0) (2022-07-17)
### Features
* `force-vp9-codec` patch ([#157](https://github.com/revanced/revanced-patches/issues/157)) ([07806a1](https://github.com/revanced/revanced-patches/commit/07806a16e5368118949e0e476e901987433ad403))
## [2.15.1](https://github.com/revanced/revanced-patches/compare/v2.15.0...v2.15.1) (2022-07-17)
### Bug Fixes
* `old-quality-layout` patch ([2497425](https://github.com/revanced/revanced-patches/commit/2497425c9f11b8b14c861c2f0f34ff47bdbfac53))
* references to integrations in `return-youtube-dislike` patch ([5824c2c](https://github.com/revanced/revanced-patches/commit/5824c2cdfb1a2d7b8d68044388e5e0746ef2ca09))
# [2.15.0](https://github.com/revanced/revanced-patches/compare/v2.14.1...v2.15.0) (2022-07-16)
### Features
* `return-youtube-dislikes` patch ([#175](https://github.com/revanced/revanced-patches/issues/175)) ([18a66d8](https://github.com/revanced/revanced-patches/commit/18a66d8454cf6e7cfdd4183631a6870c80d16b90))
## [2.14.1](https://github.com/revanced/revanced-patches/compare/v2.14.0...v2.14.1) (2022-07-15)
### Bug Fixes
* `codecs-unlock` patch and update Music patches to `5.14.53` ([2437d30](https://github.com/revanced/revanced-patches/commit/2437d3070f6a630d353619f642cefebd47abee20))
# [2.14.0](https://github.com/revanced/revanced-patches/compare/v2.13.6...v2.14.0) (2022-07-15)
### Features
* `music-video-ads` patch ([#172](https://github.com/revanced/revanced-patches/issues/172)) ([cbb71b5](https://github.com/revanced/revanced-patches/commit/cbb71b5faf1386ed31dd9e0387f6cf0509d92d31))
## [2.13.6](https://github.com/revanced/revanced-patches/compare/v2.13.5...v2.13.6) (2022-07-14)
## [2.13.5](https://github.com/revanced/revanced-patches/compare/v2.13.4...v2.13.5) (2022-07-14)
### Bug Fixes
* `swipe-controls` with active engagement panel ([#177](https://github.com/revanced/revanced-patches/issues/177)) ([000ec6d](https://github.com/revanced/revanced-patches/commit/000ec6d8f6ecbb910a06ec852564ee9e5f03dcf8))
## [2.13.4](https://github.com/revanced/revanced-patches/compare/v2.13.3...v2.13.4) (2022-07-13)
### Bug Fixes
* constrain `old-quality-layout` to older version ([add7232](https://github.com/revanced/revanced-patches/commit/add72326199e90f677b450b553b9d88c0bb4c490))
## [2.13.3](https://github.com/revanced/revanced-patches/compare/v2.13.2...v2.13.3) (2022-07-11)
### Bug Fixes
* `exclusive-audio-playback` patch ([#153](https://github.com/revanced/revanced-patches/issues/153)) ([9beff95](https://github.com/revanced/revanced-patches/commit/9beff9567f1586e5c58690c1f1d2f7f204025ab7))
## [2.13.2](https://github.com/revanced/revanced-patches/compare/v2.13.1...v2.13.2) (2022-07-11)
### Bug Fixes
* `hrd-auto-brightness` ([#152](https://github.com/revanced/revanced-patches/issues/152)) ([5f2e9ba](https://github.com/revanced/revanced-patches/commit/5f2e9ba30b7432be04bdc9f9f7ec7ac75fdc4b34))
## [2.13.1](https://github.com/revanced/revanced-patches/compare/v2.13.0...v2.13.1) (2022-07-11)
### Bug Fixes
* bump youtube version for swipe-controls patch ([ff207a5](https://github.com/revanced/revanced-patches/commit/ff207a57af7d3c15a8127f4465e97da23878b0d6))
# [2.13.0](https://github.com/revanced/revanced-patches/compare/v2.12.4...v2.13.0) (2022-07-11)
### Features
* `swipe-controls` rewrite ([#131](https://github.com/revanced/revanced-patches/issues/131)) ([b7dba09](https://github.com/revanced/revanced-patches/commit/b7dba09927ba15a9eacb06dcb4bf1f268560c96e))
## [2.12.4](https://github.com/revanced/revanced-patches/compare/v2.12.3...v2.12.4) (2022-07-11)
### Bug Fixes
* `autorepeat-by-default` patch ([#148](https://github.com/revanced/revanced-patches/issues/148)) ([fe628ba](https://github.com/revanced/revanced-patches/commit/fe628ba909d89ea0bf3d95fe94ca78ef819677da))
## [2.12.3](https://github.com/revanced/revanced-patches/compare/v2.12.2...v2.12.3) (2022-07-11)
### Bug Fixes
* listing of wrong fingerprint class ([#147](https://github.com/revanced/revanced-patches/issues/147)) ([95c2bbd](https://github.com/revanced/revanced-patches/commit/95c2bbdd1deb1d76f1177b48286fa6a3bc9f7663))
## [2.12.2](https://github.com/revanced/revanced-patches/compare/v2.12.1...v2.12.2) (2022-07-10)
### Bug Fixes
* display codename for patch names ([10c53f7](https://github.com/revanced/revanced-patches/commit/10c53f720df3e70b9d59e8bc3219d56b996f03db))
* incorrect package name in gradle task ([152b2c9](https://github.com/revanced/revanced-patches/commit/152b2c90cf102170648fcc168da10f46743bdc63))
* invalid regex ([26bf1d8](https://github.com/revanced/revanced-patches/commit/26bf1d818f953abc061126d8b91f17cd9008ba1d))
## [2.12.1](https://github.com/revanced/revanced-patches/compare/v2.12.0...v2.12.1) (2022-07-10) ## [2.12.1](https://github.com/revanced/revanced-patches/compare/v2.12.0...v2.12.1) (2022-07-10)
# [2.12.0](https://github.com/revanced/revanced-patches/compare/v2.11.0...v2.12.0) (2022-07-10) # [2.12.0](https://github.com/revanced/revanced-patches/compare/v2.11.0...v2.12.0) (2022-07-10)

View File

@@ -1,7 +1,8 @@
# ReVanced Patches # ReVanced Patches
🧩 Official patches by ReVanced 🧩 Official patches by ReVanced
# Patch list # List of available patches
| 💊 Patch | 📜 Description | 🎯 Target Package | 🏹 Target Version | | 💊 Patch | 📜 Description | 🎯 Target Package | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|:-----------------:| |:--------:|:--------------:|:-----------------:|:-----------------:|

View File

@@ -1,35 +1,41 @@
# ReVanced Patches # ReVanced Patches
🧩 Official patches by ReVanced 🧩 Official patches by ReVanced
# Patch list # List of available patches
| 💊 Patch | 📜 Description | 🎯 Target Package | 🏹 Target Version | | 💊 Patch | 📜 Description | 🎯 Target Package | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|:-----------------:| |:--------:|:--------------:|:-----------------:|:-----------------:|
|Fenster Swipe Controls|Adds volume and brightness swipe controls.|`com.google.android.youtube`|17.26.35| | `music-video-ads` | Removes ads in the music player. | `com.google.android.apps.youtube.music` | 5.14.53 |
|Seekbar Tapping|Enables tapping on the seekbar of the YouTube player.|`com.google.android.youtube`|17.26.35| | `exclusive-audio-playback` | Enables the option to play music without video. | `com.google.android.apps.youtube.music` | 5.14.53 |
|General Ads|Removes general ads in bytecode.|`com.google.android.youtube`|17.26.35| | `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | `com.google.android.apps.youtube.music` | 5.14.53 |
|Video Ads|Removes ads in the YouTube video player.|`com.google.android.youtube`|17.26.35| | `background-play` | Enables playing music in the background. | `com.google.android.apps.youtube.music` | 5.14.53 |
|Hide Infocard Suggestions|Hides infocards in videos.|`com.google.android.youtube`|17.26.35| | `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | `com.google.android.apps.youtube.music` | 5.14.53 |
|Autorepeat By Default|Enables auto repeating of videos by default.|`com.google.android.youtube`|17.26.35| | `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | `com.google.android.apps.youtube.music` | 5.14.53 |
|Custom Branding|Changes the branding of YouTube.|`com.google.android.youtube`|all| | `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | `com.google.android.apps.youtube.music` | 5.14.53 |
|Premium Heading|Shows premium branding on the YouTube home screen.|`com.google.android.youtube`|all| | `hide-infocard-suggestions` | Hides infocards in videos. | `com.google.android.youtube` | 17.27.39 |
|Minimized Playback|Enables minimized and background playback.|`com.google.android.youtube`|17.26.35| | `video-ads` | Removes ads in the video player. | `com.google.android.youtube` | 17.27.39 |
|Enable Wide Searchbar|Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.|`com.google.android.youtube`|17.26.35| | `general-ads` | Removes general ads. | `com.google.android.youtube` | 17.27.39 |
|Disable Fullscreen Panels|Disables comments panel in fullscreen view.|`com.google.android.youtube`|17.26.35| | `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | `com.google.android.youtube` | 17.27.39 |
|Old Quality Layout|Enables the original quality flyout menu.|`com.google.android.youtube`|17.26.35| | `swipe-controls` | Adds volume and brightness swipe controls. | `com.google.android.youtube` | 17.27.39 |
|Hide Autoplay Button|Disables the autoplay button.|`com.google.android.youtube`|17.26.35| | `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG | `com.google.android.youtube` | 17.27.39 |
|Disable Create Button|Disables the create button.|`com.google.android.youtube`|17.26.35| | `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | `com.google.android.youtube` | 17.27.39 |
|Amoled|Enables pure black theme.|`com.google.android.youtube`|17.26.35| | `autorepeat-by-default` | Enables auto repeating of videos by default. | `com.google.android.youtube` | 17.27.39 |
|Hide Shorts Button|Hides the shorts button.|`com.google.android.youtube`|17.26.35| | `custom-playback-speed` | Adds more video playback speed options. | `com.google.android.youtube` | 17.27.39 |
|Hide Cast Button|Hides the cast button.|`com.google.android.youtube`|all| | `enable-debugging` | Enables app debugging by patching the manifest file. | `com.google.android.youtube` | all |
|Hide Watermark|Hides the creator's watermark on videos.|`com.google.android.youtube`|17.26.35| | `force-vp9-codec` | Forces the VP9 codec for videos. | `com.google.android.youtube` | 17.27.39 |
|Microg Support|Allows YouTube ReVanced to run without root and under a different package name.|`com.google.android.youtube`|17.26.35| | `sponsorblock` | Integrate SponsorBlock. | `com.google.android.youtube` | 17.27.39 |
|Custom Playback Speed|Allows to change the default playback speed options.|`com.google.android.youtube`|17.26.35| | `old-quality-layout` | Enables the original quality flyout menu. | `com.google.android.youtube` | 17.27.39 |
|Hdr Max Brightness|Sets brightness to max for HDR videos in fullscreen mode.|`com.google.android.youtube`|17.26.35| | `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | `com.google.android.youtube` | 17.27.39 |
|Enable Debugging|Enables app debugging by patching the manifest file.|`com.google.android.youtube`|all| | `hide-cast-button` | Hides the cast button in the video player. | `com.google.android.youtube` | all |
|Background Play|Enables playing music in the background.|`com.google.android.apps.youtube.music`|5.03.50| | `amoled` | Enables pure black theme. | `com.google.android.youtube` | 17.27.39 |
|Exclusive Audio Playback|Adds the option to play music without video.|`com.google.android.apps.youtube.music`|5.03.50| | `hide-autoplay-button` | Hides the autoplay button in the video player. | `com.google.android.youtube` | 17.27.39 |
|Codecs Unlock|Enables more audio codecs. Usually results in better audio quality but may depend on song and device.|`com.google.android.apps.youtube.music`|5.03.50| | `minimized-playback` | Enables minimized and background playback. | `com.google.android.youtube` | 17.27.39 |
|Upgrade Button Remover|Removes the upgrade tab from the pivot bar in YouTube music.|`com.google.android.apps.youtube.music`|5.03.50| | `premium-heading` | Shows premium branding on the home screen. | `com.google.android.youtube` | all |
|TasteBuilder Remover|Removes the "Tell us which artists you like" card from the Home screen. The same functionality can be triggered from the settings anyway.|`com.google.android.apps.youtube.music`|5.03.50| | `custom-branding` | Changes the YouTube launcher icon to be ReVanced's. | `com.google.android.youtube` | all |
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | `com.google.android.youtube` | 17.27.39 |
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | `com.google.android.youtube` | 17.27.39 |
| `hide-shorts-button` | Hides the shorts button on the navigation bar. | `com.google.android.youtube` | 17.27.39 |
| `disable-create-button` | Hides the create button in the navigation bar. | `com.google.android.youtube` | 17.27.39 |
| `hide-watermark` | Hides creator's watermarks on videos. | `com.google.android.youtube` | 17.27.39 |

View File

@@ -54,7 +54,7 @@ tasks {
dependsOn(build) dependsOn(build)
classpath = sourceSets["main"].runtimeClasspath classpath = sourceSets["main"].runtimeClasspath
mainClass.set("app.revanced.patches.meta.readme.Generator") mainClass.set("app.revanced.meta.readme.Generator")
} }
// Dummy task to fix the Gradle semantic-release plugin. // Dummy task to fix the Gradle semantic-release plugin.
// Remove this if you forked it to support building only. // Remove this if you forked it to support building only.

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 2.12.1 version = 2.18.2

View File

@@ -1,6 +1,6 @@
package app.revanced.extensions package app.revanced.extensions
import app.revanced.patcher.data.impl.BytecodeData import app.revanced.patcher.data.impl.ResourceData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
@@ -14,7 +14,10 @@ import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
import org.w3c.dom.Node import org.w3c.dom.Node
import java.io.OutputStream
import java.nio.file.Files
// TODO: this method does not make sense here
internal fun MutableMethodImplementation.injectHideCall( internal fun MutableMethodImplementation.injectHideCall(
index: Int, index: Int,
register: Int register: Int
@@ -100,37 +103,65 @@ internal fun MutableMethod.injectConsumableEventHook(hookRef: ImmutableMethodRef
} }
/** /**
* Insert instructions into a named method * inject resources into the patched app
* *
* @param targetClass the name of the class of which the method is a member * @param classLoader classloader to use for loading the resources
* @param targetMethod the name of the method to insert into * @param patchDirectoryPath path to the files. this will be the directory you created under the 'resources' source folder
* @param index index to insert the instructions at. If the index is negative, it is used as an offset to the last method (so -1 inserts at the end of the method) * @param resourceType the resource type, for example 'drawable'. this has to match both the source and the target
* @param instructions the smali instructions to insert (they'll be compiled by MutableMethod.addInstructions) * @param resourceFileNames names of all resources of this type to inject
*/ */
internal fun BytecodeData.injectIntoNamedMethod( fun ResourceData.injectResources(
targetClass: String, classLoader: ClassLoader,
targetMethod: String, patchDirectoryPath: String,
index: Int, resourceType: String,
instructions: String resourceFileNames: List<String>
) { ) {
var injections = 0 resourceFileNames.forEach { name ->
this.classes.filter { it.type.endsWith("$targetClass;") }.forEach { classDef -> val relativePath = "$resourceType/$name"
this.proxy(classDef).resolve().methods.filter { it.name == targetMethod }.forEach { methodDef -> val sourceRes = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath")
// if index is negative, interpret as an offset from the back ?: throw PatchResultError("could not open resource '$patchDirectoryPath/$relativePath'")
var insertIndex = index
if (insertIndex < 0) {
insertIndex += methodDef.implementation!!.instructions.size
}
// insert instructions Files.copy(
methodDef.addInstructions(insertIndex, instructions) sourceRes,
injections++ this["res"].resolve(relativePath).toPath()
} )
} }
}
// fail if nothing was injected /**
if (injections <= 0) { * inject strings into the patched app
throw PatchResultError("failed to inject into $targetClass.$targetMethod: no targets were found") *
* @param classLoader classloader to use for loading the resources
* @param patchDirectoryPath path to the files. this will be the directory you created under the 'resources' source folder
* @param languageIdentifier ISO 639-2 two- letter language code identifier (aka the one android uses for values directory)
*/
fun ResourceData.injectStrings(
classLoader: ClassLoader,
patchDirectoryPath: String,
languageIdentifier: String? = null,
) {
val relativePath =
if (languageIdentifier.isNullOrBlank()) "values/strings.xml" else "values/strings-$languageIdentifier.xml"
// open source strings.xml
val sourceInputStream = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath")
?: throw PatchResultError("failed to open '$patchDirectoryPath/$relativePath'")
xmlEditor[sourceInputStream, OutputStream.nullOutputStream()].use { sourceStringsXml ->
val strings = sourceStringsXml.file.getElementsByTagName("resources").item(0).childNodes
// open target strings.xml
xmlEditor["res/$relativePath"].use { targetStringsXml ->
val targetFile = targetStringsXml.file
val targetRootNode = targetFile.getElementsByTagName("resources").item(0)
// process all children strings in the source
for (i in 0 until strings.length) {
// clone the node from source to target
val node = strings.item(i).cloneNode(true)
targetFile.adoptNode(node)
targetRootNode.appendChild(node)
}
}
} }
} }

View File

@@ -1,41 +1,41 @@
package app.revanced.patches.meta.readme package app.revanced.meta.readme
import java.io.File
import kotlin.io.writeText
import kotlin.collections.first
import app.revanced.patcher.util.patch.implementation.JarPatchBundle
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.extensions.PatchExtensions.description import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.util.patch.implementation.JarPatchBundle
import java.io.File
class Generator { class Generator {
companion object { companion object {
@JvmStatic @JvmStatic
fun main(args: Array<String>) { fun main(args: Array<String>) {
val buildDir = File("build/libs/") val buildDir = File("build/libs/")
val buildJar = buildDir.listFiles().first { it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar") } val buildJar =
buildDir.listFiles()?.first { it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar") }!!
val bundle = JarPatchBundle(buildJar.absolutePath).loadPatches() val bundle = JarPatchBundle(buildJar.absolutePath).loadPatches()
val table = StringBuilder() val patches = StringBuilder()
for (patch in bundle) { for (patch in bundle) {
val humanName = val patchName = patch.patchName
patch.patchName.split('-').map { it.replaceFirstChar { it.uppercase() } }.joinToString(" ")
val compatiblePackage = patch.compatiblePackages?.first() val compatiblePackage = patch.compatiblePackages?.first()
val latestVersion = compatiblePackage?.versions?.maxByOrNull { it.replace(".", "").toInt() } ?: "all" val latestVersion =
compatiblePackage?.versions?.map { SemanticVersion.fromString(it) }?.maxWithOrNull(
SemanticVersionComparator
) ?: "all"
table.appendLine("|$humanName|${patch.description}|`${compatiblePackage?.name}`|$latestVersion|") patches.appendLine("| `$patchName` | ${patch.description} | `${compatiblePackage?.name}` | $latestVersion |")
} }
val readMeTemplateFile = File("README-template.md") val readMeTemplateFile = File("README-template.md")
val readMeTemplate = Template(readMeTemplateFile.readText()) val readmeTemplate = Template(readMeTemplateFile.readText())
readMeTemplate.replaceVariable("table", table.toString()) readmeTemplate.replaceVariable("table", patches.toString())
val readMeFile = File("README.md") val readme = File("README.md")
readMeFile.writeText(readMeTemplate.toString()) readme.writeText(readmeTemplate.toString())
} }
} }
} }

View File

@@ -0,0 +1,24 @@
package app.revanced.meta.readme
data class SemanticVersion(val major: Int, val minor: Int, val patch: Int) {
companion object {
fun fromString(version: String): SemanticVersion {
var parts = version.split(".")
if (parts.count() != 3) throw IllegalArgumentException("Invalid semantic version")
val versionNumbers = parts.map { it.toInt() }
return SemanticVersion(versionNumbers[0], versionNumbers[1], versionNumbers[2])
}
}
override fun toString(): String = "$major.$minor.$patch"
}
object SemanticVersionComparator : Comparator<SemanticVersion> {
override fun compare(a: SemanticVersion, b: SemanticVersion): Int = when {
a.major != b.major -> a.major - b.major
a.minor != b.minor -> a.minor - b.minor
else -> a.patch - b.patch
}
}

View File

@@ -1,13 +1,13 @@
package app.revanced.patches.meta.readme package app.revanced.meta.readme
class Template(val template: String) { class Template(template: String) {
val result: StringBuilder = StringBuilder(template) val result: StringBuilder = StringBuilder(template)
fun replaceVariable(name: String, value: String) { fun replaceVariable(name: String, value: String) {
val regex = Regex("\\{\\{\\s?$name\\s?\\}\\}") val regex = Regex("\\{\\{\\s?$name\\s?}}")
val range = regex.find(result)!!.range val range = regex.find(result)!!.range
result.replace(range.start, range.endInclusive + 1, value) result.replace(range.first, range.last + 1, value)
} }
override fun toString(): String = result.toString() override fun toString(): String = result.toString()

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.music.ad.video.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class MusicVideoAdsCompatibility

View File

@@ -0,0 +1,39 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("show-video-ads-constructor-fingerprint")
@MatchingMethod(
"Laghd;",
"<init>",
)
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
@MusicVideoAdsCompatibility
@Version("0.0.1")
object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
Opcode.INVOKE_DIRECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.CONST_4,
Opcode.IPUT_BOOLEAN,
Opcode.RETURN_VOID
)
)

View File

@@ -0,0 +1,26 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("show-video-ads-method-fingerprint")
@MatchingMethod(
"Laghd;", "d"
)
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
@MusicVideoAdsCompatibility
@Version("0.0.1")
object ShowMusicVideoAdsFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf(
Opcode.IPUT_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
)
)

View File

@@ -0,0 +1,40 @@
package app.revanced.patches.music.ad.video.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
@Patch
@Name("music-video-ads")
@Description("Removes ads in the music player.")
@MusicVideoAdsCompatibility
@Version("0.0.1")
class MusicVideoAdsPatch : BytecodePatch(
listOf(
ShowMusicVideoAdsConstructorFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {
ShowMusicVideoAdsFingerprint.resolve(data, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
val result = ShowMusicVideoAdsFingerprint.result!!
result.mutableMethod.addInstructions(
result.patternScanResult!!.startIndex, """
const/4 p1, 0x0
"""
)
return PatchResultSuccess()
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.apps.youtube.music", arrayOf("5.03.50") "com.google.android.apps.youtube.music", arrayOf("5.14.53")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -20,8 +20,9 @@ import org.jf.dexlib2.Opcode
@Version("0.0.1") @Version("0.0.1")
object CodecsLockFingerprint : MethodFingerprint( object CodecsLockFingerprint : MethodFingerprint(
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L", "L"), listOf( "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L", "L"), listOf(
Opcode.INVOKE_STATIC, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
@@ -29,18 +30,11 @@ object CodecsLockFingerprint : MethodFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.SGET, Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,
Opcode.RETURN_OBJECT Opcode.RETURN_OBJECT
) )

View File

@@ -16,7 +16,7 @@ import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprin
@Patch @Patch
@Name("codecs-unlock") @Name("codecs-unlock")
@Description("Enables more audio codecs. Usually results in better audio quality but may depend on song and device.") @Description("Adds more audio codec options. The new audio codecs usually result in better audio quality.")
@CodecsUnlockCompatibility @CodecsUnlockCompatibility
@Version("0.0.1") @Version("0.0.1")
class CodecsUnlockPatch : BytecodePatch( class CodecsUnlockPatch : BytecodePatch(

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.apps.youtube.music", arrayOf("5.03.50") "com.google.android.apps.youtube.music", arrayOf("5.14.53")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -17,18 +17,16 @@ import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.ExclusiveAud
@Patch @Patch
@Name("exclusive-audio-playback") @Name("exclusive-audio-playback")
@Description("Adds the option to play music without video.") @Description("Enables the option to play music without video.")
@ExclusiveAudioCompatibility @ExclusiveAudioCompatibility
@Version("0.0.1") @Version("0.0.1")
class ExclusiveAudioPatch : BytecodePatch( class ExclusiveAudioPatch : BytecodePatch(
listOf( listOf(
ExclusiveAudioFingerprint AudioOnlyEnablerFingerprint
) )
) { ) {
override fun execute(data: BytecodeData): PatchResult { override fun execute(data: BytecodeData): PatchResult {
ExclusiveAudioFingerprint.resolve(data, AudioOnlyEnablerFingerprint.result!!.classDef) val method = AudioOnlyEnablerFingerprint.result!!.mutableMethod
val method = ExclusiveAudioFingerprint.result!!.mutableMethod
method.replaceInstruction(method.implementation!!.instructions.count() - 1, "const/4 v0, 0x1") method.replaceInstruction(method.implementation!!.instructions.count() - 1, "const/4 v0, 0x1")
method.addInstruction("return v0") method.addInstruction("return v0")

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.music.layout.premium.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.apps.youtube.music", arrayOf("5.14.53")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class HideGetPremiumCompatibility

View File

@@ -0,0 +1,26 @@
package app.revanced.patches.music.layout.premium.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("hide-get-premium-fingerprint")
@MatchingMethod(
"Lktn;", "k"
)
@HideGetPremiumCompatibility
@Version("0.0.1")
object HideGetPremiumFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
Opcode.IF_NEZ,
Opcode.CONST_16,
Opcode.GOTO,
Opcode.NOP,
Opcode.INVOKE_VIRTUAL
)
)

View File

@@ -0,0 +1,29 @@
package app.revanced.patches.music.layout.premium.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("hide-get-premium-parent-fingerprint")
@MatchingMethod(
"Lktn;", "k"
)
@HideGetPremiumCompatibility
@Version("0.0.1")
object HideGetPremiumParentFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC
),
listOf("FEmusic_history"),
)

View File

@@ -0,0 +1,49 @@
package app.revanced.patches.music.layout.premium.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
@Patch
@Name("hide-get-premium")
@Description("Removes all \"Get Premium\" evidences from the avatar menu.")
@HideGetPremiumCompatibility
@Version("0.0.1")
class HideGetPremiumPatch : BytecodePatch(
listOf(
HideGetPremiumParentFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {
val parentResult = HideGetPremiumParentFingerprint.result!!
HideGetPremiumFingerprint.resolve(data, parentResult.classDef)
val parentMethod = parentResult.mutableMethod
parentMethod.replaceInstruction(
parentResult.patternScanResult!!.startIndex, """
const/4 v1, 0x0
"""
)
val result = HideGetPremiumFingerprint.result!!
val method = result.mutableMethod
method.addInstructions(
result.patternScanResult!!.startIndex, """
const/16 v0, 0x8
"""
)
return PatchResultSuccess()
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.apps.youtube.music", arrayOf("5.03.50") "com.google.android.apps.youtube.music", arrayOf("5.14.53")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -15,7 +15,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction22c
@Patch @Patch
@Name("tasteBuilder-remover") @Name("tasteBuilder-remover")
@Description("Removes the \"Tell us which artists you like\" card from the Home screen. The same functionality can be triggered from the settings anyway.") @Description("Removes the \"Tell us which artists you like\" card from the home screen.")
@RemoveTasteBuilderCompatibility @RemoveTasteBuilderCompatibility
@Version("0.0.1") @Version("0.0.1")
class RemoveTasteBuilderPatch : BytecodePatch( class RemoveTasteBuilderPatch : BytecodePatch(

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.apps.youtube.music", arrayOf("5.03.50") "com.google.android.apps.youtube.music", arrayOf("5.14.53")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -20,7 +20,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch @Patch
@Name("upgrade-button-remover") @Name("upgrade-button-remover")
@Description("Removes the upgrade tab from the pivot bar in YouTube music.") @Description("Removes the upgrade tab from the pivot bar.")
@RemoveUpgradeButtonCompatibility @RemoveUpgradeButtonCompatibility
@Version("0.0.1") @Version("0.0.1")
class RemoveUpgradeButtonPatch : BytecodePatch( class RemoveUpgradeButtonPatch : BytecodePatch(

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.apps.youtube.music", arrayOf("5.03.50") "com.google.android.apps.youtube.music", arrayOf("5.14.53")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -38,11 +38,9 @@ import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
@Patch @Patch
@Dependencies( @Dependencies([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
dependencies = [ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class]
)
@Name("general-ads") @Name("general-ads")
@Description("Removes general ads in bytecode.") @Description("Removes general ads.")
@GeneralAdsCompatibility @GeneralAdsCompatibility
@Version("0.0.1") @Version("0.0.1")
class GeneralBytecodeAdsPatch : BytecodePatch() { class GeneralBytecodeAdsPatch : BytecodePatch() {
@@ -60,7 +58,7 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
"promoted_video_item_land", "promoted_video_item_land",
"promoted_video_item_full_bleed", "promoted_video_item_full_bleed",
).map { name -> ).map { name ->
ResourceIdMappingProviderResourcePatch.resourceMappings.first { it.name == name }.id ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.name == name }.id
} }
private val stringReferences = arrayOf( private val stringReferences = arrayOf(
@@ -129,6 +127,7 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
if (mutableMethod == null) mutableMethod = if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method) mutableClass!!.findMutableMethodOf(method)
//ToDo: Add Settings toggle for whatever this is
mutableMethod!!.implementation!!.removeInstruction(removeIndex) mutableMethod!!.implementation!!.removeInstruction(removeIndex)
} }
@@ -188,6 +187,7 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
// return the method // return the method
val insertIndex = 1 // after super constructor val insertIndex = 1 // after super constructor
//ToDo: Add setting here
mutableMethod!!.implementation!!.addInstruction( mutableMethod!!.implementation!!.addInstruction(
insertIndex, BuilderInstruction10x(Opcode.RETURN_VOID) insertIndex, BuilderInstruction10x(Opcode.RETURN_VOID)
) )

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -4,24 +4,22 @@ 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.impl.BytecodeData import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfocardSuggestionsCompatibility import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfocardSuggestionsCompatibility
import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsFingerprint import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsFingerprint
import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsParentFingerprint import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("hide-infocard-suggestions") @Name("hide-infocard-suggestions")
@Description("Hides infocards in videos.") @Description("Hides infocards in videos.")
@HideInfocardSuggestionsCompatibility @HideInfocardSuggestionsCompatibility
@@ -45,17 +43,10 @@ class HideInfocardSuggestionsPatch : BytecodePatch(
?: return PatchResultError("Implementation not found.") ?: return PatchResultError("Implementation not found.")
val index = implementation.instructions.indexOfFirst { ((it as? BuilderInstruction35c)?.reference.toString() == "Landroid/view/View;->setVisibility(I)V") } val index = implementation.instructions.indexOfFirst { ((it as? BuilderInstruction35c)?.reference.toString() == "Landroid/view/View;->setVisibility(I)V") }
val register = "v" + (implementation.instructions.get(index) as FiveRegisterInstruction).registerD
method.removeInstruction(index) method.replaceInstruction(index, """
invoke-static {p1}, Lapp/revanced/integrations/patches/HideInfoCardSuggestionsPatch;->hideInfoCardSuggestions(Landroid/view/View;)V
method.addInstructions( """)
index, """
invoke-static {}, Lapp/revanced/integrations/patches/HideInfoCardSuggestionsPatch;->hideInfoCardSuggestions()I
move-result $register
invoke-virtual {p1, $register}, Landroid/view/View;->setVisibility(I)V
"""
)
return PatchResultSuccess() return PatchResultSuccess()
} }

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -17,9 +17,9 @@ import app.revanced.patches.youtube.ad.video.fingerprints.ShowVideoAdsFingerprin
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("video-ads") @Name("video-ads")
@Description("Removes ads in the YouTube video player.") @Description("Removes ads in the video player.")
@VideoAdsCompatibility @VideoAdsCompatibility
@Version("0.0.1") @Version("0.0.1")
class VideoAdsPatch : BytecodePatch( class VideoAdsPatch : BytecodePatch(

View File

@@ -1,121 +0,0 @@
package app.revanced.patches.youtube.interaction.fenster.patch
import app.revanced.extensions.injectConsumableEventHook
import app.revanced.extensions.injectIntoNamedMethod
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.interaction.fenster.annotation.FensterCompatibility
import app.revanced.patches.youtube.interaction.fenster.fingerprints.UpdatePlayerTypeFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
@Patch
@Name("fenster-swipe-controls")
@Description("Adds volume and brightness swipe controls.")
@FensterCompatibility
@Version("0.0.1")
@Dependencies(dependencies = [IntegrationsPatch::class])
class FensterPatch : BytecodePatch(
listOf(
UpdatePlayerTypeFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {
// hook WatchWhileActivity.onStart (main activity lifecycle hook)
data.injectIntoNamedMethod(
"com/google/android/apps/youtube/app/watchwhile/WatchWhileActivity",
"onStart",
0,
"invoke-static { p0 }, Lapp/revanced/integrations/patches/FensterSwipePatch;->WatchWhileActivity_onStartHookEX(Ljava/lang/Object;)V"
)
// hook YoutubePlayerOverlaysLayout.onFinishInflate (player overlays init hook)
data.injectIntoNamedMethod(
"com/google/android/apps/youtube/app/common/player/overlay/YouTubePlayerOverlaysLayout",
"onFinishInflate",
-2,
"invoke-static { p0 }, Lapp/revanced/integrations/patches/FensterSwipePatch;->YouTubePlayerOverlaysLayout_onFinishInflateHookEX(Ljava/lang/Object;)V"
)
// hook YoutubePlayerOverlaysLayout.UpdatePlayerType
injectUpdatePlayerTypeHook(
UpdatePlayerTypeFingerprint.result!!,
"com/google/android/apps/youtube/app/common/player/overlay/YouTubePlayerOverlaysLayout"
)
// hook NextGenWatchLayout.onTouchEvent and NextGenWatchLayout.onInterceptTouchEvent (player touch event hook)
injectWatchLayoutTouchHooks(
data,
"com/google/android/apps/youtube/app/watch/nextgenwatch/ui/NextGenWatchLayout"
)
return PatchResultSuccess()
}
@Suppress("SameParameterValue")
private fun injectUpdatePlayerTypeHook(fingerPrintResult: MethodFingerprintResult, targetClass: String) {
// validate fingerprint found the right class
if (!fingerPrintResult.classDef.type.endsWith("$targetClass;")) {
throw PatchResultError("$targetClass.UpdatePlayerType fingerprint could not be validated")
}
// insert the hook
fingerPrintResult.mutableMethod.addInstruction(
0,
"invoke-static { p1 }, Lapp/revanced/integrations/patches/FensterSwipePatch;->YouTubePlayerOverlaysLayout_updatePlayerTypeHookEX(Ljava/lang/Object;)V"
)
}
/**
* Inject onTouch event hooks into the watch layout class
*
* @param data bytecode data
* @param targetClass watch layout class name
*/
@Suppress("SameParameterValue")
private fun injectWatchLayoutTouchHooks(data: BytecodeData, targetClass: String) {
var touchHooksCount = 0
data.classes.filter { it.type.endsWith("$targetClass;") }.forEach { classDef ->
// hook onTouchEvent
data.proxy(classDef).resolve().methods.filter { it.name == "onTouchEvent" }.forEach { methodDef ->
touchHooksCount++
methodDef.injectConsumableEventHook(
ImmutableMethodReference(
"Lapp/revanced/integrations/patches/FensterSwipePatch;",
"NextGenWatchLayout_onTouchEventHookEX",
listOf("Ljava/lang/Object;", "Ljava/lang/Object;"),
"Z"
)
)
}
// hook onInterceptTouchEvent
data.proxy(classDef).resolve().methods.filter { it.name == "onInterceptTouchEvent" }.forEach { methodDef ->
touchHooksCount++
methodDef.injectConsumableEventHook(
ImmutableMethodReference(
"Lapp/revanced/integrations/patches/FensterSwipePatch;",
"NextGenWatchLayout_onInterceptTouchEventHookEX",
listOf("Ljava/lang/Object;", "Ljava/lang/Object;"),
"Z"
)
)
}
}
// fail if no touch hooks were inserted
if (touchHooksCount <= 0) {
throw PatchResultError("failed to inject onTouchEvent hook into NextGenWatchLayout: none found")
}
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -22,9 +22,9 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction11n
import org.jf.dexlib2.iface.instruction.formats.Instruction35c import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("seekbar-tapping") @Name("seekbar-tapping")
@Description("Enables tapping on the seekbar of the YouTube player.") @Description("Enables tap-to-seek on the seekbar of the video player.")
@SeekbarTappingCompatibility @SeekbarTappingCompatibility
@Version("0.0.1") @Version("0.0.1")
class EnableSeekbarTappingPatch : BytecodePatch( class EnableSeekbarTappingPatch : BytecodePatch(

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.interaction.swipecontrols.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.24.34", "17.25.34", "17.26.35", "17.27.39")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class SwipeControlsCompatibility

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.youtube.interaction.swipecontrols.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
@Name("watch-while-onStart-fingerprint")
@MatchingMethod(
"LWatchWhileActivity;", "onCreate"
)
@DirectPatternScanMethod
@SwipeControlsCompatibility
@Version("0.0.1")
object WatchWhileOnStartFingerprint : MethodFingerprint(
null, null, null, null, null, { methodDef ->
methodDef.definingClass.endsWith("WatchWhileActivity;") && methodDef.name == "onStart"
}
)

View File

@@ -0,0 +1,45 @@
package app.revanced.patches.youtube.interaction.swipecontrols.patch.bytecode
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.WatchWhileOnStartFingerprint
import app.revanced.patches.youtube.interaction.swipecontrols.patch.resource.SwipeControlsResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.patch.PlayerOverlaysHookPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
@Patch
@Name("swipe-controls")
@Description("Adds volume and brightness swipe controls.")
@SwipeControlsCompatibility
@Version("0.0.2")
@Dependencies(
[
IntegrationsPatch::class,
PlayerTypeHookPatch::class,
PlayerOverlaysHookPatch::class,
SwipeControlsResourcePatch::class
]
)
class SwipeControlsBytecodePatch : BytecodePatch(
listOf(
WatchWhileOnStartFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {
WatchWhileOnStartFingerprint.result!!.mutableMethod.addInstruction(
0,
"invoke-static { p0 }, Lapp/revanced/integrations/patches/SwipeControlsPatch;->WatchWhileActivity_onStartHookEX(Ljava/lang/Object;)V"
)
return PatchResultSuccess()
}
}

View File

@@ -0,0 +1,32 @@
package app.revanced.patches.youtube.interaction.swipecontrols.patch.resource
import app.revanced.extensions.injectResources
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.ResourceData
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.impl.ResourcePatch
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
@Name("swipe-controls-resource-patch")
@SwipeControlsCompatibility
@Version("0.0.1")
class SwipeControlsResourcePatch : ResourcePatch() {
override fun execute(data: ResourceData): PatchResult {
val resourcesDir = "swipecontrols"
data.injectResources(
this.javaClass.classLoader,
resourcesDir,
"drawable",
listOf(
"ic_sc_brightness_auto",
"ic_sc_brightness_manual",
"ic_sc_volume_mute",
"ic_sc_volume_normal"
).map { "$it.xml" }
)
return PatchResultSuccess()
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -15,11 +15,7 @@ import org.w3c.dom.Element
import java.io.File import java.io.File
@Patch @Patch
@Dependencies( @Dependencies([FixLocaleConfigErrorPatch::class])
dependencies = [
FixLocaleConfigErrorPatch::class
]
)
@Name("amoled") @Name("amoled")
@Description("Enables pure black theme.") @Description("Enables pure black theme.")
@AmoledCompatibility @AmoledCompatibility

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -4,23 +4,27 @@ 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.impl.BytecodeData import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.removeInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.extensions.replaceInstructions import app.revanced.patcher.extensions.replaceInstructions
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.Dependencies import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutonavInformerFingerprint import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutonavInformerFingerprint
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch @Patch
@Dependencies(dependencies = [ResourceIdMappingProviderResourcePatch::class]) @Dependencies([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
@Name("hide-autoplay-button") @Name("hide-autoplay-button")
@Description("Disables the autoplay button.") @Description("Hides the autoplay button in the video player.")
@AutoplayButtonCompatibility @AutoplayButtonCompatibility
@Version("0.0.1") @Version("0.0.1")
class HideAutoplayButton : BytecodePatch( class HideAutoplayButton : BytecodePatch(
@@ -32,30 +36,50 @@ class HideAutoplayButton : BytecodePatch(
val layoutGenMethod = LayoutConstructorFingerprint.result!!.mutableMethod val layoutGenMethod = LayoutConstructorFingerprint.result!!.mutableMethod
val autonavToggle = val autonavToggle =
ResourceIdMappingProviderResourcePatch.resourceMappings.first { it.type == "id" && it.name == "autonav_toggle" } ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "autonav_toggle" }
val autonavPreviewStub = val autonavPreviewStub =
ResourceIdMappingProviderResourcePatch.resourceMappings.first { it.type == "id" && it.name == "autonav_preview_stub" } ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "autonav_preview_stub" }
val instructions = layoutGenMethod.implementation!!.instructions
val autonavToggleConstIndex = val autonavToggleConstIndex =
layoutGenMethod.implementation!!.instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavToggle.id } instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavToggle.id } + 4
val autonavPreviewStubConstIndex = val autonavPreviewStubConstIndex =
layoutGenMethod.implementation!!.instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavPreviewStub.id } instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavPreviewStub.id } + 4
//remove adding autoplay button to the layout injectIfBranch(layoutGenMethod, autonavToggleConstIndex)
layoutGenMethod.removeInstructions(autonavToggleConstIndex, 5) injectIfBranch(layoutGenMethod, autonavPreviewStubConstIndex)
layoutGenMethod.removeInstructions(autonavPreviewStubConstIndex, 5)
val autonavInformerMethod = AutonavInformerFingerprint.result!!.mutableMethod val autonavInformerMethod = AutonavInformerFingerprint.result!!.mutableMethod
//force disable autoplay since it's hard to do without the button //force disable autoplay since it's hard to do without the button
autonavInformerMethod.replaceInstructions( autonavInformerMethod.replaceInstructions(
0, 0, """
""" invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonHidden()Z
const/4 v0, 0x0 move-result v0
return v0 return v0
""" """
) )
return PatchResultSuccess() return PatchResultSuccess()
} }
private fun injectIfBranch(method: MutableMethod, index: Int) {
val instructions = method.implementation!!.instructions
val insn = (instructions.get(index) as? Instruction35c)!!
val methodToCall = insn.reference.toString()
//remove the invoke-virtual because we want to put it in an if-statement
method.removeInstruction(index)
method.addInstructions(
index, """
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
move-result v11
if-eqz v11, :hidebutton
invoke-virtual {v${insn.registerC}, v${insn.registerD}, v${insn.registerE}}, $methodToCall
:hidebutton
nop
"""
)
}
} }

View File

@@ -17,11 +17,9 @@ import java.nio.file.StandardCopyOption
import kotlin.io.path.exists import kotlin.io.path.exists
@Patch @Patch
@Dependencies( @Dependencies([FixLocaleConfigErrorPatch::class])
dependencies = [FixLocaleConfigErrorPatch::class]
)
@Name("premium-heading") @Name("premium-heading")
@Description("Shows premium branding on the YouTube home screen.") @Description("Shows premium branding on the home screen.")
@PremiumHeadingCompatibility @PremiumHeadingCompatibility
@Version("0.0.1") @Version("0.0.1")
class PremiumHeadingPatch : ResourcePatch() { class PremiumHeadingPatch : ResourcePatch() {
@@ -34,7 +32,7 @@ class PremiumHeadingPatch : ResourcePatch() {
arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi").forEach { size -> arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi").forEach { size ->
val headingDirectory = resDirectory.resolve("drawable-$size") val headingDirectory = resDirectory.resolve("drawable-$size")
modes.forEach {mode -> modes.forEach { mode ->
val fromPath = headingDirectory.resolve("${original}_$mode.png").toPath() val fromPath = headingDirectory.resolve("${original}_$mode.png").toPath()
val toPath = headingDirectory.resolve("${replacement}_$mode.png").toPath() val toPath = headingDirectory.resolve("${replacement}_$mode.png").toPath()

View File

@@ -15,11 +15,9 @@ import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatc
import java.nio.file.Files import java.nio.file.Files
@Patch @Patch
@Dependencies( @Dependencies([FixLocaleConfigErrorPatch::class])
dependencies = [FixLocaleConfigErrorPatch::class]
)
@Name("custom-branding") @Name("custom-branding")
@Description("Changes the branding of YouTube.") @Description("Changes the YouTube launcher icon to be ReVanced's.")
@CustomBrandingCompatibility @CustomBrandingCompatibility
@Version("0.0.1") @Version("0.0.1")
class CustomBrandingPatch : ResourcePatch() { class CustomBrandingPatch : ResourcePatch() {

View File

@@ -14,9 +14,9 @@ import app.revanced.patches.youtube.layout.castbutton.annotations.CastButtonComp
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("hide-cast-button") @Name("hide-cast-button")
@Description("Hides the cast button.") @Description("Hides the cast button in the video player.")
@CastButtonCompatibility @CastButtonCompatibility
@Version("0.0.1") @Version("0.0.1")
class HideCastButtonPatch : BytecodePatch() { class HideCastButtonPatch : BytecodePatch() {

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -22,9 +22,9 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class]) @Dependencies([IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class])
@Name("disable-create-button") @Name("disable-create-button")
@Description("Disables the create button.") @Description("Hides the create button in the navigation bar.")
@CreateButtonCompatibility @CreateButtonCompatibility
@Version("0.0.1") @Version("0.0.1")
class CreateButtonRemoverPatch : BytecodePatch( class CreateButtonRemoverPatch : BytecodePatch(
@@ -39,7 +39,7 @@ class CreateButtonRemoverPatch : BytecodePatch(
val implementation = result.mutableMethod.implementation!! val implementation = result.mutableMethod.implementation!!
val imageOnlyLayout = val imageOnlyLayout =
ResourceIdMappingProviderResourcePatch.resourceMappings.first { it.type == "layout" && it.name == "image_only_tab" } ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "layout" && it.name == "image_only_tab" }
val imageOnlyLayoutConstIndex = val imageOnlyLayoutConstIndex =
implementation.instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == imageOnlyLayout.id } implementation.instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == imageOnlyLayout.id }

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -4,47 +4,47 @@ 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.impl.BytecodeData import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.layout.fullscreenpanels.annotations.FullscreenPanelsCompatibility import app.revanced.patches.youtube.layout.fullscreenpanels.annotations.FullscreenPanelsCompatibility
import app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints.FullscreenViewAdderFingerprint import app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints.FullscreenViewAdderFingerprint
import org.jf.dexlib2.Opcode import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
@Patch @Patch
@Name("disable-fullscreen-panels") @Name("disable-fullscreen-panels")
@Description("Disables comments panel in fullscreen view.") @Dependencies([IntegrationsPatch::class])
@Description("Disables video description and comments panel in fullscreen view.")
@FullscreenPanelsCompatibility @FullscreenPanelsCompatibility
@Version("0.0.1") @Version("0.0.1")
class FullscreenPanelsRemovalPatch : BytecodePatch( class FullscreenPanelsRemoverPatch : BytecodePatch(
listOf( listOf(
FullscreenViewAdderFingerprint FullscreenViewAdderFingerprint
) )
) { ) {
override fun execute(data: BytecodeData): PatchResult { override fun execute(data: BytecodeData): PatchResult {
val method = FullscreenViewAdderFingerprint.result?.mutableMethod!! val result = FullscreenViewAdderFingerprint.result
val implementation = method.implementation!! ?: return PatchResultError("Fingerprint not resolved!")
val (visibilityCallIndex, visibilityCall) = val method = result.mutableMethod
implementation.instructions.withIndex() val implementation = method.implementation
.first { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.name == ("setVisibility") } ?: return PatchResultError("Implementation not found!")
val gotoIndex = val visibilityCallIndex = implementation.instructions.withIndex()
implementation.instructions.subList(0, visibilityCallIndex).indexOfLast { it.opcode == Opcode.GOTO } .first { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.name == ("setVisibility") }.index
//force the if method.addInstructions(
method.removeInstruction(gotoIndex) visibilityCallIndex - 1, """
invoke-static { }, Lapp/revanced/integrations/patches/FullscreenPanelsRemoverPatch;->getFullsceenPanelsVisibility()I
val visibilityIntRegister = (visibilityCall as FiveRegisterInstruction).registerD move-result p1
"""
//set the visibility to GONE )
method.addInstruction(visibilityCallIndex - 1, "const/16 v$visibilityIntRegister, 0x8")
return PatchResultSuccess() return PatchResultSuccess()
} }

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -0,0 +1,34 @@
package app.revanced.patches.youtube.layout.minimizedplayback.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("minimized-playback-kids-fingerprint")
@MatchingMethod(
"LMinimizedPlaybackPolicyController;", "k"
)
@MinimizedPlaybackCompatibility
@Version("0.0.1")
object MinimizedPlaybackKidsFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("I", "L", "L"),
listOf(
Opcode.IF_EQZ,
Opcode.SGET_OBJECT,
Opcode.IF_NE,
Opcode.CONST_4,
Opcode.IPUT_BOOLEAN,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.INVOKE_STATIC
),
null,
{ it.definingClass.endsWith("MinimizedPlaybackPolicyController;") }
)

View File

@@ -7,7 +7,6 @@ import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction import org.jf.dexlib2.iface.instruction.WideLiteralInstruction

View File

@@ -8,13 +8,15 @@ import app.revanced.patcher.data.impl.toMethodWalker
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
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.Dependencies
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackKidsFingerprint
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
@@ -22,11 +24,12 @@ import org.jf.dexlib2.iface.reference.MethodReference
@Patch @Patch
@Name("minimized-playback") @Name("minimized-playback")
@Description("Enables minimized and background playback.") @Description("Enables minimized and background playback.")
@Dependencies([IntegrationsPatch::class])
@MinimizedPlaybackCompatibility @MinimizedPlaybackCompatibility
@Version("0.0.1") @Version("0.0.1")
class MinimizedPlaybackPatch : BytecodePatch( class MinimizedPlaybackPatch : BytecodePatch(
listOf( listOf(
MinimizedPlaybackManagerFingerprint, MinimizedPlaybackSettingsFingerprint MinimizedPlaybackKidsFingerprint, MinimizedPlaybackManagerFingerprint, MinimizedPlaybackSettingsFingerprint
) )
) { ) {
override fun execute(data: BytecodeData): PatchResult { override fun execute(data: BytecodeData): PatchResult {
@@ -34,7 +37,8 @@ class MinimizedPlaybackPatch : BytecodePatch(
// we return the method at the beginning instead // we return the method at the beginning instead
MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions( MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions(
0, """ 0, """
const/4 v0, 0x1 invoke-static {}, Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;->isMinimizedPlaybackEnabled()Z
move-result v0
return v0 return v0
""" """
) )
@@ -49,11 +53,23 @@ class MinimizedPlaybackPatch : BytecodePatch(
settingsBooleanMethod.addInstructions( settingsBooleanMethod.addInstructions(
0, """ 0, """
const/4 v0, 0x1 invoke-static {}, Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;->isMinimizedPlaybackEnabled()Z
move-result v0
return v0 return v0
""" """
) )
MinimizedPlaybackKidsFingerprint.result!!.mutableMethod.addInstructions(
0, """
invoke-static {}, Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;->isMinimizedPlaybackEnabled()Z
move-result v0
if-eqz v0, :enable
return-void
:enable
nop
"""
)
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -1,50 +0,0 @@
package app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("old-quality-parent-method-fingerprint")
@MatchingMethod(
"Libh", "<init>"
)
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
@OldQualityLayoutCompatibility
@Version("0.0.1")
object OldQualityParentFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "L", "L", "L", "L", "L", "L"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
)
)

View File

@@ -3,27 +3,37 @@ package app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints
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.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
@Name("old-quality-fingerprint") @Name("quality-menu-view-inflate-fingerprint")
@MatchingMethod(definingClass = "Libh") @MatchingMethod("Lkhp;", "K")
@FuzzyPatternScanMethod(2)
@OldQualityLayoutCompatibility @OldQualityLayoutCompatibility
@Version("0.0.1") @Version("0.0.1")
object OldQualityFingerprint : MethodFingerprint( object QualityMenuViewInflateFingerprint : MethodFingerprint(
"L", AccessFlags.FINAL or AccessFlags.PRIVATE, listOf("Z"), listOf( "L", AccessFlags.FINAL or AccessFlags.PUBLIC, listOf("L", "L", "L"), listOf(
Opcode.INVOKE_SUPER,
Opcode.CONST,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT, Opcode.CONST,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.GOTO,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.CONST_STRING,
) )
) )

View File

@@ -4,49 +4,41 @@ 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.impl.BytecodeData import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.OldQualityFingerprint import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.QualityMenuViewInflateFingerprint
import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.OldQualityParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("old-quality-layout") @Name("old-quality-layout")
@Description("Enables the original quality flyout menu.") @Description("Enables the original quality flyout menu.")
@OldQualityLayoutCompatibility @OldQualityLayoutCompatibility
@Version("0.0.1") @Version("0.0.1")
class OldQualityLayoutPatch : BytecodePatch( class OldQualityLayoutPatch : BytecodePatch(
listOf( listOf(QualityMenuViewInflateFingerprint)
OldQualityParentFingerprint
)
) { ) {
override fun execute(data: BytecodeData): PatchResult { override fun execute(data: BytecodeData): PatchResult {
OldQualityFingerprint.resolve(data, OldQualityParentFingerprint.result!!.classDef) val inflateFingerprintResult = QualityMenuViewInflateFingerprint.result!!
val result = OldQualityFingerprint.result val method = inflateFingerprintResult.mutableMethod
?: return PatchResultError("Required parent method could not be found.") val instructions = method.implementation!!.instructions
val implementation = result.mutableMethod.implementation!! // at this index the listener is added to the list view
val listenerInvokeRegister = instructions.size - 1 - 1
// if useOldStyleQualitySettings == true, jump over all instructions // get the register which stores the quality menu list view
val jmpInstruction = BuilderInstruction21t( val onItemClickViewRegister = (instructions[listenerInvokeRegister] as FiveRegisterInstruction).registerC
Opcode.IF_NEZ, 0, implementation.instructions[result.patternScanResult!!.endIndex].location.labels.first()
) // insert the integrations method
implementation.addInstruction(5, jmpInstruction) method.addInstruction(
result.mutableMethod.addInstructions( listenerInvokeRegister, // insert the integrations instructions right before the listener
0, """ "invoke-static { v$onItemClickViewRegister }, Lapp/revanced/integrations/patches/OldQualityLayoutPatch;->showOldQualityMenu(Landroid/widget/ListView;)V"
invoke-static { }, Lapp/revanced/integrations/patches/OldStyleQualityPatch;->useOldStyleQualitySettings()Z
move-result v0
"""
) )
return PatchResultSuccess() return PatchResultSuccess()

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -13,7 +13,7 @@ import app.revanced.patches.youtube.layout.reels.fingerprints.HideReelsFingerpri
//@Patch TODO: this is currently in the general-bytecode-ads patch due to the integrations having a preference for including reels or not. Move it here. //@Patch TODO: this is currently in the general-bytecode-ads patch due to the integrations having a preference for including reels or not. Move it here.
@Name("hide-reels") @Name("hide-reels")
@Description("Hides reels on the page.") @Description("Hides reels on the home page.")
@HideReelsCompatibility @HideReelsCompatibility
@Version("0.0.1") @Version("0.0.1")
class HideReelsPatch : BytecodePatch( class HideReelsPatch : BytecodePatch(

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.26.35", "17.27.39")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class ReturnYouTubeDislikeCompatibility

View File

@@ -0,0 +1,25 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import org.jf.dexlib2.AccessFlags
@Name("dislike-fingerprint")
@MatchingMethod(
"Luqs;", "<init>"
)
@FuzzyPatternScanMethod(2)
@ReturnYouTubeDislikeCompatibility
@Version("0.0.2")
object DislikeFingerprint : MethodFingerprint(
"V",
AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
null,
null,
listOf("like/dislike")
)

View File

@@ -0,0 +1,25 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import org.jf.dexlib2.AccessFlags
@Name("like-fingerprint")
@MatchingMethod(
"Luqt;", "<init>"
)
@FuzzyPatternScanMethod(2)
@ReturnYouTubeDislikeCompatibility
@Version("0.0.2")
object LikeFingerprint : MethodFingerprint(
"V",
AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
null,
null,
listOf("like/like")
)

View File

@@ -0,0 +1,25 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import org.jf.dexlib2.AccessFlags
@Name("remove-like-fingerprint")
@MatchingMethod(
"Luqw;", "<init>"
)
@FuzzyPatternScanMethod(2)
@ReturnYouTubeDislikeCompatibility
@Version("0.0.2")
object RemoveLikeFingerprint : MethodFingerprint(
"V",
AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
null,
null,
listOf("like/removelike")
)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
@Name("text-component-spec-parent-fingerprint")
@MatchingMethod(
"Lnvy;", "e"
)
@DirectPatternScanMethod
@ReturnYouTubeDislikeCompatibility
@Version("0.0.1")
object TextComponentSpecParentFingerprint : MethodFingerprint(
null,
null,
null,
null,
listOf("TextComponentSpec: No converter for extension: ")
)

View File

@@ -0,0 +1,79 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentSpecParentFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.DislikeFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.LikeFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RemoveLikeFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
@Patch
@Dependencies([IntegrationsPatch::class, VideoIdPatch::class])
@Name("return-youtube-dislike")
@Description("Shows the dislike count of videos using the Return YouTube Dislike API.")
@ReturnYouTubeDislikeCompatibility
@Version("0.0.1")
class ReturnYouTubeDislikePatch : BytecodePatch(
listOf(
TextComponentSpecParentFingerprint, LikeFingerprint, DislikeFingerprint, RemoveLikeFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {
LikeFingerprint.result!!.mutableMethod.addInstructions(
0,
"""
const/4 v0, 1
invoke-static {v0}, Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->sendVote(I)V
"""
)
DislikeFingerprint.result!!.mutableMethod.addInstructions(
0,
"""
const/4 v0, -1
invoke-static {v0}, Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->sendVote(I)V
"""
)
RemoveLikeFingerprint.result!!.mutableMethod.addInstructions(
0,
"""
const/4 v0, 0
invoke-static {v0}, Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->sendVote(I)V
"""
)
VideoIdPatch.injectCall("Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->newVideoLoaded(Ljava/lang/String;)V")
val parentResult = TextComponentSpecParentFingerprint.result!!
val createComponentMethod = parentResult.mutableClass.methods.find { method ->
method.parameters.size >= 19 && method.parameterTypes.takeLast(4)
.all { param -> param == "Ljava/util/concurrent/atomic/AtomicReference;" }
}
?: return PatchResultError("TextComponentSpec.createComponent not found")
val conversionContextParam = 5
val textRefParam = createComponentMethod.parameters.size - 2
createComponentMethod.addInstructions(
0,
"""
move-object/from16 v0, p$conversionContextParam
move-object/from16 v1, p$textRefParam
invoke-static {v0, v1}, Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V
"""
)
return PatchResultSuccess()
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36", "17.20.37", "17.22.36", "17.23.35", "17.23.36", "17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -17,9 +17,9 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("hide-shorts-button") @Name("hide-shorts-button")
@Description("Hides the shorts button.") @Description("Hides the shorts button on the navigation bar.")
@ShortsButtonCompatibility @ShortsButtonCompatibility
@Version("0.0.1") @Version("0.0.1")
class ShortsButtonRemoverPatch : BytecodePatch( class ShortsButtonRemoverPatch : BytecodePatch(

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.sponsorblock.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.22.36", "17.26.35", "17.27.39")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class SponsorBlockCompatibility

View File

@@ -0,0 +1,41 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("append-time-fingerprint")
@MatchingMethod(
"Liet;", "e"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object AppendTimeFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L", "L", "L"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
)
)

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
@Name("create-video-player-seekbar-fingerprint")
@MatchingMethod(
"Lfcm;", "onDraw"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object CreateVideoPlayerSeekbarFingerprint : MethodFingerprint(
"V", null, null,
null,
listOf("timed_markers_width")
)

View File

@@ -0,0 +1,24 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import org.jf.dexlib2.util.MethodUtil
@Name("next-gen-watch-layout-fingerprint")
@MatchingMethod(
"LNextGenWatchLayout;", "<init>"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object NextGenWatchLayoutFingerprint : MethodFingerprint(
"V", // constructors return void, in favour of speed of matching, this fingerprint has been added
null,
null,
null,
customFingerprint = { methodDef -> MethodUtil.isConstructor(methodDef) && methodDef.parameterTypes.size == 3 && methodDef.definingClass.endsWith("NextGenWatchLayout;") }
)

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import org.jf.dexlib2.Opcode
@Name("player-controller-set-time-reference-fingerprint")
@MatchingMethod(
"Lxqm;", "<init>"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object PlayerControllerSetTimeReferenceFingerprint : MethodFingerprint(
null, null, null,
listOf(Opcode.INVOKE_DIRECT_RANGE, Opcode.IGET_OBJECT),
listOf("Media progress reported outside media playback: ")
)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
@Name("player-init-fingerprint")
@MatchingMethod(
"Laajv;", "aG"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object PlayerInitFingerprint : MethodFingerprint(
null, null, null,
null,
strings = listOf(
"playVideo called on player response with no videoStreamingData."
),
)

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
@Name("player-overlays-layout-init-fingerprint")
@MatchingMethod(
"Lihh;", "u"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object PlayerOverlaysLayoutInitFingerprint : MethodFingerprint(
null, null, null,
null,
null,
{ methodDef -> methodDef.returnType.endsWith("YouTubePlayerOverlaysLayout;") }
)

View File

@@ -0,0 +1,37 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.MethodReference
@Name("rectangle-field-invalidator-fingerprint")
@MatchingMethod(
"Lfcm;", "kY"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object RectangleFieldInvalidatorFingerprint : MethodFingerprint(
"V",
null,
null,
null,
null,
custom@{ methodDef ->
val instructions = methodDef.implementation?.instructions!!
val instructionCount = instructions.count()
// the method has definitely more than 5 instructions
if (instructionCount < 5) return@custom false
val referenceInstruction = instructions.elementAt(instructionCount - 2) // the second to last instruction
val reference = ((referenceInstruction as? ReferenceInstruction)?.reference as? MethodReference)
reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method
}
)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
@Name("seek-fingerprint")
@MatchingMethod(
"Laajv;", "af"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object SeekFingerprint : MethodFingerprint(
null,
null,
null,
null,
listOf("Attempting to seek during an ad")
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
@Name("show-player-controls-fingerprint")
@MatchingMethod(
"LYouTubeControlsOverlay;", "ac"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object ShowPlayerControlsFingerprint : MethodFingerprint(
"V", null, listOf("Z","Z"), null, null
)

View File

@@ -0,0 +1,34 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import org.jf.dexlib2.Opcode
@Name("video-length-fingerprint")
@MatchingMethod(
"Lyfh;", "z"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object VideoLengthFingerprint : MethodFingerprint(
null, null, null,
listOf(
Opcode.MOVE_RESULT_WIDE,
Opcode.CMP_LONG,
Opcode.IF_LEZ,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_WIDE,
Opcode.GOTO,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_WIDE,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL
)
)

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
@Name("video-time-fingerprint")
@MatchingMethod(
"Lwyh;", "<init>"
)
@DirectPatternScanMethod
@SponsorBlockCompatibility
@Version("0.0.1")
object VideoTimeFingerprint : MethodFingerprint(
null, null, null, null,
listOf("MedialibPlayerTimeInfo{currentPositionMillis=")
)

View File

@@ -0,0 +1,335 @@
package app.revanced.patches.youtube.layout.sponsorblock.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.impl.BytecodeData
import app.revanced.patcher.data.impl.toMethodWalker
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.*
import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.iface.instruction.*
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodParameter
import org.jf.dexlib2.util.MethodUtil
@Patch
@Dependencies(
dependencies = [IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class, SponsorBlockResourcePatch::class, VideoIdPatch::class]
)
@Name("sponsorblock")
@Description("Integrate SponsorBlock.")
@SponsorBlockCompatibility
@Version("0.0.1")
class SponsorBlockBytecodePatch : BytecodePatch(
listOf(
PlayerControllerSetTimeReferenceFingerprint,
CreateVideoPlayerSeekbarFingerprint,
VideoTimeFingerprint,
NextGenWatchLayoutFingerprint,
AppendTimeFingerprint,
PlayerInitFingerprint,
PlayerOverlaysLayoutInitFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {/*
Set current video time
*/
val referenceResult = PlayerControllerSetTimeReferenceFingerprint.result!!
val playerControllerSetTimeMethod =
data.toMethodWalker(referenceResult.method).nextMethod(referenceResult.patternScanResult!!.startIndex, true)
.getMethod() as MutableMethod
playerControllerSetTimeMethod.addInstruction(
2,
"invoke-static {p1, p2}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setCurrentVideoTime(J)V"
)
/*
Set current video time high precision
*/
val constructorFingerprint =
object : MethodFingerprint("V", null, listOf("J", "J", "J", "J", "I", "L"), null) {}
constructorFingerprint.resolve(data, VideoTimeFingerprint.result!!.classDef)
val constructor = constructorFingerprint.result!!.mutableMethod
constructor.addInstruction(
0,
"invoke-static {p1, p2}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setCurrentVideoTimeHighPrecision(J)V"
)
/*
Set current video id
*/
VideoIdPatch.injectCall("Lapp/revanced/integrations/sponsorblock/PlayerController;->setCurrentVideoId(Ljava/lang/String;)V")
/*
Seekbar drawing
*/
val seekbarSignatureResult = CreateVideoPlayerSeekbarFingerprint.result!!
val seekbarMethod = seekbarSignatureResult.mutableMethod
val seekbarMethodInstructions = seekbarMethod.implementation!!.instructions
/*
Get the instance of the seekbar rectangle
*/
seekbarMethod.addInstruction(
1,
"invoke-static {v0}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setSponsorBarRect(Ljava/lang/Object;)V"
)
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_STATIC) continue
val invokeInstruction = instruction as Instruction35c
if ((invokeInstruction.reference as MethodReference).name != "round") continue
val insertIndex = index + 2
// set the thickness of the segment
seekbarMethod.addInstruction(
insertIndex,
"invoke-static {v${invokeInstruction.registerC}}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setSponsorBarThickness(I)V"
)
break
}
/*
Set rectangle absolute left and right positions
*/
val drawRectangleInstructions = seekbarMethodInstructions.filter {
it is ReferenceInstruction && (it.reference as? MethodReference)?.name == "drawRect" && it is FiveRegisterInstruction
}.map { // TODO: improve code
seekbarMethodInstructions.indexOf(it) to (it as FiveRegisterInstruction).registerD
}
val (indexRight, rectangleRightRegister) = drawRectangleInstructions[0]
val (indexLeft, rectangleLeftRegister) = drawRectangleInstructions[3]
// order of operation is important here due to the code above which has to be improved
// the reason for that is that we get the index, add instructions and then the offset would be wrong
seekbarMethod.addInstruction(
indexLeft + 1,
"invoke-static {v$rectangleLeftRegister}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V"
)
seekbarMethod.addInstruction(
indexRight + 1,
"invoke-static {v$rectangleRightRegister}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V"
)
/*
Draw segment
*/
val drawSegmentInstructionInsertIndex = (seekbarMethodInstructions.size - 1 - 2)
val (canvasInstance, centerY) = (seekbarMethodInstructions[drawSegmentInstructionInsertIndex] as FiveRegisterInstruction).let {
it.registerC to it.registerE
}
seekbarMethod.addInstruction(
drawSegmentInstructionInsertIndex - 1,
"invoke-static {v$canvasInstance, v$centerY}, Lapp/revanced/integrations/sponsorblock/PlayerController;->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V"
)
/*
Set video length
*/
VideoLengthFingerprint.resolve(data, seekbarSignatureResult.classDef)
val videoLengthMethodResult = VideoLengthFingerprint.result!!
val videoLengthMethod = videoLengthMethodResult.mutableMethod
val videoLengthMethodInstructions = videoLengthMethod.implementation!!.instructions
val videoLengthRegister =
(videoLengthMethodInstructions[videoLengthMethodResult.patternScanResult!!.endIndex - 2] as OneRegisterInstruction).registerA
val dummyRegisterForLong =
videoLengthRegister + 1 // this is required for long values since they are 64 bit wide
videoLengthMethod.addInstruction(
videoLengthMethodResult.patternScanResult!!.endIndex,
"invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, Lapp/revanced/integrations/sponsorblock/PlayerController;->setVideoLength(J)V"
)
/*
Voting & Shield button
*/
ShowPlayerControlsFingerprint.resolve(data, data.classes.find { it.type.endsWith("YouTubeControlsOverlay;") }!!)
val controlsMethodResult = ShowPlayerControlsFingerprint.result!!
val controlsLayoutStubResourceId =
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "controls_layout_stub" }.id
val zoomOverlayResourceId =
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "video_zoom_overlay_stub" }.id
methods@ for (method in controlsMethodResult.mutableClass.methods) {
val instructions = method.implementation?.instructions!!
instructions@ for ((index, instruction) in instructions.withIndex()) {
// search for method which inflates the controls layout view
if (instruction.opcode != Opcode.CONST) continue@instructions
when ((instruction as NarrowLiteralInstruction).wideLiteral) {
controlsLayoutStubResourceId -> {
// replace the view with the YouTubeControlsOverlay
val moveResultInstructionIndex = index + 5
val inflatedViewRegister =
(instructions[moveResultInstructionIndex] as OneRegisterInstruction).registerA
// initialize with the player overlay object
method.addInstructions(
moveResultInstructionIndex + 1, // insert right after moving the view to the register and use that register
"""
invoke-static {v$inflatedViewRegister}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->initialize(Ljava/lang/Object;)V
invoke-static {v$inflatedViewRegister}, Lapp/revanced/integrations/sponsorblock/VotingButton;->initialize(Ljava/lang/Object;)V
"""
)
}
zoomOverlayResourceId -> {
val invertVisibilityMethod =
data.toMethodWalker(method).nextMethod(index - 6, true).getMethod() as MutableMethod
// change visibility of the buttons
invertVisibilityMethod.addInstructions(
0, """
invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibilityNegatedImmediate(Z)V
invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibilityNegatedImmediate(Z)V
""".trimIndent()
)
}
}
}
}
// change visibility of the buttons
controlsMethodResult.mutableMethod.addInstructions(
0, """
invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibility(Z)V
invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibility(Z)V
""".trimIndent()
)
// set SegmentHelperLayout.context to the player layout instance
val instanceRegister = 0
NextGenWatchLayoutFingerprint.result!!.mutableMethod.addInstruction(
3, // after super call
"invoke-static/range {p$instanceRegister}, Lapp/revanced/integrations/sponsorblock/PlayerController;->addSkipSponsorView15(Landroid/view/View;)V"
)
// append the new time to the player layout
val appendTimeFingerprintResult = AppendTimeFingerprint.result!!
val appendTimePatternScanStartIndex = appendTimeFingerprintResult.patternScanResult!!.startIndex
val targetRegister =
(appendTimeFingerprintResult.method.implementation!!.instructions.elementAt(appendTimePatternScanStartIndex + 1) as OneRegisterInstruction).registerA
appendTimeFingerprintResult.mutableMethod.addInstructions(
appendTimePatternScanStartIndex + 2, """
invoke-static {v$targetRegister}, Lapp/revanced/integrations/sponsorblock/SponsorBlockUtils;->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
"""
)
// initialize the player controller
val initFingerprintResult = PlayerInitFingerprint.result!!
val initInstanceRegister = 0
initFingerprintResult.mutableClass.methods.first { MethodUtil.isConstructor(it) }.addInstruction(
4, // after super class invoke
"invoke-static {v$initInstanceRegister}, Lapp/revanced/integrations/sponsorblock/PlayerController;->onCreate(Ljava/lang/Object;)V"
)
// initialize the sponsorblock view
PlayerOverlaysLayoutInitFingerprint.result!!.mutableMethod.addInstruction(
6, // after inflating the view
"invoke-static {p0}, Lapp/revanced/integrations/sponsorblock/player/ui/SponsorBlockView;->initialize(Ljava/lang/Object;)V"
)
// lastly create hooks for the player controller
// get original seek method
SeekFingerprint.resolve(data, initFingerprintResult.classDef)
val seekFingerprintResultMethod = SeekFingerprint.result!!.method
// get enum type for the seek helper method
val seekSourceEnumType = seekFingerprintResultMethod.parameterTypes[1].toString()
// create helper method
val seekHelperMethod = ImmutableMethod(
seekFingerprintResultMethod.definingClass,
"seekHelper",
listOf(ImmutableMethodParameter("J", null, "time")),
"Z",
AccessFlags.PUBLIC or AccessFlags.FINAL,
null, null,
MutableMethodImplementation(4)
).toMutable()
// insert helper method instructions
seekHelperMethod.addInstructions(
0,
"""
sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType
invoke-virtual {p0, p1, p2, v0}, ${seekFingerprintResultMethod.definingClass}->${seekFingerprintResultMethod.name}(J$seekSourceEnumType)Z
move-result p1
return p1
"""
)
// add the helper method to the original class
initFingerprintResult.mutableClass.methods.add(seekHelperMethod)
// get rectangle field name
RectangleFieldInvalidatorFingerprint.resolve(data, seekbarSignatureResult.classDef)
val rectangleFieldInvalidatorInstructions =
RectangleFieldInvalidatorFingerprint.result!!.method.implementation!!.instructions
val rectangleFieldName =
((rectangleFieldInvalidatorInstructions.elementAt(rectangleFieldInvalidatorInstructions.count() - 3) as ReferenceInstruction).reference as FieldReference).name
// get the player controller class from the integrations
val playerControllerMethods =
data.proxy(data.classes.first { it.type.endsWith("PlayerController;") }).resolve().methods
// get the method which contain the "replaceMe" strings
val replaceMeMethods =
playerControllerMethods.filter { it.name == "onCreate" || it.name == "setSponsorBarRect" }
fun MutableMethod.replaceStringInstruction(index: Int, instruction: Instruction, with: String) {
val register = (instruction as OneRegisterInstruction).registerA
this.replaceInstruction(
index, "const-string v$register, \"$with\""
)
}
// replace the "replaceMeWith*" strings
for (method in replaceMeMethods) {
for ((index, it) in method.implementation!!.instructions.withIndex()) {
if (it.opcode.ordinal != Opcode.CONST_STRING.ordinal) continue
when (((it as ReferenceInstruction).reference as StringReference).string) {
"replaceMeWithsetSponsorBarRect" ->
method.replaceStringInstruction(index, it, rectangleFieldName)
"replaceMeWithsetMillisecondMethod" ->
method.replaceStringInstruction(index, it, "seekHelper")
}
}
}
// TODO: isSBChannelWhitelisting implementation
return PatchResultSuccess()
}
}

View File

@@ -0,0 +1,128 @@
package app.revanced.patches.youtube.layout.sponsorblock.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.DomFileEditor
import app.revanced.patcher.data.impl.ResourceData
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.impl.ResourcePatch
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
import java.io.OutputStream
import java.nio.file.Files
@Name("sponsorblock-resource-patch")
@SponsorBlockCompatibility
@Dependencies([FixLocaleConfigErrorPatch::class])
@Version("0.0.1")
class SponsorBlockResourcePatch : ResourcePatch() {
override fun execute(data: ResourceData): PatchResult {
val classLoader = this.javaClass.classLoader
/*
merge SponsorBlock strings to main strings
*/
val stringsResourcePath = "values/strings.xml"
val stringsResourceInputStream = classLoader.getResourceAsStream("sponsorblock/$stringsResourcePath")!!
// copy nodes from the resources node to the real resource node
"resources".copyXmlNode(
data.xmlEditor[stringsResourceInputStream, OutputStream.nullOutputStream()],
data.xmlEditor["res/$stringsResourcePath"]
).close() // close afterwards
/*
merge SponsorBlock drawables to main drawables
*/
val drawables = "drawable" to arrayOf(
"ic_sb_adjust",
"ic_sb_compare",
"ic_sb_edit",
"ic_sb_logo",
"ic_sb_publish",
"ic_sb_voting"
)
val layouts = "layout" to arrayOf(
"inline_sponsor_overlay", "new_segment", "skip_sponsor_button"
)
// collect resources
val xmlResources = arrayOf(drawables, layouts)
// write resources
xmlResources.forEach { (path, resourceNames) ->
resourceNames.forEach { name ->
val relativePath = "$path/$name.xml"
Files.copy(
classLoader.getResourceAsStream("sponsorblock/$relativePath")!!,
data["res"].resolve(relativePath).toPath()
)
}
}
/*
merge xml nodes from the host to their real xml files
*/
// collect all host resources
val hostingXmlResources = mapOf("layout" to arrayOf("youtube_controls_layout"))
// copy nodes from host resources to their real xml files
hostingXmlResources.forEach { (path, resources) ->
resources.forEach { resource ->
val hostingResourceStream = classLoader.getResourceAsStream("sponsorblock/host/$path/$resource.xml")!!
val targetXmlEditor = data.xmlEditor["res/$path/$resource.xml"]
"RelativeLayout".copyXmlNode(
data.xmlEditor[hostingResourceStream, OutputStream.nullOutputStream()],
targetXmlEditor
).also {
val children = targetXmlEditor.file.getElementsByTagName("RelativeLayout").item(0).childNodes
// Replace the startOf with the voting button view so that the button does not overlap
for (i in 1 until children.length) {
val view = children.item(i)
// Replace the attribute for a specific node only
if (!(view.hasAttributes() && view.attributes.getNamedItem("android:id").nodeValue.endsWith("live_chat_overlay_button"))) continue
// voting button id from the voting button view from the youtube_controls_layout.xml host file
val votingButtonId = "@+id/voting_button"
view.attributes.getNamedItem("android:layout_toStartOf").nodeValue = votingButtonId
break
}
}.close() // close afterwards
}
}
return PatchResultSuccess()
}
/**
* Copies the specified node of the source [DomFileEditor] to the target [DomFileEditor].
* @param source the source [DomFileEditor].
* @param target the target [DomFileEditor]-
*/
private fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoCloseable {
val hostNodes = source.file.getElementsByTagName(this).item(0).childNodes
val destinationResourceFile = target.file
val destinationNode = destinationResourceFile.getElementsByTagName(this).item(0)
for (index in 0 until hostNodes.length) {
val node = hostNodes.item(index).cloneNode(true)
destinationResourceFile.adoptNode(node)
destinationNode.appendChild(node)
}
return AutoCloseable {
source.close()
target.close()
}
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.24.34", "17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.24.34", "17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -19,9 +19,9 @@ import app.revanced.patches.youtube.layout.watermark.fingerprints.HideWatermarkF
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
@Patch @Patch
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("hide-watermark") @Name("hide-watermark")
@Description("Hides the creator's watermark on videos.") @Description("Hides creator's watermarks on videos.")
@HideWatermarkCompatibility @HideWatermarkCompatibility
@Version("0.0.1") @Version("0.0.1")
class HideWatermarkPatch : BytecodePatch( class HideWatermarkPatch : BytecodePatch(

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -21,7 +21,7 @@ import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
@Patch(include = false) @Patch(include = false)
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("enable-wide-searchbar") @Name("enable-wide-searchbar")
@Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.") @Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.")
@WideSearchbarCompatibility @WideSearchbarCompatibility

View File

@@ -1,11 +1,11 @@
package app.revanced.patches.youtube.layout.autorepeat.annotations package app.revanced.patches.youtube.misc.autorepeat.annotations
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.24.35", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.24.35", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -1,12 +1,12 @@
package app.revanced.patches.youtube.layout.autorepeat.fingerprints package app.revanced.patches.youtube.misc.autorepeat.fingerprints
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.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.youtube.layout.autorepeat.annotations.AutoRepeatCompatibility import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
@Name("auto-repeat-fingerprint") @Name("auto-repeat-fingerprint")
@@ -25,8 +25,8 @@ public final void ae() {
object AutoRepeatFingerprint : MethodFingerprint( object AutoRepeatFingerprint : MethodFingerprint(
"V", "V",
AccessFlags.PUBLIC or AccessFlags.FINAL, AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf(),
null, null,
null, null,
null, customFingerprint = { methodDef -> methodDef.implementation!!.instructions.count() == 3 && methodDef.annotations.isEmpty()}
customFingerprint = { methodDef -> methodDef.implementation!!.instructions.count() == 3 }
) )

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.youtube.layout.autorepeat.fingerprints package app.revanced.patches.youtube.misc.autorepeat.fingerprints
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
@@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.youtube.layout.autorepeat.annotations.AutoRepeatCompatibility import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
@Name("auto-repeat-parent-fingerprint") @Name("auto-repeat-parent-fingerprint")

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.youtube.layout.autorepeat.patch package app.revanced.patches.youtube.misc.autorepeat.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
@@ -13,13 +13,13 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Dependencies import app.revanced.patcher.patch.annotations.Dependencies
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.layout.autorepeat.annotations.AutoRepeatCompatibility import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility
import app.revanced.patches.youtube.layout.autorepeat.fingerprints.AutoRepeatFingerprint import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint
import app.revanced.patches.youtube.layout.autorepeat.fingerprints.AutoRepeatParentFingerprint import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
@Patch(include = false) @Patch(include = false)
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@Name("autorepeat-by-default") @Name("autorepeat-by-default")
@Description("Enables auto repeating of videos by default.") @Description("Enables auto repeating of videos by default.")
@AutoRepeatCompatibility @AutoRepeatCompatibility
@@ -50,8 +50,7 @@ class AutoRepeatPatch : BytecodePatch(
invoke-static {}, Lapp/revanced/integrations/patches/AutoRepeatPatch;->shouldAutoRepeat()Z invoke-static {}, Lapp/revanced/integrations/patches/AutoRepeatPatch;->shouldAutoRepeat()Z
move-result v0 move-result v0
if-eqz v0, :noautorepeat if-eqz v0, :noautorepeat
const/4 v0, 0x0 invoke-virtual {p0}, $methodToCall
invoke-virtual {}, $methodToCall
:noautorepeat :noautorepeat
return-void return-void
""" """
@@ -62,7 +61,7 @@ class AutoRepeatPatch : BytecodePatch(
//Since addInstructions needs an index which starts counting at 0 and size starts counting at 1, //Since addInstructions needs an index which starts counting at 0 and size starts counting at 1,
//we have to remove 1 to get the latest instruction //we have to remove 1 to get the latest instruction
val index = implementation.instructions.size-1 val index = implementation.instructions.size - 1
//remove last instruction which is return-void //remove last instruction which is return-void

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility(
[Package( [Package(
"com.google.android.youtube", arrayOf("17.24.34", "17.25.34", "17.26.35") "com.google.android.youtube", arrayOf("17.24.34", "17.25.34", "17.26.35", "17.27.39")
)] )]
) )
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)

View File

@@ -24,8 +24,8 @@ import org.jf.dexlib2.iface.reference.MethodReference
@Patch @Patch
@Name("custom-playback-speed") @Name("custom-playback-speed")
@Description("Allows to change the default playback speed options.") @Description("Adds more video playback speed options.")
@Dependencies(dependencies = [IntegrationsPatch::class]) @Dependencies([IntegrationsPatch::class])
@CustomPlaybackSpeedCompatibility @CustomPlaybackSpeedCompatibility
@Version("0.0.1") @Version("0.0.1")
class CustomPlaybackSpeedPatch : BytecodePatch( class CustomPlaybackSpeedPatch : BytecodePatch(
@@ -56,7 +56,7 @@ class CustomPlaybackSpeedPatch : BytecodePatch(
val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
val videoSpeedsArrayType = "Lapp/revanced/integrations/videoplayer/videosettings/VideoSpeed;->videoSpeeds:[F" val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/VideoSpeedPatch;->videoSpeeds:[F"
arrayGenMethod.addInstructions( arrayGenMethod.addInstructions(
arrayLengthConstIndex + 1, arrayLengthConstIndex + 1,

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.youtube.misc.forcevp9.annotations;
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.26.35", "17.27.39")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class ForceVP9Compatibility {
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("force-vp9-codec-fingerprint")
@MatchingMethod(
"Lpzs;", "aI"
)
@DirectPatternScanMethod
@ForceVP9Compatibility
@Version("0.0.1")
object ForceVP9CodecFingerprint : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf(
Opcode.SGET, Opcode.IF_NEZ, Opcode.INVOKE_STATIC
), null, null
)
/*
public static boolean aI(Context context, int i) {
if (b == 0) {
aH(context);
}
return b >= i; // Override to: return Lapp/revanced/integrations/patches/ForceCodecPatch->shouldForceVP9()
}
.method public static aI(Landroid/content/Context;I)Z
sget v0, Lpzs;->b:I
if-nez v0, :cond_7
invoke-static {p0}, Lpzs;->aH(Landroid/content/Context;)V
:cond_7
//remove after here, and inject only our code
sget p0, Lpzs;->b:I
if-lt p0, p1, :cond_d
const/4 p0, 0x1
return p0
:cond_d
const/4 p0, 0x0
return p0
.end method
*/

View File

@@ -0,0 +1,73 @@
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("force-vp9-codec-fingerprint-two")
@MatchingMethod(
"Lpzs;", "aO"
)
@DirectPatternScanMethod
@ForceVP9Compatibility
@Version("0.0.1")
object ForceVP9CodecFingerprintTwo : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("I"), listOf(
Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT_OBJECT, Opcode.CONST_4
), null, null
)
/*
public static boolean aO(int i) {
Pair aG = aG();
return (aG == null ? 0 : Math.min(((Integer) aG.first).intValue(), ((Integer) aG.second).intValue())) >= i;
//replace line with: return Lapp/revanced/integrations/patches/ForceCodecPatch/shouldForceVP9();
}
becomes:
public static boolean aO(int i) {
return Lapp/revanced/integrations/patches/ForceCodecPatch/shouldForceVP9();
}
.method public static aO(I)Z
invoke-static {}, Lpzs;->aG()Landroid/util/Pair;
move-result-object v0
const/4 v1, 0x0
if-nez v0, :cond_9
const/4 v0, 0x0
goto :goto_1d
:cond_9
iget-object v2, v0, Landroid/util/Pair;->first:Ljava/lang/Object;
check-cast v2, Ljava/lang/Integer;
invoke-virtual {v2}, Ljava/lang/Integer;->intValue()I
move-result v2
iget-object v0, v0, Landroid/util/Pair;->second:Ljava/lang/Object;
check-cast v0, Ljava/lang/Integer;
invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I
move-result v0
invoke-static {v2, v0}, Ljava/lang/Math;->min(II)I
move-result v0
:goto_1d
if-lt v0, p0, :cond_21
const/4 p0, 0x1
return p0
:cond_21
return v1
.end method
becomes:
.method public static aO(I)Z
invoke-static {}, Lapp/revanced/integrations/patches/ForceCodecPatch;->shouldForceVP9()Z
move-result v0
return v0
.end method
*/

View File

@@ -0,0 +1,24 @@
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
import org.jf.dexlib2.AccessFlags
@Name("force-vp9-codec-parent-fingerprint")
@MatchingMethod(
"Lpzs;", "Y"
)
@DirectPatternScanMethod
@ForceVP9Compatibility
@Version("0.0.1")
object ForceVP9ParentFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L"), null,
listOf(
"Share video error: null watch uri"
)
)

View File

@@ -0,0 +1,30 @@
package app.revanced.patches.youtube.misc.forcevp9.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.forcevp9.annotations.ForceVP9Compatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference
@Name("replace-device-info-parent-fingerprint")
@MatchingMethod(
"Lvjb;", "e"
)
@DirectPatternScanMethod
@ForceVP9Compatibility
@Version("0.0.1")
object ReplaceDeviceInfoFingerprint : MethodFingerprint(
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), null,
null,
customFingerprint = { methodDef ->
methodDef.implementation!!.instructions.any {
((it as? ReferenceInstruction)?.reference as? FieldReference)?.definingClass.equals("Landroid/os/Build;")
&& ((it as? ReferenceInstruction)?.reference as? FieldReference)?.name.equals("MANUFACTURER")
}
}
)

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