mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 09:53:55 +01:00
Compare commits
134 Commits
v2.191.0-d
...
v2.196.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
704e097b4e | ||
|
|
ea419a6e5f | ||
|
|
312dc1eb6f | ||
|
|
7dc8ec9f34 | ||
|
|
9564fd2b7c | ||
|
|
124380f738 | ||
|
|
777b6f6160 | ||
|
|
358b367408 | ||
|
|
68eee9b5e2 | ||
|
|
dc7bf5c760 | ||
|
|
b3fcb0e92b | ||
|
|
fb3cd9a3ad | ||
|
|
2a047ed1b6 | ||
|
|
0d1ab25cb5 | ||
|
|
87185171da | ||
|
|
d9c3748314 | ||
|
|
c14642a34b | ||
|
|
af2df3edd9 | ||
|
|
b5a7258f74 | ||
|
|
28fa499974 | ||
|
|
5fa89b6846 | ||
|
|
9588a47880 | ||
|
|
0dc06768d9 | ||
|
|
a04232ea91 | ||
|
|
49b47fa772 | ||
|
|
daf125a863 | ||
|
|
9121e0519b | ||
|
|
b352f48cb1 | ||
|
|
51844222c8 | ||
|
|
87877a8f2f | ||
|
|
bff07aa5b8 | ||
|
|
c575751dd4 | ||
|
|
8c53a6ab82 | ||
|
|
c1df94ae0b | ||
|
|
f8c0286b15 | ||
|
|
d59431ed74 | ||
|
|
44e35bf8aa | ||
|
|
1d90346f19 | ||
|
|
ab84dc78b9 | ||
|
|
be5df4d076 | ||
|
|
f73594c7e2 | ||
|
|
99cf7ca173 | ||
|
|
6ad9225f3e | ||
|
|
540e6d63d1 | ||
|
|
a8b0781d76 | ||
|
|
e398968762 | ||
|
|
cf8e8a44e4 | ||
|
|
42aea0c9ca | ||
|
|
d735520421 | ||
|
|
debb07ae21 | ||
|
|
2fe71a18ea | ||
|
|
5b6e015e64 | ||
|
|
b4d33a1dcf | ||
|
|
ecb92d3f68 | ||
|
|
caf1e6b211 | ||
|
|
07d98ab3f7 | ||
|
|
5bd5f87315 | ||
|
|
fa0b788111 | ||
|
|
bd10651c3b | ||
|
|
2d65ef676d | ||
|
|
0424cea8f0 | ||
|
|
f5acbe4315 | ||
|
|
992d85ded8 | ||
|
|
f25d085d25 | ||
|
|
002cc9d810 | ||
|
|
2919eb26e6 | ||
|
|
3b5141d4b4 | ||
|
|
fd2daa37b1 | ||
|
|
9ff6f84642 | ||
|
|
9417b67e74 | ||
|
|
f41e657191 | ||
|
|
883f69ee9a | ||
|
|
a7cf7e6d70 | ||
|
|
23dec85068 | ||
|
|
936c98c709 | ||
|
|
ba92f2e5d9 | ||
|
|
1f5c1d48a2 | ||
|
|
7d9ddc9203 | ||
|
|
0e0ea5d064 | ||
|
|
4ba1ddde8f | ||
|
|
5b09ef79a8 | ||
|
|
cd544669b2 | ||
|
|
7d50a7b178 | ||
|
|
e153e97ed2 | ||
|
|
224142ba19 | ||
|
|
8c5239d6b5 | ||
|
|
43533f6c09 | ||
|
|
f77d743a92 | ||
|
|
27a346d74b | ||
|
|
5138197358 | ||
|
|
2e7ab38a3d | ||
|
|
47e1bcbafa | ||
|
|
d83ef1ed59 | ||
|
|
3f397dabf7 | ||
|
|
1d23dcb3ea | ||
|
|
be335adeb9 | ||
|
|
7422617dc5 | ||
|
|
b07887800b | ||
|
|
0c5d846192 | ||
|
|
ff6daf55e0 | ||
|
|
2d33ba68b3 | ||
|
|
f703c9ab81 | ||
|
|
9546d12218 | ||
|
|
b2b5594f6a | ||
|
|
bf628dc0ea | ||
|
|
5f2536814d | ||
|
|
99bc87909e | ||
|
|
928df2428d | ||
|
|
3e9e1e2577 | ||
|
|
5ebec9b424 | ||
|
|
0204ff67a9 | ||
|
|
7d2a707030 | ||
|
|
26e0e4cd1d | ||
|
|
40f0a8cd0d | ||
|
|
47c858ef4e | ||
|
|
b17cd14d7d | ||
|
|
c7383bdf67 | ||
|
|
01e36428a0 | ||
|
|
187c1eb14a | ||
|
|
acadac3049 | ||
|
|
bf5c197eb8 | ||
|
|
73e8b3f81b | ||
|
|
1c2f499b1c | ||
|
|
32599ab13d | ||
|
|
19519d1d06 | ||
|
|
2ff70e8b8f | ||
|
|
1e21b0b572 | ||
|
|
18180745bc | ||
|
|
aa89b8d20c | ||
|
|
287648cf1e | ||
|
|
c4554b3564 | ||
|
|
1532d899b4 | ||
|
|
8ac18e6e23 | ||
|
|
54aa358b9f |
2
.github/workflows/pull_request.yml
vendored
2
.github/workflows/pull_request.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
with:
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Make sure the release step uses its own credentials:
|
||||
# https://github.com/cycjimmy/semantic-release-action#private-packages
|
||||
|
||||
477
CHANGELOG.md
477
CHANGELOG.md
@@ -1,3 +1,480 @@
|
||||
# [2.196.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.196.0-dev.1...v2.196.0-dev.2) (2023-10-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Announcements:** Clarify announcements origin in patch description ([#3175](https://github.com/ReVanced/revanced-patches/issues/3175)) ([0a04500](https://github.com/ReVanced/revanced-patches/commit/0a0450075a6af913de0c8b414103e491e5ff8e72))
|
||||
|
||||
# [2.196.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.195.1-dev.2...v2.196.0-dev.1) (2023-10-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Announcements:** Do not end descriptions with punctuation ([17e414d](https://github.com/ReVanced/revanced-patches/commit/17e414d32b41b66441382d123aa4c16c2547f2c9))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Announcements:** Clarify announcements origin ([03bb7d3](https://github.com/ReVanced/revanced-patches/commit/03bb7d3cff419c5214cf5bc0e5298e612b678d98))
|
||||
|
||||
## [2.195.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.195.1-dev.1...v2.195.1-dev.2) (2023-10-20)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "fix(YouTube - Minimized playback): Fix pip incorrectly showing for Short playback (#3170)" ([4179b16](https://github.com/ReVanced/revanced-patches/commit/4179b166bbdfbe98cc368f4a7ad17419e1b469a9)), closes [#3170](https://github.com/ReVanced/revanced-patches/issues/3170)
|
||||
* Revert "chore(release): 2.195.1-dev.1 [skip ci]" ([be0e0e4](https://github.com/ReVanced/revanced-patches/commit/be0e0e40d6396ceebd40c4e43aecd32dfd86cf0f))
|
||||
|
||||
# [2.195.0](https://github.com/ReVanced/revanced-patches/compare/v2.194.0...v2.195.0) (2023-10-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Indent option description correctly ([d4a9ea1](https://github.com/ReVanced/revanced-patches/commit/d4a9ea1f6c7ab9d25fd60695cce0965c7b5269a4))
|
||||
* **Reddit - Sanitize sharing links:** Restore compatibility with newer versions of the app ([1671d8d](https://github.com/ReVanced/revanced-patches/commit/1671d8d826a08273fae5ccffc4a4ebfef9648fe2))
|
||||
* **YouTube - Hide layout components:** Hide new channel watermark component ([cbfd569](https://github.com/ReVanced/revanced-patches/commit/cbfd5691d31ed144eac1d23de918ab5a6a905dfa))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Theme:** Disable gradient loading screen ([90d5877](https://github.com/ReVanced/revanced-patches/commit/90d5877950095b7abacdca979bc7ad709192eee2))
|
||||
* **YouTube:** Add `Announcements` patch ([#3166](https://github.com/ReVanced/revanced-patches/issues/3166)) ([f977983](https://github.com/ReVanced/revanced-patches/commit/f97798391ffc3477f781d43817664d31cfcd209a))
|
||||
* **YouTube:** Add `Spoof device dimensions` patch ([c8d409e](https://github.com/ReVanced/revanced-patches/commit/c8d409e1dbda6ac45fef01912ce7afad1022b4b7))
|
||||
|
||||
# [2.195.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.195.0-dev.4...v2.195.0-dev.5) (2023-10-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Announcements` patch ([#3166](https://github.com/ReVanced/revanced-patches/issues/3166)) ([f977983](https://github.com/ReVanced/revanced-patches/commit/f97798391ffc3477f781d43817664d31cfcd209a))
|
||||
|
||||
# [2.195.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.195.0-dev.3...v2.195.0-dev.4) (2023-10-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Reddit - Sanitize sharing links:** Restore compatibility with newer versions of the app ([1671d8d](https://github.com/ReVanced/revanced-patches/commit/1671d8d826a08273fae5ccffc4a4ebfef9648fe2))
|
||||
|
||||
# [2.195.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.195.0-dev.2...v2.195.0-dev.3) (2023-10-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Spoof device dimensions` patch ([c8d409e](https://github.com/ReVanced/revanced-patches/commit/c8d409e1dbda6ac45fef01912ce7afad1022b4b7))
|
||||
|
||||
# [2.195.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.195.0-dev.1...v2.195.0-dev.2) (2023-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Indent option description correctly ([d4a9ea1](https://github.com/ReVanced/revanced-patches/commit/d4a9ea1f6c7ab9d25fd60695cce0965c7b5269a4))
|
||||
|
||||
# [2.195.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.194.1-dev.1...v2.195.0-dev.1) (2023-10-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Theme:** Disable gradient loading screen ([90d5877](https://github.com/ReVanced/revanced-patches/commit/90d5877950095b7abacdca979bc7ad709192eee2))
|
||||
|
||||
## [2.194.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.194.0...v2.194.1-dev.1) (2023-10-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Hide new channel watermark component ([cbfd569](https://github.com/ReVanced/revanced-patches/commit/cbfd5691d31ed144eac1d23de918ab5a6a905dfa))
|
||||
|
||||
# [2.194.0](https://github.com/ReVanced/revanced-patches/compare/v2.193.0...v2.194.0) (2023-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix builds ([d7b8149](https://github.com/ReVanced/revanced-patches/commit/d7b8149b0a8dad4e2c201b2f514d298bc6b97f54))
|
||||
* **YouTube - ReturnYouTubeDislike:** Fix dislikes not showing on Shorts ([#3133](https://github.com/ReVanced/revanced-patches/issues/3133)) ([0e8a286](https://github.com/ReVanced/revanced-patches/commit/0e8a2868e8e4328a6f02fa31537abc5e5ed220eb))
|
||||
* **YouTube - Spoof app version:** Recommend clearing the app data after turning off spoofing ([#3134](https://github.com/ReVanced/revanced-patches/issues/3134)) ([166bf5b](https://github.com/ReVanced/revanced-patches/commit/166bf5b1aec5f8868b3895f7e24d2abc9037a7de))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **CieID:** Add `bypass root check` patch ([#3011](https://github.com/ReVanced/revanced-patches/issues/3011)) ([20cfa8a](https://github.com/ReVanced/revanced-patches/commit/20cfa8a5cdebc7e81128c820a2aa01415a068320))
|
||||
* Do not support reading options from a properties file ([3d1c0c1](https://github.com/ReVanced/revanced-patches/commit/3d1c0c1a958271c358755220b97b9dd92eb81d54))
|
||||
* Improve option descriptions and titles ([9f86daa](https://github.com/ReVanced/revanced-patches/commit/9f86daa82271591bcaa9144d300a4810458fdd28))
|
||||
|
||||
# [2.194.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.194.0-dev.2...v2.194.0-dev.3) (2023-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix builds ([d7b8149](https://github.com/ReVanced/revanced-patches/commit/d7b8149b0a8dad4e2c201b2f514d298bc6b97f54))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **CieID:** Add `bypass root check` patch ([#3011](https://github.com/ReVanced/revanced-patches/issues/3011)) ([20cfa8a](https://github.com/ReVanced/revanced-patches/commit/20cfa8a5cdebc7e81128c820a2aa01415a068320))
|
||||
|
||||
# [2.194.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.194.0-dev.1...v2.194.0-dev.2) (2023-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - ReturnYouTubeDislike:** Fix dislikes not showing on Shorts ([#3133](https://github.com/ReVanced/revanced-patches/issues/3133)) ([0e8a286](https://github.com/ReVanced/revanced-patches/commit/0e8a2868e8e4328a6f02fa31537abc5e5ed220eb))
|
||||
|
||||
# [2.194.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.193.1-dev.2...v2.194.0-dev.1) (2023-10-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Do not support reading options from a properties file ([3d1c0c1](https://github.com/ReVanced/revanced-patches/commit/3d1c0c1a958271c358755220b97b9dd92eb81d54))
|
||||
* Improve option descriptions and titles ([9f86daa](https://github.com/ReVanced/revanced-patches/commit/9f86daa82271591bcaa9144d300a4810458fdd28))
|
||||
|
||||
## [2.193.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.193.1-dev.1...v2.193.1-dev.2) (2023-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof app version:** Recommend clearing the app data after turning off spoofing ([#3134](https://github.com/ReVanced/revanced-patches/issues/3134)) ([166bf5b](https://github.com/ReVanced/revanced-patches/commit/166bf5b1aec5f8868b3895f7e24d2abc9037a7de))
|
||||
|
||||
## [2.193.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.193.0...v2.193.1-dev.1) (2023-10-09)
|
||||
|
||||
# [2.193.0](https://github.com/ReVanced/revanced-patches/compare/v2.192.0...v2.193.0) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Boost for Reddit - Spoof client:** Set user-agent for OAuth requests to fix login ([2223951](https://github.com/ReVanced/revanced-patches/commit/2223951fa16011d735ef4c4cda11eba13403f62d))
|
||||
* Consolidate patches ([#3098](https://github.com/ReVanced/revanced-patches/issues/3098)) ([02f767d](https://github.com/ReVanced/revanced-patches/commit/02f767df3cd1b2d0155e7360d2b26fa5d1cfcace))
|
||||
* **Infinity for Reddit - Spoof client:** Set user-agent for OAuth requests to fix login ([a710f05](https://github.com/ReVanced/revanced-patches/commit/a710f05bb46156e66ca56aa4731e1028f459c414))
|
||||
* **Sync for Reddit - Spoof client:** Set user-agent for OAuth requests to fix login ([a48c4a7](https://github.com/ReVanced/revanced-patches/commit/a48c4a7cc1dbb3ecfce2e345240bca8142740b77))
|
||||
* **YouTube:** Sort settings alphabetically despite punctuation ([#3097](https://github.com/ReVanced/revanced-patches/issues/3097)) ([46e3c97](https://github.com/ReVanced/revanced-patches/commit/46e3c97d24e282e4d7d444603af4fb475ae03315))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide shorts components:** Hide subscribe button when paused separately from subscribe button ([52d07ec](https://github.com/ReVanced/revanced-patches/commit/52d07ecd39b1c37cfbfbfa699ccbef849600d9f8))
|
||||
* **YouTube - Return YouTube Dislike:** Support version `18.37.36` ([#3061](https://github.com/ReVanced/revanced-patches/issues/3061)) ([fe11db7](https://github.com/ReVanced/revanced-patches/commit/fe11db70eafb481db87231d3db22eafbaa479871))
|
||||
* **YouTube:** Add `Disable fine scrubbing gesture` patch ([6c9baf2](https://github.com/ReVanced/revanced-patches/commit/6c9baf22614b1be4870be684915445f7a138cf31))
|
||||
* **YouTube:** Bump compatibility to `18.38.44` ([#3071](https://github.com/ReVanced/revanced-patches/issues/3071)) ([a73868c](https://github.com/ReVanced/revanced-patches/commit/a73868cb270295c871a9f1e4d543f728d6152146))
|
||||
|
||||
# [2.193.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v2.193.0-dev.6...v2.193.0-dev.7) (2023-10-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Bump compatibility to `18.38.44` ([#3071](https://github.com/ReVanced/revanced-patches/issues/3071)) ([a73868c](https://github.com/ReVanced/revanced-patches/commit/a73868cb270295c871a9f1e4d543f728d6152146))
|
||||
|
||||
# [2.193.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.193.0-dev.5...v2.193.0-dev.6) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Sort settings alphabetically despite punctuation ([#3097](https://github.com/ReVanced/revanced-patches/issues/3097)) ([46e3c97](https://github.com/ReVanced/revanced-patches/commit/46e3c97d24e282e4d7d444603af4fb475ae03315))
|
||||
|
||||
# [2.193.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.193.0-dev.4...v2.193.0-dev.5) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Consolidate patches ([#3098](https://github.com/ReVanced/revanced-patches/issues/3098)) ([02f767d](https://github.com/ReVanced/revanced-patches/commit/02f767df3cd1b2d0155e7360d2b26fa5d1cfcace))
|
||||
|
||||
# [2.193.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.193.0-dev.3...v2.193.0-dev.4) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Boost for Reddit - Spoof client:** Set user-agent for OAuth requests to fix login ([2223951](https://github.com/ReVanced/revanced-patches/commit/2223951fa16011d735ef4c4cda11eba13403f62d))
|
||||
* **Infinity for Reddit - Spoof client:** Set user-agent for OAuth requests to fix login ([a710f05](https://github.com/ReVanced/revanced-patches/commit/a710f05bb46156e66ca56aa4731e1028f459c414))
|
||||
* **Sync for Reddit - Spoof client:** Set user-agent for OAuth requests to fix login ([a48c4a7](https://github.com/ReVanced/revanced-patches/commit/a48c4a7cc1dbb3ecfce2e345240bca8142740b77))
|
||||
|
||||
# [2.193.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.193.0-dev.2...v2.193.0-dev.3) (2023-10-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Return YouTube Dislike:** Support version `18.37.36` ([#3061](https://github.com/ReVanced/revanced-patches/issues/3061)) ([fe11db7](https://github.com/ReVanced/revanced-patches/commit/fe11db70eafb481db87231d3db22eafbaa479871))
|
||||
|
||||
# [2.193.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.193.0-dev.1...v2.193.0-dev.2) (2023-10-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Disable fine scrubbing gesture` patch ([6c9baf2](https://github.com/ReVanced/revanced-patches/commit/6c9baf22614b1be4870be684915445f7a138cf31))
|
||||
|
||||
# [2.193.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.192.0...v2.193.0-dev.1) (2023-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide shorts components:** Hide subscribe button when paused separately from subscribe button ([52d07ec](https://github.com/ReVanced/revanced-patches/commit/52d07ecd39b1c37cfbfbfa699ccbef849600d9f8))
|
||||
|
||||
# [2.192.0](https://github.com/ReVanced/revanced-patches/compare/v2.191.0...v2.192.0) (2023-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Relay for Reddit - Spoof client:** Prevent OAuth login being disabled remotely ([a0aa2be](https://github.com/ReVanced/revanced-patches/commit/a0aa2be86d25aab2803901b4100fdc75461e94bc))
|
||||
* Remove `dependencies` from generated JSON file ([79bb3e1](https://github.com/ReVanced/revanced-patches/commit/79bb3e164f84094c639ac9e567dc0a5ce70300bd))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TikTok:** Constrain patches to last working version ([066023c](https://github.com/ReVanced/revanced-patches/commit/066023ca148b413b0848c0939e0bab2b3ff32b3a))
|
||||
* **YouTube - Hide "Get YouTube Premium" advertisements:** Name patch correctly ([#3079](https://github.com/ReVanced/revanced-patches/issues/3079)) ([5c140ea](https://github.com/ReVanced/revanced-patches/commit/5c140ea38dc7b7da1efd4b98315fb401267b99f8))
|
||||
|
||||
# [2.192.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.192.0-dev.2...v2.192.0-dev.3) (2023-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Relay for Reddit - Spoof client:** Prevent OAuth login being disabled remotely ([a0aa2be](https://github.com/ReVanced/revanced-patches/commit/a0aa2be86d25aab2803901b4100fdc75461e94bc))
|
||||
|
||||
# [2.192.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.192.0-dev.1...v2.192.0-dev.2) (2023-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TikTok:** Constrain patches to last working version ([066023c](https://github.com/ReVanced/revanced-patches/commit/066023ca148b413b0848c0939e0bab2b3ff32b3a))
|
||||
|
||||
# [2.192.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.191.1-dev.1...v2.192.0-dev.1) (2023-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide "Get YouTube Premium" advertisements:** Name patch correctly ([#3079](https://github.com/ReVanced/revanced-patches/issues/3079)) ([5c140ea](https://github.com/ReVanced/revanced-patches/commit/5c140ea38dc7b7da1efd4b98315fb401267b99f8))
|
||||
|
||||
## [2.191.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.191.0...v2.191.1-dev.1) (2023-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove `dependencies` from generated JSON file ([79bb3e1](https://github.com/ReVanced/revanced-patches/commit/79bb3e164f84094c639ac9e567dc0a5ce70300bd))
|
||||
|
||||
# [2.191.0](https://github.com/ReVanced/revanced-patches/compare/v2.190.0...v2.191.0) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add hooks to existing hook set ([5655067](https://github.com/ReVanced/revanced-patches/commit/5655067f28d010f3a7a6d91b09ac984eee162031))
|
||||
* **Duolingo - Unlock Super:** Get correct instruction offset ([#3023](https://github.com/ReVanced/revanced-patches/issues/3023)) ([5146de8](https://github.com/ReVanced/revanced-patches/commit/5146de872acb17d7c21019ac7ed531f27361038f))
|
||||
* **Google Recorder - Remove device restrictions:** Clarify limitation ([094f57b](https://github.com/ReVanced/revanced-patches/commit/094f57b601d746079c43fd5c8834e3e6be07f946))
|
||||
* **Infinity for Reddit - Spoof client:** Constrain patch to last working versions ([#2944](https://github.com/ReVanced/revanced-patches/issues/2944)) ([ee975de](https://github.com/ReVanced/revanced-patches/commit/ee975dea846c77af0efe608e647075f4055af320))
|
||||
* **Relay - Spoof client:** Restore OAuth login ([96e01f7](https://github.com/ReVanced/revanced-patches/commit/96e01f7a7b87f468776fbde48e114a3f51630a46))
|
||||
* **Slide - Spoof client:** Use correct patch name ([f355dbf](https://github.com/ReVanced/revanced-patches/commit/f355dbf1d2af3075c6a3f13d8bf5f8dca22e6005))
|
||||
* **Sync for Reddit:** Do not throw an error when not necessary ([ef644e4](https://github.com/ReVanced/revanced-patches/commit/ef644e48018a90429108779b7419299c4f43e4ff))
|
||||
* **TikTok - Hide ads:** Constrain to last working version ([56e45a6](https://github.com/ReVanced/revanced-patches/commit/56e45a60a405b5382e1ef6f7bcd5de570c7c52ef))
|
||||
* **Twitch - Audio ads:** Support missing version `16.1.0` ([#2928](https://github.com/ReVanced/revanced-patches/issues/2928)) ([688d8fa](https://github.com/ReVanced/revanced-patches/commit/688d8fa7e86862e03d8336af5f6cb207c4b72593))
|
||||
* Use consistent toggle description ([#2983](https://github.com/ReVanced/revanced-patches/issues/2983)) ([ceaa512](https://github.com/ReVanced/revanced-patches/commit/ceaa512f317fdd95dca37e425b389494a9b2e226))
|
||||
* Use correct instruction ([246cf2c](https://github.com/ReVanced/revanced-patches/commit/246cf2cc92624e43bc7405cb32be9b560bb648c5))
|
||||
* **YouTube - Client spoof:** adjust settings text ([#3035](https://github.com/ReVanced/revanced-patches/issues/3035)) ([59a2e96](https://github.com/ReVanced/revanced-patches/commit/59a2e9617fc4f898e87cefeb3d2c6996b925fa90))
|
||||
* **YouTube - Client spoof:** Display seekbar thumbnails in high quality ([5e8a2d3](https://github.com/ReVanced/revanced-patches/commit/5e8a2d3fe77a4a08ea32e7dc22f2c8e4048b7a6b))
|
||||
* **YouTube - Client spoof:** Do not record feed videos to history by default ([#3017](https://github.com/ReVanced/revanced-patches/issues/3017)) ([5ccbf1b](https://github.com/ReVanced/revanced-patches/commit/5ccbf1bf8ed92cde61689a2b1e3a3c1e915959a7))
|
||||
* **YouTube - Client spoof:** Removed unused code ([#3030](https://github.com/ReVanced/revanced-patches/issues/3030)) ([15e27bf](https://github.com/ReVanced/revanced-patches/commit/15e27bf93e6366ba8a59091409c4271c8230edb6))
|
||||
* **YouTube - Client spoof:** Restore seekbar thumbnails ([bf4a115](https://github.com/ReVanced/revanced-patches/commit/bf4a1159ff745f8f91e11f30db4651d85769227b))
|
||||
* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([1a79300](https://github.com/ReVanced/revanced-patches/commit/1a793007c919753a8c31ab2382d86c0546eefe20))
|
||||
* **YouTube - Custom filter:** Use new lines between components instead of commas ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([ecb2e32](https://github.com/ReVanced/revanced-patches/commit/ecb2e32b1e296590d150bdd3f8bea2665b19a84d))
|
||||
* **YouTube - Hide "Load more" button:** Use correct names ([569c3cd](https://github.com/ReVanced/revanced-patches/commit/569c3cde9875b807c9116322ca324f69b5fa0218))
|
||||
* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#3039](https://github.com/ReVanced/revanced-patches/issues/3039)) ([cb38637](https://github.com/ReVanced/revanced-patches/commit/cb38637e6be968d54561a1e0466b9259dbf0b4ee))
|
||||
* **YouTube - Hide layout components:** Always hide redundant 'player audio track' button ([#2951](https://github.com/ReVanced/revanced-patches/issues/2951)) ([ca632bd](https://github.com/ReVanced/revanced-patches/commit/ca632bd2cc74f0ce5ccb948e902445de3ab893cf))
|
||||
* **YouTube - Hide shorts components:** Fix hiding navigation bar ([2de51e6](https://github.com/ReVanced/revanced-patches/commit/2de51e65f05be8a6364dfdfe9cd36e8fed5737f6))
|
||||
* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([b33ed75](https://github.com/ReVanced/revanced-patches/commit/b33ed757370653b8eb0002b0977eedfbc73dbe5e))
|
||||
* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([3761073](https://github.com/ReVanced/revanced-patches/commit/37610732da87549c22a430bb62d10793dfa2e696))
|
||||
* **YouTube - SponsorBlock:** Adjust import/export UI text ([#3063](https://github.com/ReVanced/revanced-patches/issues/3063)) ([4e5513e](https://github.com/ReVanced/revanced-patches/commit/4e5513e973f5de7c9f6330dfe7a0744e91f305b4))
|
||||
* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([f6f226b](https://github.com/ReVanced/revanced-patches/commit/f6f226ba281823cb5d2d468c32f6e48551971726))
|
||||
* **YouTube:** Restore functionality of `Old video quality menu` and `Custom speeds` on tablets ([#2999](https://github.com/ReVanced/revanced-patches/issues/2999)) ([238bed1](https://github.com/ReVanced/revanced-patches/commit/238bed12519ec61a53b1ee72da467830ef252154))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add notice for thumbnails for age restricted or paid videos ([f7cf70b](https://github.com/ReVanced/revanced-patches/commit/f7cf70b5d3f415411fa767931a33e84df9df6c16))
|
||||
* **Duolingo:** Remove `Unlock Duolingo Super` patch ([b4b9746](https://github.com/ReVanced/revanced-patches/commit/b4b9746361b5435b9d9429ad065e53364c51904a))
|
||||
* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([481bf58](https://github.com/ReVanced/revanced-patches/commit/481bf583afbf954bef1c4e5349a62ea1c623115a))
|
||||
* **Strava:** Add `Disable subscription suggestions` patch ([#2997](https://github.com/ReVanced/revanced-patches/issues/2997)) ([af02175](https://github.com/ReVanced/revanced-patches/commit/af0217594d9c7526f550fc7e6f09f8a9232e72cf))
|
||||
* **Sync for Reddit - Client spoof:** Restore upload functionality ([9344c8a](https://github.com/ReVanced/revanced-patches/commit/9344c8a067127b0fb4ee8599c5dcfcb206b4ee07))
|
||||
* **TikTok - Hide ads:** Constrain to last working version ([516e8a1](https://github.com/ReVanced/revanced-patches/commit/516e8a14c0e113f9f4c0dda9be223cf3e929eb3a))
|
||||
* **TU Dortmund:** Add `Show on lockscreen` patch ([#2947](https://github.com/ReVanced/revanced-patches/issues/2947)) ([9a18326](https://github.com/ReVanced/revanced-patches/commit/9a18326aeb68d7518594d0eab326ca845b9bdbdd))
|
||||
* **Tumblr:** Add `Disable blog notification reminder` patch ([29f19b9](https://github.com/ReVanced/revanced-patches/commit/29f19b9378c7e167137f38fa4517ae19382ca4f6))
|
||||
* **Tumblr:** Add `Disable dashboard ads` patch ([#2979](https://github.com/ReVanced/revanced-patches/issues/2979)) ([07c267a](https://github.com/ReVanced/revanced-patches/commit/07c267ad20afa1415d2dba31f0830d2dd5a34654))
|
||||
* **Tumblr:** Add `Disable gift message popup` patch ([a4d6b4e](https://github.com/ReVanced/revanced-patches/commit/a4d6b4e5ce6065d932f3895b4996e7dc1e5f7c67))
|
||||
* **Tumblr:** Add `Disable in-app update` patch ([#3058](https://github.com/ReVanced/revanced-patches/issues/3058)) ([5e8076b](https://github.com/ReVanced/revanced-patches/commit/5e8076b330cabe57130233adacdf84b56f010217))
|
||||
* **Tumblr:** Add `Disable Tumblr Live` patch ([#2987](https://github.com/ReVanced/revanced-patches/issues/2987)) ([bf1f9dc](https://github.com/ReVanced/revanced-patches/commit/bf1f9dc799705679d17973e689165ab1bff327cd))
|
||||
* **Twitch - Block embedded ads:** Switch from `ttv.lol` to `luminous.dev` ([0fe115e](https://github.com/ReVanced/revanced-patches/commit/0fe115e8f98ccdc86d318090fc92fe77cece1dd8))
|
||||
* Use properties file for `Client spoof` patches ([e5d548c](https://github.com/ReVanced/revanced-patches/commit/e5d548c6427fb54968f26d706ff16274e72f700a))
|
||||
* **YouTube - Hide layout components:** Hide "Join" button ([1b71f89](https://github.com/ReVanced/revanced-patches/commit/1b71f893bb9fd8511833b8895031c8d8122a6efb))
|
||||
* **YouTube - Hide layout components:** Hide "Notify me" button ([3027c15](https://github.com/ReVanced/revanced-patches/commit/3027c1575717588f43f4b95be6ba97dac2b94069))
|
||||
* **YouTube - Hide layout components:** Hide search result shelf header ([f4eda8c](https://github.com/ReVanced/revanced-patches/commit/f4eda8c8d111cc856d5878a32ddca3f7c2e0df31))
|
||||
* **YouTube - Hide layout components:** Hide timed reactions ([d0a775d](https://github.com/ReVanced/revanced-patches/commit/d0a775d685b1e0564804d564d1cbcbb8d0a04b03))
|
||||
* **YouTube - Premium heading:** Allow using default heading ([#3029](https://github.com/ReVanced/revanced-patches/issues/3029)) ([d5ab35a](https://github.com/ReVanced/revanced-patches/commit/d5ab35a444523baa0586fcb9513d6ae4f2518946))
|
||||
* **YouTube - Spoof app version:** add version 18.20.39 ([#3001](https://github.com/ReVanced/revanced-patches/issues/3001)) ([f14c5e7](https://github.com/ReVanced/revanced-patches/commit/f14c5e79792f62fb060dd0eebbd3dd7157a08a98))
|
||||
* **YouTube:** Add `Bypass URL redirects` patch ([125cac5](https://github.com/ReVanced/revanced-patches/commit/125cac5928c9b71d35253f1fd7651f4a30e15529))
|
||||
* **YouTube:** Bump compatibility to `18.37.36` ([#3028](https://github.com/ReVanced/revanced-patches/issues/3028)) ([eda28e5](https://github.com/ReVanced/revanced-patches/commit/eda28e507e7fb5171eeb15a5a0532929ee611211))
|
||||
|
||||
# [2.191.0-dev.33](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.32...v2.191.0-dev.33) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok - Hide ads:** Constrain to last working version ([56e45a6](https://github.com/ReVanced/revanced-patches/commit/56e45a60a405b5382e1ef6f7bcd5de570c7c52ef))
|
||||
|
||||
# [2.191.0-dev.32](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.31...v2.191.0-dev.32) (2023-10-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Sync for Reddit:** Do not throw an error when not necessary ([ef644e4](https://github.com/ReVanced/revanced-patches/commit/ef644e48018a90429108779b7419299c4f43e4ff))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Sync for Reddit - Client spoof:** Restore upload functionality ([9344c8a](https://github.com/ReVanced/revanced-patches/commit/9344c8a067127b0fb4ee8599c5dcfcb206b4ee07))
|
||||
* Use properties file for `Client spoof` patches ([e5d548c](https://github.com/ReVanced/revanced-patches/commit/e5d548c6427fb54968f26d706ff16274e72f700a))
|
||||
|
||||
# [2.191.0-dev.31](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.30...v2.191.0-dev.31) (2023-10-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Adjust import/export UI text ([#3063](https://github.com/ReVanced/revanced-patches/issues/3063)) ([4e5513e](https://github.com/ReVanced/revanced-patches/commit/4e5513e973f5de7c9f6330dfe7a0744e91f305b4))
|
||||
|
||||
# [2.191.0-dev.30](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.29...v2.191.0-dev.30) (2023-10-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add hooks to existing hook set ([5655067](https://github.com/ReVanced/revanced-patches/commit/5655067f28d010f3a7a6d91b09ac984eee162031))
|
||||
* **Google Recorder - Remove device restrictions:** Clarify limitation ([094f57b](https://github.com/ReVanced/revanced-patches/commit/094f57b601d746079c43fd5c8834e3e6be07f946))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Hide search result shelf header ([f4eda8c](https://github.com/ReVanced/revanced-patches/commit/f4eda8c8d111cc856d5878a32ddca3f7c2e0df31))
|
||||
|
||||
# [2.191.0-dev.29](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.28...v2.191.0-dev.29) (2023-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TikTok - Hide ads:** Constrain to last working version ([516e8a1](https://github.com/ReVanced/revanced-patches/commit/516e8a14c0e113f9f4c0dda9be223cf3e929eb3a))
|
||||
|
||||
# [2.191.0-dev.28](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.27...v2.191.0-dev.28) (2023-10-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide "Load more" button:** Use correct names ([569c3cd](https://github.com/ReVanced/revanced-patches/commit/569c3cde9875b807c9116322ca324f69b5fa0218))
|
||||
* **YouTube - Hide shorts components:** Fix hiding navigation bar ([2de51e6](https://github.com/ReVanced/revanced-patches/commit/2de51e65f05be8a6364dfdfe9cd36e8fed5737f6))
|
||||
|
||||
# [2.191.0-dev.27](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.26...v2.191.0-dev.27) (2023-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Tumblr:** Add `Disable in-app update` patch ([#3058](https://github.com/ReVanced/revanced-patches/issues/3058)) ([5e8076b](https://github.com/ReVanced/revanced-patches/commit/5e8076b330cabe57130233adacdf84b56f010217))
|
||||
|
||||
# [2.191.0-dev.26](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.25...v2.191.0-dev.26) (2023-10-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use correct instruction ([246cf2c](https://github.com/ReVanced/revanced-patches/commit/246cf2cc92624e43bc7405cb32be9b560bb648c5))
|
||||
|
||||
# [2.191.0-dev.25](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.24...v2.191.0-dev.25) (2023-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Hide "Join" button ([1b71f89](https://github.com/ReVanced/revanced-patches/commit/1b71f893bb9fd8511833b8895031c8d8122a6efb))
|
||||
* **YouTube - Hide layout components:** Hide "Notify me" button ([3027c15](https://github.com/ReVanced/revanced-patches/commit/3027c1575717588f43f4b95be6ba97dac2b94069))
|
||||
* **YouTube - Hide layout components:** Hide timed reactions ([d0a775d](https://github.com/ReVanced/revanced-patches/commit/d0a775d685b1e0564804d564d1cbcbb8d0a04b03))
|
||||
|
||||
# [2.191.0-dev.24](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.23...v2.191.0-dev.24) (2023-09-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Duolingo:** Remove `Unlock Duolingo Super` patch ([b4b9746](https://github.com/ReVanced/revanced-patches/commit/b4b9746361b5435b9d9429ad065e53364c51904a))
|
||||
|
||||
# [2.191.0-dev.23](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.22...v2.191.0-dev.23) (2023-09-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([481bf58](https://github.com/ReVanced/revanced-patches/commit/481bf583afbf954bef1c4e5349a62ea1c623115a))
|
||||
|
||||
# [2.191.0-dev.22](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.21...v2.191.0-dev.22) (2023-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([b33ed75](https://github.com/ReVanced/revanced-patches/commit/b33ed757370653b8eb0002b0977eedfbc73dbe5e))
|
||||
|
||||
# [2.191.0-dev.21](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.20...v2.191.0-dev.21) (2023-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([3761073](https://github.com/ReVanced/revanced-patches/commit/37610732da87549c22a430bb62d10793dfa2e696))
|
||||
|
||||
# [2.191.0-dev.20](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.19...v2.191.0-dev.20) (2023-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([f6f226b](https://github.com/ReVanced/revanced-patches/commit/f6f226ba281823cb5d2d468c32f6e48551971726))
|
||||
|
||||
# [2.191.0-dev.19](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.18...v2.191.0-dev.19) (2023-09-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Bypass URL redirects` patch ([125cac5](https://github.com/ReVanced/revanced-patches/commit/125cac5928c9b71d35253f1fd7651f4a30e15529))
|
||||
|
||||
# [2.191.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.17...v2.191.0-dev.18) (2023-09-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Premium heading:** Allow using default heading ([#3029](https://github.com/ReVanced/revanced-patches/issues/3029)) ([d5ab35a](https://github.com/ReVanced/revanced-patches/commit/d5ab35a444523baa0586fcb9513d6ae4f2518946))
|
||||
|
||||
# [2.191.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.16...v2.191.0-dev.17) (2023-09-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Bump compatibility to `18.37.36` ([#3028](https://github.com/ReVanced/revanced-patches/issues/3028)) ([eda28e5](https://github.com/ReVanced/revanced-patches/commit/eda28e507e7fb5171eeb15a5a0532929ee611211))
|
||||
|
||||
# [2.191.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.15...v2.191.0-dev.16) (2023-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#3039](https://github.com/ReVanced/revanced-patches/issues/3039)) ([cb38637](https://github.com/ReVanced/revanced-patches/commit/cb38637e6be968d54561a1e0466b9259dbf0b4ee))
|
||||
|
||||
# [2.191.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.14...v2.191.0-dev.15) (2023-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Client spoof:** adjust settings text ([#3035](https://github.com/ReVanced/revanced-patches/issues/3035)) ([59a2e96](https://github.com/ReVanced/revanced-patches/commit/59a2e9617fc4f898e87cefeb3d2c6996b925fa90))
|
||||
|
||||
# [2.191.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.13...v2.191.0-dev.14) (2023-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([1a79300](https://github.com/ReVanced/revanced-patches/commit/1a793007c919753a8c31ab2382d86c0546eefe20))
|
||||
|
||||
# [2.191.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.12...v2.191.0-dev.13) (2023-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Client spoof:** Removed unused code ([#3030](https://github.com/ReVanced/revanced-patches/issues/3030)) ([15e27bf](https://github.com/ReVanced/revanced-patches/commit/15e27bf93e6366ba8a59091409c4271c8230edb6))
|
||||
|
||||
# [2.191.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.11...v2.191.0-dev.12) (2023-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Client spoof:** Display seekbar thumbnails in high quality ([5e8a2d3](https://github.com/ReVanced/revanced-patches/commit/5e8a2d3fe77a4a08ea32e7dc22f2c8e4048b7a6b))
|
||||
|
||||
# [2.191.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.10...v2.191.0-dev.11) (2023-09-25)
|
||||
|
||||
|
||||
|
||||
@@ -28,18 +28,21 @@
|
||||
<a href="https://t.me/app_revanced">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
</a>
|
||||
<a href="https://twitter.com/revancedapp">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032018-6da37214-7474-4641-a1da-7af7db3a31cd.png" />
|
||||
<a href="https://x.com/revancedapp">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
|
||||
<picture/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@ReVanced">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
</a>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
Continuing the legacy of Vanced
|
||||
</p>
|
||||
|
||||
# 📙 ReVanced Patches contribution guidelines
|
||||
# 👋 Contribution guidelines
|
||||
|
||||
This document describes how to contribute to ReVanced Patches.
|
||||
|
||||
|
||||
10
README.md
10
README.md
@@ -28,18 +28,20 @@
|
||||
<a href="https://t.me/app_revanced">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
</a>
|
||||
<a href="https://twitter.com/revancedapp">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032018-6da37214-7474-4641-a1da-7af7db3a31cd.png" />
|
||||
<a href="https://x.com/revancedapp">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
|
||||
<picture/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@ReVanced">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
</a>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
Continuing the legacy of Vanced
|
||||
</p>
|
||||
|
||||
|
||||
# 🧩 ReVanced Patches
|
||||
|
||||

|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import org.gradle.kotlin.dsl.support.listFilesOrdered
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.8.20"
|
||||
alias(libs.plugins.ksp)
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
group = "app.revanced"
|
||||
@@ -9,13 +12,7 @@ repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
google()
|
||||
maven {
|
||||
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
|
||||
credentials {
|
||||
username = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR")
|
||||
password = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN")
|
||||
}
|
||||
}
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
// Required for FlexVer-Java
|
||||
maven {
|
||||
url = uri("https://repo.sleeping.town")
|
||||
@@ -33,6 +30,7 @@ dependencies {
|
||||
implementation(libs.guava)
|
||||
// Used in JsonGenerator.
|
||||
implementation(libs.gson)
|
||||
|
||||
// A dependency to the Android library unfortunately fails the build, which is why this is required.
|
||||
compileOnly(project("dummy"))
|
||||
|
||||
@@ -46,40 +44,74 @@ kotlin {
|
||||
tasks {
|
||||
register<DefaultTask>("generateBundle") {
|
||||
description = "Generate dex files from build and bundle them in the jar file"
|
||||
|
||||
dependsOn(build)
|
||||
|
||||
doLast {
|
||||
val androidHome = System.getenv("ANDROID_HOME") ?: throw GradleException("ANDROID_HOME not found")
|
||||
val d8 = "${androidHome}/build-tools/33.0.1/d8"
|
||||
val input = configurations.archives.get().allArtifacts.files.files.first().absolutePath
|
||||
val work = layout.buildDirectory.dir("libs").get().asFile
|
||||
val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools")
|
||||
.listFilesOrdered().last().resolve("d8").absolutePath
|
||||
|
||||
val artifacts = configurations.archives.get().allArtifacts.files.files.first().absolutePath
|
||||
val workingDirectory = layout.buildDirectory.dir("libs").get().asFile
|
||||
|
||||
exec {
|
||||
workingDir = work
|
||||
commandLine = listOf(d8, input)
|
||||
workingDir = workingDirectory
|
||||
commandLine = listOf(d8, artifacts)
|
||||
}
|
||||
|
||||
exec {
|
||||
workingDir = work
|
||||
commandLine = listOf("zip", "-u", input, "classes.dex")
|
||||
workingDir = workingDirectory
|
||||
commandLine = listOf("zip", "-u", artifacts, "classes.dex")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register<JavaExec>("generateMeta") {
|
||||
description = "Generate metadata for this bundle"
|
||||
|
||||
dependsOn(build)
|
||||
|
||||
classpath = sourceSets["main"].runtimeClasspath
|
||||
mainClass.set("app.revanced.meta.PatchesFileGenerator")
|
||||
}
|
||||
|
||||
// Dummy task to fix the Gradle semantic-release plugin.
|
||||
// Remove this if you forked it to support building only.
|
||||
// Tracking issue: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
||||
register<DefaultTask>("publish") {
|
||||
group = "publish"
|
||||
description = "Dummy task"
|
||||
dependsOn(named("generateBundle"), named("generateMeta"))
|
||||
// Required to run tasks because Gradle semantic-release plugin runs the publish task.
|
||||
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
||||
named("publish") {
|
||||
dependsOn("generateBundle")
|
||||
dependsOn("generateMeta")
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("revanced-patches-publication") {
|
||||
from(components["java"])
|
||||
|
||||
pom {
|
||||
name = "ReVanced Patches"
|
||||
description = "Patches for ReVanced."
|
||||
url = "https://revanced.app"
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = "GNU General Public License v3.0"
|
||||
url = "https://www.gnu.org/licenses/gpl-3.0.en.html"
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = "ReVanced"
|
||||
name = "ReVanced"
|
||||
email = "contact@revanced.app"
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection = "scm:git:git://github.com/revanced/revanced-patches.git"
|
||||
developerConnection = "scm:git:git@github.com:revanced/revanced-patches.git"
|
||||
url = "https://github.com/revanced/revanced-patches"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 2.191.0-dev.11
|
||||
version = 2.196.0-dev.2
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
[versions]
|
||||
revanced-patcher = "15.0.1"
|
||||
revanced-patch-annotation-processor = "15.0.1"
|
||||
revanced-patcher = "17.0.0"
|
||||
revanced-patch-annotation-processor = "17.0.0"
|
||||
ksp = "1.9.0-1.0.11"
|
||||
smali = "3.0.3"
|
||||
guava = "32.1.2-jre"
|
||||
gson = "2.10.1"
|
||||
|
||||
[libraries]
|
||||
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
||||
revanced-patch-annotation-processor = { module = "app.revanced:revanced-patch-annotation-processor", version.ref = "revanced-patch-annotation-processor" }
|
||||
revanced-patcher = { module = "app.revanced.revanced-patcher:revanced-patcher", version.ref = "revanced-patcher" }
|
||||
revanced-patch-annotation-processor = { module = "app.revanced.revanced-patcher:revanced-patch-annotation-processor", version.ref = "revanced-patch-annotation-processor" }
|
||||
smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }
|
||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -7,7 +7,6 @@ import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
@@ -58,38 +57,38 @@ fun MutableMethod.injectHideViewCall(
|
||||
)
|
||||
|
||||
/**
|
||||
* Find the index of the first constant instruction with the id of the given resource name.
|
||||
* Find the index of the first instruction with the id of the given resource name.
|
||||
*
|
||||
* @param resourceName the name of the resource to find the id for.
|
||||
* @return the index of the first constant instruction with the id of the given resource name, or -1 if not found.
|
||||
* @return the index of the first instruction with the id of the given resource name, or -1 if not found.
|
||||
*/
|
||||
fun Method.findIndexForIdResource(resourceName: String): Int {
|
||||
fun getIdResourceId(resourceName: String) = ResourceMappingPatch.resourceMappings.single {
|
||||
it.type == "id" && it.name == resourceName
|
||||
}.id
|
||||
|
||||
return indexOfFirstConstantInstructionValue(getIdResourceId(resourceName))
|
||||
return indexOfFirstWideLiteralInstructionValue(getIdResourceId(resourceName))
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the first constant instruction with the given value.
|
||||
* Find the index of the first wide literal instruction with the given value.
|
||||
*
|
||||
* @return the first constant instruction with the value, or -1 if not found.
|
||||
* @return the first literal instruction with the value, or -1 if not found.
|
||||
*/
|
||||
fun Method.indexOfFirstConstantInstructionValue(constantValue: Long) = implementation?.let {
|
||||
fun Method.indexOfFirstWideLiteralInstructionValue(literal: Long) = implementation?.let {
|
||||
it.instructions.indexOfFirst { instruction ->
|
||||
instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == constantValue
|
||||
(instruction as? WideLiteralInstruction)?.wideLiteral == literal
|
||||
}
|
||||
} ?: -1
|
||||
|
||||
|
||||
/**
|
||||
* Check if the method contains a constant with the given value.
|
||||
* Check if the method contains a literal with the given value.
|
||||
*
|
||||
* @return if the method contains a constant with the given value.
|
||||
* @return if the method contains a literal with the given value.
|
||||
*/
|
||||
fun Method.containsConstantInstructionValue(constantValue: Long) =
|
||||
indexOfFirstConstantInstructionValue(constantValue) >= 0
|
||||
fun Method.containsWideLiteralInstructionValue(literal: Long) =
|
||||
indexOfFirstWideLiteralInstructionValue(literal) >= 0
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,6 @@ internal class JsonGenerator : PatchesFileGenerator {
|
||||
it.name!!,
|
||||
it.description,
|
||||
it.compatiblePackages,
|
||||
it.dependencies?.map { dependency -> dependency::class.java.name }?.toSet(),
|
||||
it.use,
|
||||
it.requiresIntegrations,
|
||||
it.options.values.map { option ->
|
||||
@@ -27,7 +26,6 @@ internal class JsonGenerator : PatchesFileGenerator {
|
||||
val name: String? = null,
|
||||
val description: String? = null,
|
||||
val compatiblePackages: Set<Patch.CompatiblePackage>? = null,
|
||||
val dependencies: Set<String>? = null,
|
||||
val use: Boolean = true,
|
||||
val requiresIntegrations: Boolean = false,
|
||||
val options: List<Option>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.cieid.restrictions.root
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.cieid.restrictions.root.fingerprints.CheckRootFingerprint
|
||||
|
||||
@Patch(
|
||||
name = "Bypass root checks",
|
||||
description = "Removes the restriction to use the app with root permissions or on a custom ROM.",
|
||||
compatiblePackages = [CompatiblePackage("it.ipzs.cieid")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object BypassRootChecksPatch : BytecodePatch(
|
||||
setOf(CheckRootFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
CheckRootFingerprint.result?.mutableMethod?.addInstruction(1, "return-void")
|
||||
?: throw CheckRootFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.cieid.restrictions.root.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object CheckRootFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass == "Lit/ipzs/cieid/BaseActivity;" && methodDef.name == "onResume"
|
||||
}
|
||||
)
|
||||
@@ -1,62 +0,0 @@
|
||||
package app.revanced.patches.duolingo.unlocksuper
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.duolingo.unlocksuper.fingerprints.IsUserSuperMethodFingerprint
|
||||
import app.revanced.patches.duolingo.unlocksuper.fingerprints.UserSerializationMethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.Reference
|
||||
|
||||
@Patch(
|
||||
name = "Unlock Duolingo Super",
|
||||
compatiblePackages = [CompatiblePackage("com.duolingo")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object UnlockDuolingoSuperPatch : BytecodePatch(
|
||||
setOf(
|
||||
UserSerializationMethodFingerprint,
|
||||
IsUserSuperMethodFingerprint
|
||||
)
|
||||
) {
|
||||
/* First find the reference to the isUserSuper field, then patch the instruction that assigns it to false.
|
||||
* This strategy is used because the method that sets the isUserSuper field is difficult to fingerprint reliably.
|
||||
*/
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Find the reference to the isUserSuper field.
|
||||
val isUserSuperReference = IsUserSuperMethodFingerprint
|
||||
.result
|
||||
?.mutableMethod
|
||||
?.getInstructions()
|
||||
?.filterIsInstance<BuilderInstruction22c>()
|
||||
?.firstOrNull { it.opcode == Opcode.IGET_BOOLEAN }
|
||||
?.reference
|
||||
?: throw IsUserSuperMethodFingerprint.exception
|
||||
|
||||
// Patch the instruction that assigns isUserSuper to true.
|
||||
UserSerializationMethodFingerprint
|
||||
.result
|
||||
?.mutableMethod
|
||||
?.apply {
|
||||
replaceInstructions(
|
||||
indexOfReference(isUserSuperReference) - 1,
|
||||
"const/4 v2, 0x1"
|
||||
)
|
||||
}
|
||||
?: throw UserSerializationMethodFingerprint.exception
|
||||
}
|
||||
|
||||
private fun MutableMethod.indexOfReference(reference: Reference) = getInstructions()
|
||||
.indexOfFirst { it is BuilderInstruction22c && it.opcode == Opcode.IPUT_BOOLEAN && it.reference == reference }
|
||||
.let {
|
||||
if (it == -1) throw PatchException("Could not find index of instruction with supplied reference.")
|
||||
else it
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package app.revanced.patches.duolingo.unlocksuper.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object UserSerializationMethodFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
strings = listOf(
|
||||
"betaStatus",
|
||||
"coachOutfit",
|
||||
"globalAmbassadorStatus",
|
||||
),
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_FROM16,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
),
|
||||
)
|
||||
@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Remove device restrictions",
|
||||
description = "Removes restrictions from using the app on any device.",
|
||||
description = "Removes restrictions from using the app on any device. Requires mounting patched app over original.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.recorder")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -12,8 +12,8 @@ import app.revanced.util.microg.MicroGBytecodeHelper
|
||||
|
||||
|
||||
@Patch(
|
||||
name = "MicroG support",
|
||||
description = "Allows YouTube Music ReVanced to run without root and under a different package name.",
|
||||
name = "Vanced MicroG support",
|
||||
description = "Allows YouTube Music to run without root and under a different package name.",
|
||||
dependencies = [MicroGResourcePatch::class],
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
|
||||
)
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package app.revanced.patches.reddit.customclients
|
||||
|
||||
import android.os.Environment
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractSpoofClientPatch(
|
||||
private val redirectUri: String,
|
||||
redirectUri: String,
|
||||
private val clientIdFingerprints: List<MethodFingerprint>,
|
||||
private val userAgentFingerprints: List<MethodFingerprint>? = null,
|
||||
private val miscellaneousFingerprints: List<MethodFingerprint>? = null
|
||||
@@ -24,34 +21,14 @@ abstract class AbstractSpoofClientPatch(
|
||||
"client-id",
|
||||
null,
|
||||
"OAuth client ID",
|
||||
"The Reddit OAuth client ID."
|
||||
"The Reddit OAuth client ID. " +
|
||||
"You can get your client ID from https://www.reddit.com/prefs/apps. " +
|
||||
"The application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"$redirectUri\".",
|
||||
true
|
||||
)
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
if (clientId == null) {
|
||||
// Ensure device runs Android.
|
||||
try {
|
||||
Class.forName("android.os.Environment")
|
||||
} catch (e: ClassNotFoundException) {
|
||||
throw PatchException("No client ID provided")
|
||||
}
|
||||
|
||||
File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also {
|
||||
if (it.exists()) return@also
|
||||
|
||||
val error = """
|
||||
In order to use this patch, you need to provide a client ID.
|
||||
You can do that by creating a file at ${it.absolutePath} with the client ID as its content.
|
||||
Alternatively, you can provide the client ID using patch options.
|
||||
|
||||
You can get your client ID from https://www.reddit.com/prefs/apps.
|
||||
The application type has to be "Installed app" and the redirect URI has to be set to "$redirectUri".
|
||||
""".trimIndent()
|
||||
|
||||
throw PatchException(error)
|
||||
}.let { clientId = it.readText().trim() }
|
||||
}
|
||||
|
||||
fun List<MethodFingerprint>?.executePatch(
|
||||
patch: List<MethodFingerprintResult>.(BytecodeContext) -> Unit
|
||||
) = this?.map { it.result ?: throw it.exception }?.patch(context)
|
||||
@@ -85,5 +62,6 @@ abstract class AbstractSpoofClientPatch(
|
||||
*
|
||||
* @param context The current [BytecodeContext].
|
||||
*/
|
||||
open fun List<MethodFingerprintResult>.patchMiscellaneous(context: BytecodeContext) { }
|
||||
// Not every client needs to patch miscellaneous things.
|
||||
open fun List<MethodFingerprintResult>.patchMiscellaneous(context: BytecodeContext) {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients
|
||||
|
||||
object Constants {
|
||||
const val OAUTH_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60"
|
||||
}
|
||||
@@ -14,9 +14,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://baconreader.com/auth\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.onelouder.baconreader"),
|
||||
CompatiblePackage("com.onelouder.baconreader.premium")
|
||||
|
||||
@@ -6,18 +6,20 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.Constants.OAUTH_USER_AGENT
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.LoginActivityOnCreateFingerprint
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://rubenmayayo.com\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
compatiblePackages = [CompatiblePackage("com.rubenmayayo.reddit")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"http://rubenmayayo.com", listOf(GetClientIdFingerprint)
|
||||
"http://rubenmayayo.com",
|
||||
clientIdFingerprints = listOf(GetClientIdFingerprint),
|
||||
userAgentFingerprints = listOf(LoginActivityOnCreateFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
|
||||
first().mutableMethod.addInstructions(
|
||||
@@ -28,4 +30,20 @@ object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
override fun List<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
|
||||
first().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val insertIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
const-string v7, "$OAUTH_USER_AGENT"
|
||||
invoke-virtual {v4, v7}, Landroid/webkit/WebSettings;->setUserAgentString(Ljava/lang/String;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object LoginActivityOnCreateFingerprint : MethodFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_4
|
||||
),
|
||||
customFingerprint = { method, classDef ->
|
||||
method.name == "onCreate" && classDef.type.endsWith("LoginActivity;")
|
||||
}
|
||||
)
|
||||
@@ -1,21 +1,22 @@
|
||||
package app.revanced.patches.reddit.customclients.infinityforreddit.api
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.Constants.OAUTH_USER_AGENT
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.GetHttpBasicAuthHeaderFingerprint
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.LoginActivityOnCreateFingerprint
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.SetWebViewSettingsFingerprint
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"infinity://localhost\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"ml.docilealligator.infinityforreddit", [
|
||||
@@ -34,7 +35,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@Suppress("unused")
|
||||
object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"infinity://localhost",
|
||||
listOf(GetHttpBasicAuthHeaderFingerprint, LoginActivityOnCreateFingerprint)
|
||||
clientIdFingerprints = listOf(GetHttpBasicAuthHeaderFingerprint, LoginActivityOnCreateFingerprint),
|
||||
userAgentFingerprints = listOf(SetWebViewSettingsFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
|
||||
forEach {
|
||||
@@ -50,4 +52,18 @@ object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun List<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
|
||||
first().let { result ->
|
||||
val insertIndex = result.scanResult.stringsScanResult!!.matches.first().index
|
||||
|
||||
result.mutableMethod.addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
const-string v0, "$OAUTH_USER_AGENT"
|
||||
invoke-virtual {p1, v0}, Landroid/webkit/WebSettings;->setUserAgentString(Ljava/lang/String;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object SetWebViewSettingsFingerprint : MethodFingerprint(
|
||||
strings= listOf("https://www.reddit.com/api/v1/authorize.compact")
|
||||
)
|
||||
@@ -12,9 +12,7 @@ import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"https://127.0.0.1:65023/authorize_callback\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
dependencies = [DisablePiracyDetectionPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("o.o.joey"),
|
||||
|
||||
@@ -16,9 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"redditisfun://auth\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.andrewshu.android.reddit"),
|
||||
CompatiblePackage("com.andrewshu.android.redditdonation")
|
||||
|
||||
@@ -9,13 +9,14 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.*
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction10t
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"dbrady://relay\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("free.reddit.news"),
|
||||
CompatiblePackage("reddit.news")
|
||||
@@ -30,7 +31,10 @@ object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
GetLoggedOutBearerTokenFingerprint,
|
||||
GetRefreshTokenFingerprint
|
||||
),
|
||||
miscellaneousFingerprints = listOf(SetRemoteConfigFingerprint)
|
||||
miscellaneousFingerprints = listOf(
|
||||
SetRemoteConfigFingerprint,
|
||||
RedditCheckDisableAPIFingerprint
|
||||
)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
|
||||
forEach {
|
||||
@@ -46,7 +50,24 @@ object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
}
|
||||
}
|
||||
|
||||
override fun List<MethodFingerprintResult>.patchMiscellaneous(context: BytecodeContext) =
|
||||
// Do not load remote config which disables OAuth login remotely
|
||||
override fun List<MethodFingerprintResult>.patchMiscellaneous(context: BytecodeContext) {
|
||||
// Do not load remote config which disables OAuth login remotely.
|
||||
first().mutableMethod.addInstructions(0, "return-void")
|
||||
|
||||
// Prevent OAuth login being disabled remotely.
|
||||
last().let {
|
||||
val checkIsOAuthRequestIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val returnNextChain = getInstruction<BuilderInstruction21t>(checkIsOAuthRequestIndex).target
|
||||
replaceInstruction(
|
||||
checkIsOAuthRequestIndex,
|
||||
BuilderInstruction10t(
|
||||
Opcode.GOTO,
|
||||
returnNextChain
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object RedditCheckDisableAPIFingerprint : MethodFingerprint(
|
||||
strings = listOf("Reddit Disabled"),
|
||||
opcodes = listOf(Opcode.IF_EQZ)
|
||||
)
|
||||
@@ -10,9 +10,7 @@ import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://www.ccrama.me\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
compatiblePackages = [CompatiblePackage("me.ccrama.redditslide")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -10,8 +10,11 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.Constants.OAUTH_USER_AGENT
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.ImgurImageAPIFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.LoadBrowserURLFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
@@ -20,9 +23,7 @@ import java.util.*
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://redditsync/auth\".",
|
||||
description = "Restores functionality of the app by using custom client ID's.",
|
||||
dependencies = [DisablePiracyDetectionPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.laurencedawson.reddit_sync"),
|
||||
@@ -32,7 +33,10 @@ import java.util.*
|
||||
)
|
||||
@Suppress("unused")
|
||||
object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"http://redditsync/auth", listOf(GetAuthorizationStringFingerprint)
|
||||
"http://redditsync/auth",
|
||||
clientIdFingerprints = listOf(GetAuthorizationStringFingerprint),
|
||||
userAgentFingerprints = listOf(LoadBrowserURLFingerprint),
|
||||
miscellaneousFingerprints = listOf(ImgurImageAPIFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
|
||||
forEach { fingerprintResult ->
|
||||
@@ -68,4 +72,28 @@ object SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the non-commercial Imgur API endpoint.
|
||||
override fun List<MethodFingerprintResult>.patchMiscellaneous(context: BytecodeContext) = first().let {
|
||||
val apiUrlIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
|
||||
it.mutableMethod.replaceInstruction(
|
||||
apiUrlIndex,
|
||||
"const-string v1, \"https://api.imgur.com/3/image\""
|
||||
)
|
||||
}
|
||||
|
||||
override fun List<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
|
||||
first().let { result ->
|
||||
val insertIndex = result.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
result.mutableMethod.addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
const-string v0, "$OAUTH_USER_AGENT"
|
||||
invoke-virtual {p1, v0}, Landroid/webkit/WebSettings;->setUserAgentString(Ljava/lang/String;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object ImgurImageAPIFingerprint : MethodFingerprint(
|
||||
strings = listOf(
|
||||
"https://imgur-apiv3.p.rapidapi.com/3/image",
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object LoadBrowserURLFingerprint : MethodFingerprint(
|
||||
parameters = listOf("Landroid/view/View;", "Landroid/os/Bundle;"),
|
||||
opcodes = listOf(Opcode.CONST_4),
|
||||
strings = listOf("CustomInterface")
|
||||
)
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
@@ -10,7 +9,7 @@ import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.
|
||||
@Patch(description = "Disables detection of modified versions.",)
|
||||
object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Do not return an error if the fingerprint is not resolved.
|
||||
// Do not throw an error if the fingerprint is not resolved.
|
||||
// This is fine because new versions of the target app do not need this patch.
|
||||
PiracyDetectionFingerprint.result?.mutableMethod?.apply {
|
||||
addInstruction(
|
||||
@@ -19,6 +18,6 @@ object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerpr
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
} ?: throw PiracyDetectionFingerprint.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package app.revanced.patches.reddit.misc.tracking.url.fingerprints
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object ShareLinkFormatterFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String;",
|
||||
parameters = listOf("Ljava/lang/String;", "Ljava/util/Map;"),
|
||||
strings = listOf("uri.getQueryParameters(name)", "uri.queryParameterNames", "newUriBuilder.build().toString()"),
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.definingClass.startsWith("Lcom/reddit/sharing/") && classDef.sourceFile == "UrlUtil.kt"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.serviceportalbund.detection.root
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.serviceportalbund.detection.root.fingerprints.RootDetectionFingerprint
|
||||
|
||||
@Patch(
|
||||
name = "Remove root detection",
|
||||
description = "Removes the check for root permissions and unlocked bootloader.",
|
||||
compatiblePackages = [CompatiblePackage("at.gv.bka.serviceportal")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object RootDetectionPatch : BytecodePatch(
|
||||
setOf(RootDetectionFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) =
|
||||
RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.serviceportalbund.detection.root.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object RootDetectionFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
accessFlags = AccessFlags.PUBLIC.value,
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
|
||||
}
|
||||
)
|
||||
@@ -40,4 +40,9 @@ internal fun <T> Element.addDefault(default: T) {
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun CharSequence.removePunctuation(): String {
|
||||
val punctuation = "\\p{P}+".toRegex()
|
||||
return this.replace(punctuation, "")
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import app.revanced.patches.shared.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.settings.preference.impl.PreferenceCategory
|
||||
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.removePunctuation
|
||||
import java.io.Closeable
|
||||
|
||||
abstract class AbstractPreferenceScreen(
|
||||
@@ -35,8 +36,8 @@ abstract class AbstractPreferenceScreen(
|
||||
return PreferenceScreen(
|
||||
key,
|
||||
StringResource("${key}_title", title),
|
||||
preferences.sortedBy { it.title.value.lowercase() } +
|
||||
categories.sortedBy { it.title.lowercase() }.map { it.transform() },
|
||||
preferences.sortedBy { it.title.value.removePunctuation().lowercase() } +
|
||||
categories.sortedBy { it.title.removePunctuation().lowercase() }.map { it.transform() },
|
||||
summary?.let { summary ->
|
||||
StringResource("${key}_summary", summary)
|
||||
}
|
||||
@@ -63,7 +64,7 @@ abstract class AbstractPreferenceScreen(
|
||||
return PreferenceCategory(
|
||||
key,
|
||||
StringResource("${key}_title", title),
|
||||
preferences.sortedBy { it.title.value.lowercase() }
|
||||
preferences.sortedBy { it.title.value.removePunctuation().lowercase() }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
@Patch(
|
||||
name = "Hide ads",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill"),
|
||||
CompatiblePackage("com.zhiliaoapp.musically")
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"])
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -16,8 +16,8 @@ import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonS
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint3
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.DownloadPathParentFingerprint
|
||||
import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
|
||||
import app.revanced.patches.tiktok.misc.settings.SettingsPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
@@ -28,8 +28,8 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
description = "Removes download restrictions and changes the default path to download to.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill"),
|
||||
CompatiblePackage("com.zhiliaoapp.musically")
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"])
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -23,8 +23,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
description = "Adds ReVanced settings to TikTok.",
|
||||
dependencies = [IntegrationsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill"),
|
||||
CompatiblePackage("com.zhiliaoapp.musically")
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"])
|
||||
]
|
||||
)
|
||||
object SettingsPatch : BytecodePatch(
|
||||
|
||||
@@ -1,33 +1,37 @@
|
||||
package app.revanced.patches.tumblr.ads
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.tumblr.ads.fingerprints.AdWaterfallFingerprint
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
|
||||
|
||||
@Patch(
|
||||
name = "Disable dashboard ads",
|
||||
description = "Disables ads in the dashboard.",
|
||||
compatiblePackages = [CompatiblePackage("com.tumblr")]
|
||||
compatiblePackages = [CompatiblePackage("com.tumblr")],
|
||||
dependencies = [TimelineFilterPatch::class]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisableDashboardAds : BytecodePatch(
|
||||
setOf(AdWaterfallFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = AdWaterfallFingerprint.result?.let {
|
||||
it.scanResult.stringsScanResult!!.matches.forEach { match ->
|
||||
// We just replace all occurrences of "client_side_ad_waterfall" with anything else
|
||||
// so the app fails to handle ads in the timeline elements array and just skips them.
|
||||
// See AdWaterfallFingerprint for more info.
|
||||
val stringRegister = it.mutableMethod.getInstruction<OneRegisterInstruction>(match.index).registerA
|
||||
it.mutableMethod.replaceInstruction(
|
||||
match.index, "const-string v$stringRegister, \"dummy\""
|
||||
)
|
||||
object DisableDashboardAds : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// The timeline object types are filtered by their name in the TimelineObjectType enum.
|
||||
// This is often different from the "object_type" returned in the api (noted in comments here)
|
||||
arrayOf(
|
||||
"CLIENT_SIDE_MEDIATION", // "client_side_ad_waterfall"
|
||||
"GEMINI_AD", // "backfill_ad"
|
||||
|
||||
// The object types below weren't actually spotted in the wild in testing, but they are valid Object types
|
||||
// and their names clearly indicate that they are ads, so we just block them anyway,
|
||||
// just in case they will be used in the future.
|
||||
"NIMBUS_AD", // "nimbus_ad"
|
||||
"CLIENT_SIDE_AD", // "client_side_ad"
|
||||
"DISPLAY_IO_INTERSCROLLER_AD", // "display_io_interscroller"
|
||||
"DISPLAY_IO_HEADLINE_VIDEO_AD", // "display_io_headline_video"
|
||||
"FACEBOOK_BIDDAABLE", // "facebook_biddable_sdk_ad"
|
||||
"GOOGLE_NATIVE" // "google_native_ad"
|
||||
).forEach {
|
||||
TimelineFilterPatch.addObjectTypeFilter(it)
|
||||
}
|
||||
} ?: throw AdWaterfallFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package app.revanced.patches.tumblr.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
// The Tumblr app sends a request to /v2/timeline/dashboard which replies with an array of elements
|
||||
// to show in the user dashboard. These element have different type ids (post, title, carousel, etc.)
|
||||
// The standard dashboard Ad has the id client_side_ad_waterfall, and this string has to be in the code
|
||||
// to handle ads and provide their appearance.
|
||||
// If we just replace this string in the tumblr code with anything else, it will fail to recognize the
|
||||
// dashboard object type and just skip it. This is a bit weird, but it shouldn't break
|
||||
// unless they change the api (unlikely) or explicitly Change the tumblr code to prevent this.
|
||||
object AdWaterfallFingerprint : MethodFingerprint(strings = listOf("client_side_ad_waterfall"))
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.tumblr.annoyances.inappupdate
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch
|
||||
|
||||
@Patch(
|
||||
name = "Disable in-app update",
|
||||
description = "Disables the in-app update check and update prompt.",
|
||||
dependencies = [OverrideFeatureFlagsPatch::class],
|
||||
compatiblePackages = [CompatiblePackage("com.tumblr")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisableInAppUpdatePatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Before checking for updates using Google Play core AppUpdateManager, the value of this feature flag is checked.
|
||||
// If this flag is false or the last update check was today and no update check is performed.
|
||||
OverrideFeatureFlagsPatch.addOverride("inAppUpdate", "false")
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,26 @@
|
||||
package app.revanced.patches.tumblr.live
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch
|
||||
import app.revanced.patches.tumblr.live.fingerprints.LiveMarqueeFingerprint
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
|
||||
|
||||
@Patch(
|
||||
name = "Disable Tumblr Live",
|
||||
description = "Disable the Tumblr Live tab button and dashboard carousel.",
|
||||
dependencies = [OverrideFeatureFlagsPatch::class],
|
||||
dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class],
|
||||
compatiblePackages = [CompatiblePackage("com.tumblr")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisableTumblrLivePatch : BytecodePatch(
|
||||
setOf(LiveMarqueeFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = LiveMarqueeFingerprint.result?.let {
|
||||
it.scanResult.stringsScanResult!!.matches.forEach { match ->
|
||||
// Replace the string constant "live_marquee"
|
||||
// with a dummy so the app doesn't recognize this type of element in the Dashboard and skips it
|
||||
it.mutableMethod.apply {
|
||||
val stringRegister = getInstruction<OneRegisterInstruction>(match.index).registerA
|
||||
replaceInstruction(match.index, "const-string v$stringRegister, \"dummy2\"")
|
||||
}
|
||||
}
|
||||
object DisableTumblrLivePatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Hide the LIVE_MARQUEE timeline element that appears in the feed
|
||||
// Called "live_marquee" in api response
|
||||
TimelineFilterPatch.addObjectTypeFilter("LIVE_MARQUEE")
|
||||
|
||||
// We hide the Tab button for Tumblr Live by forcing the feature flag to false
|
||||
// Hide the Tab button for Tumblr Live by forcing the feature flag to false
|
||||
OverrideFeatureFlagsPatch.addOverride("liveStreaming", "false")
|
||||
} ?: throw LiveMarqueeFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package app.revanced.patches.tumblr.live.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
// This works identically to the Tumblr AdWaterfallFingerprint, see comments there
|
||||
object LiveMarqueeFingerprint : MethodFingerprint(strings = listOf("live_marquee"))
|
||||
@@ -0,0 +1,68 @@
|
||||
package app.revanced.patches.tumblr.timelinefilter
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.tumblr.timelinefilter.fingerprints.PostsResponseConstructorFingerprint
|
||||
import app.revanced.patches.tumblr.timelinefilter.fingerprints.TimelineConstructorFingerprint
|
||||
import app.revanced.patches.tumblr.timelinefilter.fingerprints.TimelineFilterIntegrationFingerprint
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
|
||||
@Patch(description = "Filter timeline objects.", requiresIntegrations = true)
|
||||
object TimelineFilterPatch : BytecodePatch(
|
||||
setOf(TimelineConstructorFingerprint, TimelineFilterIntegrationFingerprint, PostsResponseConstructorFingerprint)
|
||||
) {
|
||||
/**
|
||||
* Add a filter to hide the given timeline object type.
|
||||
* The list of all Timeline object types is found in the TimelineObjectType class,
|
||||
* where they are mapped from their api name (returned by tumblr via the HTTP API) to the enum value name.
|
||||
*
|
||||
* @param typeName The enum name of the timeline object type to hide.
|
||||
*/
|
||||
@Suppress("KDocUnresolvedReference")
|
||||
internal lateinit var addObjectTypeFilter: (typeName: String) -> Unit private set
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
TimelineFilterIntegrationFingerprint.result?.let { integration ->
|
||||
val filterInsertIndex = integration.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
integration.mutableMethod.apply {
|
||||
val addInstruction = getInstruction<BuilderInstruction35c>(filterInsertIndex + 1)
|
||||
if (addInstruction.registerCount != 2) throw TimelineFilterIntegrationFingerprint.exception
|
||||
|
||||
val filterListRegister = addInstruction.registerC
|
||||
val stringRegister = addInstruction.registerD
|
||||
|
||||
// Remove "BLOCKED_OBJECT_DUMMY"
|
||||
removeInstructions(filterInsertIndex, 2)
|
||||
|
||||
addObjectTypeFilter = { typeName ->
|
||||
// blockedObjectTypes.add({typeName})
|
||||
addInstructionsWithLabels(
|
||||
filterInsertIndex, """
|
||||
const-string v$stringRegister, "$typeName"
|
||||
invoke-virtual { v$filterListRegister, v$stringRegister }, Ljava/util/HashSet;->add(Ljava/lang/Object;)Z
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: throw TimelineFilterIntegrationFingerprint.exception
|
||||
|
||||
mapOf(
|
||||
TimelineConstructorFingerprint to 1,
|
||||
PostsResponseConstructorFingerprint to 2
|
||||
).forEach { (fingerprint, timelineObjectsRegister) ->
|
||||
fingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"invoke-static {p$timelineObjectsRegister}, " +
|
||||
"Lapp/revanced/tumblr/patches/TimelineFilterPatch;->" +
|
||||
"filterTimeline(Ljava/util/List;)V"
|
||||
) ?: throw fingerprint.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.tumblr.timelinefilter.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
// This is the constructor of the PostsResponse class.
|
||||
// The same applies here as with the TimelineConstructorFingerprint.
|
||||
object PostsResponseConstructorFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.CONSTRUCTOR or AccessFlags.PUBLIC,
|
||||
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/PostsResponse;") && methodDef.parameters.size == 4 },
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.tumblr.timelinefilter.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
// This is the constructor of the Timeline class.
|
||||
// It receives the List<TimelineObject> as an argument with a @Json annotation, so this should be the first time
|
||||
// that the List<TimelineObject> is exposed in non-library code.
|
||||
object TimelineConstructorFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/Timeline;") && methodDef.parameters[0].type == "Ljava/util/List;"
|
||||
}, strings = listOf("timelineObjectsList")
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.tumblr.timelinefilter.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
// This fingerprints the Integration TimelineFilterPatch.filterTimeline method.
|
||||
// The opcode fingerprint is searching for
|
||||
// if ("BLOCKED_OBJECT_DUMMY".equals(elementType)) iterator.remove();
|
||||
object TimelineFilterIntegrationFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/TimelineFilterPatch;") },
|
||||
strings = listOf("BLOCKED_OBJECT_DUMMY"),
|
||||
opcodes = listOf(
|
||||
Opcode.CONST_STRING, // "BLOCKED_OBJECT_DUMMY"
|
||||
Opcode.INVOKE_VIRTUAL // HashSet.add(^)
|
||||
)
|
||||
)
|
||||
@@ -31,7 +31,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -15,10 +15,21 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Hide get premium",
|
||||
description = "Hides YouTube Premium signup promotions under the video player.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube", ["18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"])
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube", [
|
||||
"18.16.37",
|
||||
"18.19.35",
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
|
||||
@@ -31,15 +42,15 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
|
||||
"revanced_hide_get_premium",
|
||||
StringResource(
|
||||
"revanced_hide_get_premium_title",
|
||||
"Hide YouTube premium advertisement"
|
||||
"Hide YouTube Premium promotions"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_get_premium_summary_on",
|
||||
"YouTube Premium advertisements under video player are hidden"
|
||||
"YouTube Premium promotions under video player is hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_get_premium_summary_off",
|
||||
"YouTube Premium advertisements under video player are shown"
|
||||
"YouTube Premium promotions under video player is shown"
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -29,7 +29,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -24,7 +24,9 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -14,8 +14,8 @@ import app.revanced.util.resources.ResourceUtils.mergeStrings
|
||||
|
||||
@Patch(
|
||||
dependencies = [
|
||||
BottomControlsResourcePatch::class,
|
||||
SettingsPatch::class
|
||||
SettingsPatch::class,
|
||||
BottomControlsResourcePatch::class
|
||||
]
|
||||
)
|
||||
object CopyVideoUrlResourcePatch : ResourcePatch() {
|
||||
|
||||
@@ -24,7 +24,9 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.IsSwipingUpFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Disable fine scrubbing gesture",
|
||||
description = "Disables gesture that shows the fine scrubbing overlay when swiping up on the seekbar.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisableFineScrubbingGesturePatch : BytecodePatch(
|
||||
setOf(IsSwipingUpFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/DisableFineScrubbingGesturePatch;->" +
|
||||
"disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_disable_fine_scrubbing_gesture",
|
||||
StringResource("revanced_disable_fine_scrubbing_gesture_title", "Disable fine scrubbing gesture"),
|
||||
StringResource("revanced_disable_fine_scrubbing_gesture_summary_on", "Gesture is disabled"),
|
||||
StringResource("revanced_disable_fine_scrubbing_gesture_summary_off", "Gesture is enabled"),
|
||||
)
|
||||
)
|
||||
|
||||
IsSwipingUpFingerprint.result?.let {
|
||||
val addMovementIndex = it.scanResult.patternScanResult!!.startIndex - 1
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val addMovementInstruction = getInstruction<FiveRegisterInstruction>(addMovementIndex)
|
||||
val trackerRegister = addMovementInstruction.registerC
|
||||
val eventRegister = addMovementInstruction.registerD
|
||||
|
||||
replaceInstruction(
|
||||
addMovementIndex,
|
||||
"invoke-static {v$trackerRegister, v$eventRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR"
|
||||
)
|
||||
}
|
||||
} ?: throw IsSwipingUpFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,12 @@ import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.OnTouchEventHandlerFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
@@ -19,9 +22,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
name = "Seekbar tapping",
|
||||
description = "Enables tap-to-seek on the seekbar of the video player.",
|
||||
dependencies = [
|
||||
IntegrationsPatch::class,
|
||||
EnableSeekbarTappingResourcePatch::class
|
||||
],
|
||||
IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
@@ -31,7 +32,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -44,6 +47,15 @@ object EnableSeekbarTappingPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_seekbar_tapping",
|
||||
StringResource("revanced_seekbar_tapping_title", "Enable seekbar tapping"),
|
||||
StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
|
||||
StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
// Find the required methods to tap the seekbar.
|
||||
val seekbarTappingMethods = OnTouchEventHandlerFingerprint.result?.let {
|
||||
val patternScanResult = it.scanResult.patternScanResult!!
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
|
||||
@Patch(
|
||||
dependencies = [SettingsPatch::class]
|
||||
)
|
||||
object EnableSeekbarTappingResourcePatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_seekbar_tapping",
|
||||
StringResource("revanced_seekbar_tapping_title", "Enable seekbar tapping"),
|
||||
StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
|
||||
StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object IsSwipingUpFingerprint : MethodFingerprint(
|
||||
parameters = listOf("Landroid/view/MotionEvent;", "J"),
|
||||
opcodes = listOf(Opcode.SGET_OBJECT)
|
||||
)
|
||||
@@ -31,7 +31,9 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.youtube.layout.autocaptions
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
@@ -28,7 +29,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
],
|
||||
@@ -47,38 +50,32 @@ object AutoCaptionsPatch : BytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
val startVideoInformerMethod = StartVideoInformerFingerprint.result!!.mutableMethod
|
||||
mapOf(
|
||||
StartVideoInformerFingerprint to 0,
|
||||
SubtitleButtonControllerFingerprint to 1
|
||||
).forEach { (fingerprint, enabled) ->
|
||||
fingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x$enabled
|
||||
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
"""
|
||||
) ?: throw fingerprint.exception
|
||||
}
|
||||
|
||||
startVideoInformerMethod.addInstructions(
|
||||
0, """
|
||||
const/4 v0, 0x0
|
||||
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
"""
|
||||
)
|
||||
|
||||
val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod
|
||||
|
||||
subtitleButtonControllerMethod.addInstructions(
|
||||
0, """
|
||||
const/4 v0, 0x1
|
||||
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
"""
|
||||
)
|
||||
|
||||
val subtitleTrackMethod = SubtitleTrackFingerprint.result!!.mutableMethod
|
||||
|
||||
subtitleTrackMethod.addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :auto_captions_enabled
|
||||
sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
if-nez v0, :auto_captions_enabled
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
:auto_captions_enabled
|
||||
nop
|
||||
"""
|
||||
SubtitleTrackFingerprint.result?.mutableMethod?.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :auto_captions_enabled
|
||||
sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
if-nez v0, :auto_captions_enabled
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
:auto_captions_enabled
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,11 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object StartVideoInformerFingerprint : MethodFingerprint(
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L", "L", "L"), listOf(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQ,
|
||||
Opcode.GOTO,
|
||||
)
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
strings = listOf("pc")
|
||||
)
|
||||
@@ -12,7 +12,7 @@ import java.nio.file.Files
|
||||
|
||||
@Patch(
|
||||
name = "Custom branding",
|
||||
description = "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
|
||||
description = "Changes the app icon and name to your choice (defaults to YouTube ReVanced and the ReVanced logo).",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube")
|
||||
],
|
||||
@@ -20,19 +20,45 @@ import java.nio.file.Files
|
||||
)
|
||||
@Suppress("unused")
|
||||
object CustomBrandingPatch : ResourcePatch() {
|
||||
private val iconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_background_color_108",
|
||||
"adaptiveproduct_youtube_foreground_color_108",
|
||||
"ic_launcher",
|
||||
"ic_launcher_round"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val mipmapDirectories = arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).map { "mipmap-$it" }
|
||||
|
||||
private var appName by stringPatchOption(
|
||||
key = "appName",
|
||||
default = "YouTube ReVanced",
|
||||
title = "Application Name",
|
||||
description = "The name of the application it will show on your home screen.",
|
||||
title = "App name",
|
||||
description = "The name of the app.",
|
||||
required = true
|
||||
)
|
||||
|
||||
private var iconPath by stringPatchOption(
|
||||
key = "iconPath",
|
||||
default = null,
|
||||
title = "App Icon Path",
|
||||
description = "A path containing mipmap resource folders with icons."
|
||||
title = "App icon path",
|
||||
description = """
|
||||
The path to a folder containing the following folders:
|
||||
|
||||
${mipmapDirectories.joinToString("\n") { "- $it" }}
|
||||
|
||||
Each of these folders has to have the following files:
|
||||
|
||||
${iconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||
"""
|
||||
.split("\n")
|
||||
.joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line.
|
||||
.trimIndent(), // Remove the leading newline.
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
@@ -55,24 +81,14 @@ object CustomBrandingPatch : ResourcePatch() {
|
||||
} ?: resourceGroups.forEach { context.copyResources("branding", it) }
|
||||
}
|
||||
|
||||
val iconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_background_color_108",
|
||||
"adaptiveproduct_youtube_foreground_color_108",
|
||||
"ic_launcher",
|
||||
"ic_launcher_round"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
fun createGroup(directory: String) = ResourceUtils.ResourceGroup(
|
||||
directory, *iconResourceFileNames
|
||||
)
|
||||
|
||||
// change the app icon
|
||||
arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi")
|
||||
.map { "mipmap-$it" }
|
||||
.map(::createGroup)
|
||||
.let(::copyResources)
|
||||
// Change the app icon.
|
||||
mipmapDirectories.map(::createGroup).let(::copyResources)
|
||||
|
||||
// change the name of the app
|
||||
// Change the app name.
|
||||
val manifest = context["AndroidManifest.xml"]
|
||||
manifest.writeText(
|
||||
manifest.readText()
|
||||
|
||||
@@ -5,39 +5,57 @@ import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.exists
|
||||
import app.revanced.patcher.patch.options.types.BooleanPatchOption.Companion.booleanPatchOption
|
||||
import kotlin.io.path.copyTo
|
||||
|
||||
@Patch(
|
||||
name = "Premium heading",
|
||||
description = "Shows premium branding on the home screen.",
|
||||
description = "Show or hide the premium heading.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object PremiumHeadingPatch : ResourcePatch() {
|
||||
private const val DEFAULT_HEADING_RES = "yt_wordmark_header"
|
||||
private const val PREMIUM_HEADING_RES = "yt_premium_wordmark_header"
|
||||
|
||||
private val usePremiumHeading by booleanPatchOption(
|
||||
key = "usePremiumHeading",
|
||||
default = true,
|
||||
title = "Use premium heading",
|
||||
description = "Whether to use the premium heading.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
val resDirectory = context["res"]
|
||||
if (!resDirectory.isDirectory) throw PatchException("The res folder can not be found.")
|
||||
|
||||
val (original, replacement) = "yt_premium_wordmark_header" to "yt_wordmark_header"
|
||||
val modes = arrayOf("light", "dark")
|
||||
val (original, replacement) = if (usePremiumHeading!!)
|
||||
PREMIUM_HEADING_RES to DEFAULT_HEADING_RES
|
||||
else
|
||||
DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
|
||||
|
||||
arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi").forEach { size ->
|
||||
val headingDirectory = resDirectory.resolve("drawable-$size")
|
||||
modes.forEach { mode ->
|
||||
val fromPath = headingDirectory.resolve("${original}_$mode.png").toPath()
|
||||
val toPath = headingDirectory.resolve("${replacement}_$mode.png").toPath()
|
||||
val variants = arrayOf("light", "dark")
|
||||
|
||||
if (!fromPath.exists())
|
||||
throw PatchException("The file $fromPath does not exist in the resources. Therefore, this patch can not succeed.")
|
||||
Files.copy(
|
||||
fromPath,
|
||||
toPath,
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).mapNotNull { dpi ->
|
||||
resDirectory.resolve("drawable-$dpi").takeIf { it.exists() }?.toPath()
|
||||
}.also {
|
||||
if (it.isEmpty())
|
||||
throw PatchException("The drawable folder can not be found. Therefore, the patch can not be applied.")
|
||||
}.forEach { path ->
|
||||
|
||||
variants.forEach { mode ->
|
||||
val fromPath = path.resolve("${original}_$mode.png")
|
||||
val toPath = path.resolve("${replacement}_$mode.png")
|
||||
|
||||
fromPath.copyTo(toPath, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -37,7 +37,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -28,7 +28,9 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -36,7 +36,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -32,7 +32,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -27,7 +27,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -27,7 +27,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -26,7 +26,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -27,7 +27,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -30,7 +30,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -7,8 +7,6 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
object LayoutIconFingerprint : LiteralValueFingerprint(
|
||||
returnType = "Landroid/view/View;",
|
||||
opcodes = listOf(
|
||||
Opcode.CONST_4,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
|
||||
@@ -27,7 +27,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -23,7 +23,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -2,9 +2,12 @@ package app.revanced.patches.youtube.layout.hide.general
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
@@ -14,6 +17,8 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
|
||||
@@ -27,11 +32,19 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class
|
||||
],
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.youtube", ["18.32.39"])]
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube", [
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideLayoutComponentsPatch : BytecodePatch(
|
||||
setOf(ParseElementFromBufferFingerprint)
|
||||
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
|
||||
@@ -44,6 +57,48 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
StringResource("revanced_hide_gray_separator_summary_on", "Gray separators are hidden"),
|
||||
StringResource("revanced_hide_gray_separator_summary_off", "Gray separators are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_join_membership_button",
|
||||
StringResource("revanced_hide_join_membership_button_title", "Hide \\\'Join\\\' button"),
|
||||
StringResource("revanced_hide_join_membership_button_summary_on", "Button is hidden"),
|
||||
StringResource("revanced_hide_join_membership_button_summary_off", "Button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_watermark_title",
|
||||
StringResource(
|
||||
"revanced_hide_channel_watermark_title",
|
||||
"Hide channel watermark in video player"
|
||||
),
|
||||
StringResource("revanced_hide_channel_watermark_title_summary_on", "Watermark is hidden"),
|
||||
StringResource("revanced_hide_channel_watermark_title_summary_off", "Watermark is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_notify_me_button",
|
||||
StringResource("revanced_hide_notify_me_button_title", "Hide \\\'Notify me\\\' button"),
|
||||
StringResource("revanced_hide_notify_me_button_summary_on", "Button is hidden"),
|
||||
StringResource("revanced_hide_notify_me_button_summary_off", "Button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_timed_reactions",
|
||||
StringResource("revanced_hide_timed_reactions_title", "Hide timed reactions"),
|
||||
StringResource("revanced_hide_timed_reactions_summary_on", "Timed reactions are hidden"),
|
||||
StringResource("revanced_hide_timed_reactions_summary_off", "Timed reactions are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_search_result_shelf_header",
|
||||
StringResource(
|
||||
"revanced_hide_search_result_shelf_header_title",
|
||||
"Hide search result shelf header"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_search_result_shelf_header_summary_on",
|
||||
"Shelf header is hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_search_result_shelf_header_summary_off",
|
||||
"Shelf header is shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_guidelines",
|
||||
StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
|
||||
@@ -274,5 +329,24 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
} ?: throw ParseElementFromBufferFingerprint.exception
|
||||
|
||||
// endregion
|
||||
|
||||
// region Watermark (legacy code for old versions of YouTube)
|
||||
|
||||
ShowWatermarkFingerprint.also {
|
||||
it.resolve(context, PlayerOverlayFingerprint.result?.classDef ?: throw PlayerOverlayFingerprint.exception)
|
||||
}.result?.mutableMethod?.apply {
|
||||
val index = implementation!!.instructions.size - 5
|
||||
|
||||
removeInstruction(index)
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
invoke-static {}, $FILTER_CLASS_DESCRIPTOR->showWatermark()Z
|
||||
move-result p2
|
||||
"""
|
||||
)
|
||||
} ?: throw ShowWatermarkFingerprint.exception
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package app.revanced.patches.youtube.layout.hide.watermark.fingerprints
|
||||
package app.revanced.patches.youtube.layout.hide.general.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object HideWatermarkParentFingerprint : MethodFingerprint (
|
||||
object PlayerOverlayFingerprint : MethodFingerprint (
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, strings = listOf("player_overlay_in_video_programming")
|
||||
)
|
||||
@@ -1,9 +1,9 @@
|
||||
package app.revanced.patches.youtube.layout.hide.watermark.fingerprints
|
||||
package app.revanced.patches.youtube.layout.hide.general.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object HideWatermarkFingerprint : MethodFingerprint (
|
||||
object ShowWatermarkFingerprint : MethodFingerprint (
|
||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L")
|
||||
)
|
||||
@@ -13,6 +13,7 @@ import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.Infocards
|
||||
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsIncognitoParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsMethodCallFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
@@ -22,6 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
description = "Hides info cards in videos.",
|
||||
dependencies = [
|
||||
IntegrationsPatch::class,
|
||||
LithoFilterPatch::class,
|
||||
HideInfocardsResourcePatch::class
|
||||
],
|
||||
compatiblePackages = [
|
||||
@@ -33,7 +35,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -45,6 +49,9 @@ object HideInfoCardsPatch : BytecodePatch(
|
||||
InfocardsMethodCallFingerprint,
|
||||
)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/HideInfoCardsFilterPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
InfocardsIncognitoFingerprint.also {
|
||||
it.resolve(context, InfocardsIncognitoParentFingerprint.result!!.classDef)
|
||||
@@ -79,5 +86,8 @@ object HideInfoCardsPatch : BytecodePatch(
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Info cards can also appear as litho components.
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import app.revanced.patches.youtube.layout.hide.loadmorebutton.fingerprints.Hide
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Hide load more button",
|
||||
name = "Hide \'Load more\' button",
|
||||
description = "Hides the button under videos that loads similar videos.",
|
||||
dependencies = [HideLoadMoreButtonResourcePatch::class],
|
||||
compatiblePackages = [
|
||||
@@ -23,7 +23,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -21,9 +21,9 @@ object HideLoadMoreButtonResourcePatch : ResourcePatch() {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_load_more_button",
|
||||
StringResource("revanced_hide_load_more_button_title", "Hide Load More button"),
|
||||
StringResource("revanced_hide_load_more_button_summary_on", "Load More button is hidden"),
|
||||
StringResource("revanced_hide_load_more_button_summary_off", "Load More button is shown")
|
||||
StringResource("revanced_hide_load_more_button_title", "Hide \\\'Load More\\\' button"),
|
||||
StringResource("revanced_hide_load_more_button_summary_on", "Button is hidden"),
|
||||
StringResource("revanced_hide_load_more_button_summary_off", "Button is shown")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -24,7 +24,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
])
|
||||
]
|
||||
)
|
||||
|
||||
@@ -32,7 +32,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -36,7 +36,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -54,8 +56,6 @@ object HideShortsComponentsPatch : BytecodePatch(
|
||||
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// region Hide the Shorts shelf.
|
||||
|
||||
ReelConstructorFingerprint.result?.let {
|
||||
@@ -74,13 +74,20 @@ object HideShortsComponentsPatch : BytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hide the Shorts buttons.
|
||||
// region Hide the Shorts buttons in older versions of YouTube.
|
||||
|
||||
// Some Shorts buttons are views, hide them by setting their visibility to GONE.
|
||||
CreateShortsButtonsFingerprint.result?.let {
|
||||
ShortsButtons.values().forEach { button -> button.injectHideCall(it.mutableMethod) }
|
||||
ShortsButtons.entries.forEach { button -> button.injectHideCall(it.mutableMethod) }
|
||||
} ?: throw CreateShortsButtonsFingerprint.exception
|
||||
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hide the Shorts buttons in newer versions of YouTube.
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hide the navigation bar.
|
||||
@@ -92,10 +99,10 @@ object HideShortsComponentsPatch : BytecodePatch(
|
||||
|
||||
SetPivotBarVisibilityFingerprint.result!!.let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val checkCastIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||
val insertIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
insertIndex,
|
||||
"sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->pivotBar:" +
|
||||
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
|
||||
)
|
||||
@@ -116,7 +123,7 @@ object HideShortsComponentsPatch : BytecodePatch(
|
||||
// Required to prevent a black bar from appearing at the bottom of the screen.
|
||||
BottomNavigationBarFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val moveResultIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val moveResultIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
|
||||
val insertIndex = moveResultIndex + 1
|
||||
|
||||
|
||||
@@ -38,6 +38,12 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
|
||||
StringResource("revanced_hide_shorts_subscribe_button_on", "Subscribe button is hidden"),
|
||||
StringResource("revanced_hide_shorts_subscribe_button_off", "Subscribe button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_shorts_subscribe_button_paused",
|
||||
StringResource("revanced_hide_shorts_subscribe_button_paused_title", "Hide subscribe button when paused"),
|
||||
StringResource("revanced_hide_shorts_subscribe_button_paused_on", "Subscribe button is hidden"),
|
||||
StringResource("revanced_hide_shorts_subscribe_button_paused_off", "Subscribe button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_shorts_thanks_button",
|
||||
StringResource("revanced_hide_shorts_thanks_button_title", "Hide thanks button"),
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object BottomNavigationBarFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/view/View;", "Landroid/os/Bundle;"),
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT, // Refers to bottom navigation bar
|
||||
Opcode.CONST, // R.id.app_engagement_panel_wrapper
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
),
|
||||
strings = listOf(
|
||||
"navigation_endpoint_interaction_logging_extension",
|
||||
"reel_watch_fragment_watch_while",
|
||||
"ReelWatchPaneFragmentViewModelKey"
|
||||
),
|
||||
)
|
||||
@@ -1,19 +1,16 @@
|
||||
package app.revanced.patches.youtube.layout.hide.shorts.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object SetPivotBarVisibilityFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
parameters = listOf("Z"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.RETURN_VOID,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.IF_EQZ
|
||||
)
|
||||
)
|
||||
@@ -24,7 +24,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.hide.watermark
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.layout.hide.watermark.fingerprints.HideWatermarkFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.watermark.fingerprints.HideWatermarkParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
|
||||
@Patch(
|
||||
name = "Hide watermark",
|
||||
description = "Hides creator's watermarks on videos.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.16.37",
|
||||
"18.19.35",
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideWatermarkPatch : BytecodePatch(
|
||||
setOf(HideWatermarkParentFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_video_watermark",
|
||||
StringResource("revanced_hide_video_watermark_title", "Hide creator watermark on videos"),
|
||||
StringResource("revanced_hide_video_watermark_summary_on", "Watermark is hidden"),
|
||||
StringResource("revanced_hide_video_watermark_summary_off", "Watermark is shown")
|
||||
)
|
||||
)
|
||||
|
||||
HideWatermarkFingerprint.resolve(context, HideWatermarkParentFingerprint.result!!.classDef)
|
||||
val result = HideWatermarkFingerprint.result
|
||||
?: throw PatchException("Required parent method could not be found.")
|
||||
|
||||
val method = result.mutableMethod
|
||||
val line = method.implementation!!.instructions.size - 5
|
||||
|
||||
method.removeInstruction(line)
|
||||
method.addInstructions(
|
||||
line,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/BrandingWaterMarkPatch;->isBrandingWatermarkShown()Z
|
||||
move-result p2
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -18,7 +18,9 @@ import org.w3c.dom.Element
|
||||
"18.20.39",
|
||||
"18.23.35",
|
||||
"18.29.38",
|
||||
"18.32.39"
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44"
|
||||
]
|
||||
)
|
||||
],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.player.overlay
|
||||
|
||||
import app.revanced.extensions.exception
|
||||
import app.revanced.extensions.indexOfFirstConstantInstructionValue
|
||||
import app.revanced.extensions.indexOfFirstWideLiteralInstructionValue
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
@@ -27,7 +27,7 @@ object CustomPlayerOverlayOpacityPatch : BytecodePatch(setOf(CreatePlayerOvervie
|
||||
CreatePlayerOverviewFingerprint.result?.let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val viewRegisterIndex =
|
||||
indexOfFirstConstantInstructionValue(CustomPlayerOverlayOpacityResourcePatch.scrimOverlayId) + 3
|
||||
indexOfFirstWideLiteralInstructionValue(CustomPlayerOverlayOpacityResourcePatch.scrimOverlayId) + 3
|
||||
val viewRegister =
|
||||
getInstruction<OneRegisterInstruction>(viewRegisterIndex).registerA
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.youtube.layout.player.overlay.fingerprints
|
||||
|
||||
import app.revanced.extensions.containsConstantInstructionValue
|
||||
import app.revanced.extensions.containsWideLiteralInstructionValue
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.player.overlay.CustomPlayerOverlayOpacityResourcePatch
|
||||
@@ -17,6 +17,6 @@ object CreatePlayerOverviewFingerprint : MethodFingerprint(
|
||||
Opcode.CHECK_CAST
|
||||
),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.containsConstantInstructionValue(CustomPlayerOverlayOpacityResourcePatch.scrimOverlayId)
|
||||
methodDef.containsWideLiteralInstructionValue(CustomPlayerOverlayOpacityResourcePatch.scrimOverlayId)
|
||||
}
|
||||
)
|
||||
@@ -14,6 +14,7 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
@@ -26,12 +27,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
description = "Shows the dislike count of videos using the Return YouTube Dislike API.",
|
||||
dependencies = [
|
||||
IntegrationsPatch::class,
|
||||
LithoFilterPatch::class,
|
||||
VideoIdPatch::class,
|
||||
ReturnYouTubeDislikeResourcePatch::class,
|
||||
PlayerTypeHookPatch::class,
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.google.android.youtube", ["18.32.39"])
|
||||
CompatiblePackage("com.google.android.youtube", ["18.37.36", "18.38.44"])
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
@@ -48,10 +50,16 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;"
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
|
||||
|
||||
VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
||||
VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
||||
|
||||
// Hook the player response video id, to start loading RYD sooner in the background.
|
||||
VideoIdPatch.hookPlayerResponseVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->preloadVideoId(Ljava/lang/String;)V")
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -89,49 +97,40 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
throw TextComponentAtomicReferenceFingerprint.exception
|
||||
}?.let { textComponentContextFingerprintResult ->
|
||||
val conversionContextIndex = textComponentContextFingerprintResult
|
||||
.scanResult.patternScanResult!!.startIndex
|
||||
.scanResult.patternScanResult!!.endIndex
|
||||
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
|
||||
.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
val insertIndex = atomicReferenceStartIndex + 6
|
||||
val insertIndex = atomicReferenceStartIndex + 9
|
||||
|
||||
textComponentContextFingerprintResult.mutableMethod.apply {
|
||||
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
|
||||
// Get the conversion context obfuscated field name
|
||||
val conversionContextFieldReference =
|
||||
getInstruction<ReferenceInstruction>(conversionContextIndex).reference
|
||||
|
||||
// Reuse the free register to make room for the atomic reference register.
|
||||
// Free register to hold the conversion context
|
||||
val freeRegister =
|
||||
getInstruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB
|
||||
|
||||
val atomicReferenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 1).registerC
|
||||
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 6).registerC
|
||||
|
||||
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex - 1)
|
||||
// Instruction that is replaced, and also has the CharacterSequence register.
|
||||
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
|
||||
val charSequenceSourceRegister = moveCharSequenceInstruction.registerB
|
||||
val charSequenceTargetRegister = moveCharSequenceInstruction.registerA
|
||||
|
||||
// In order to preserve the atomic reference register, because it is overwritten,
|
||||
// use another free register to store it.
|
||||
replaceInstruction(
|
||||
atomicReferenceStartIndex + 2,
|
||||
"move-result-object v$freeRegister"
|
||||
)
|
||||
replaceInstruction(
|
||||
atomicReferenceStartIndex + 3,
|
||||
"move-object v$charSequenceSourceRegister, v$freeRegister"
|
||||
)
|
||||
|
||||
// Move the current instance to the free register, and get the conversion context from it.
|
||||
replaceInstruction(insertIndex - 1, "move-object/from16 v$freeRegister, p0")
|
||||
// Must replace the instruction to preserve the control flow label.
|
||||
replaceInstruction(insertIndex, "move-object/from16 v$freeRegister, p0")
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
insertIndex + 1,
|
||||
"""
|
||||
# Move context to free register
|
||||
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
|
||||
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
|
||||
invoke-static {v$freeRegister, v$atomicReferenceRegister, v$charSequenceSourceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$freeRegister
|
||||
# Replace the original char sequence with the modified one.
|
||||
# Replace the original instruction
|
||||
move-object v${charSequenceTargetRegister}, v${freeRegister}
|
||||
"""
|
||||
)
|
||||
@@ -140,7 +139,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hook for Short videos.
|
||||
// region Hook for non litho Short videos.
|
||||
|
||||
ShortsTextViewFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
@@ -150,7 +149,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference
|
||||
|
||||
val textViewFieldReference = // Like/Dislike button TextView field
|
||||
getInstruction<ReferenceInstruction>(patternResult.endIndex - 2).reference
|
||||
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
|
||||
|
||||
// Check if the hooked TextView object is that of the dislike button.
|
||||
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
|
||||
@@ -180,6 +179,16 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hook for litho Shorts
|
||||
|
||||
// Filter that parses the video id from the UI
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// Player response video id is needed to search for the video ids in Shorts litho components.
|
||||
VideoIdPatch.hookPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;)V")
|
||||
|
||||
// endregion
|
||||
|
||||
// region Hook old UI layout dislikes, for the older app spoofs used with spoof-app-version.
|
||||
|
||||
DislikesOldLayoutTextViewFingerprint.result?.let {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
object ShortsTextViewFingerprint : MethodFingerprint(
|
||||
// 18.29.38 method is public final visibility, but in 18.23.35 and older it's protected final.
|
||||
// If 18.23.35 is dropped then accessFlags should be specified here.
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "V",
|
||||
parameters = listOf("L", "L"),
|
||||
opcodes = listOf(
|
||||
@@ -27,7 +27,6 @@ object ShortsTextViewFingerprint : MethodFingerprint(
|
||||
Opcode.IF_EQ,
|
||||
Opcode.RETURN_VOID,
|
||||
Opcode.IGET_OBJECT, // TextView field
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.IGET_BOOLEAN, // boolean field
|
||||
)
|
||||
)
|
||||
@@ -13,13 +13,17 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_OBJECT, // Register A and B is context, use B as context, reuse A as free register
|
||||
Opcode.MOVE_OBJECT, // Register B is free register
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.MOVE_OBJECT_FROM16,
|
||||
Opcode.INVOKE_VIRTUAL, // Register C is atomic reference
|
||||
Opcode.MOVE_RESULT_OBJECT, // Register A is char sequence
|
||||
Opcode.MOVE_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.MOVE_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE, // Insert hook here
|
||||
Opcode.MOVE_OBJECT, // Replace this instruction with patch code
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user