Compare commits

...

146 Commits

Author SHA1 Message Date
semantic-release-bot
3d3197701c chore(release): 4.7.0-dev.3 [skip ci]
# [4.7.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.2...v4.7.0-dev.3) (2024-04-09)

### Bug Fixes

* **Tumblr - Fix old versions:** Improve reliability by removing remnances of Tumblr Live  ([#2988](https://github.com/ReVanced/revanced-patches/issues/2988)) ([1ac6127](1ac612798b))
2024-04-09 17:40:30 +00:00
Temm
1ac612798b fix(Tumblr - Fix old versions): Improve reliability by removing remnances of Tumblr Live (#2988)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-04-09 19:38:11 +02:00
LisoUseInAIKyrios
e1ed1aee69 chore(YouTube): Fix typos, simplify some strings for translating 2024-04-07 23:56:09 +04:00
oSumAtrIX
795ccac990 chore: Fix spelling mistake 2024-04-07 17:36:01 +02:00
semantic-release-bot
da55410a2b chore(release): 4.7.0-dev.2 [skip ci]
# [4.7.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.1...v4.7.0-dev.2) (2024-04-06)

### Features

* **Strava - Unlock subscription:** Remove compatible version constraint ([e798341](e7983411a7))
2024-04-06 18:53:36 +00:00
oSumAtrIX
e7983411a7 feat(Strava - Unlock subscription): Remove compatible version constraint 2024-04-06 20:51:37 +02:00
semantic-release-bot
182748cb16 chore(release): 4.7.0-dev.1 [skip ci]
# [4.7.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.3...v4.7.0-dev.1) (2024-04-06)

### Features

* **YouTube - Hide layout components:** Add option to hide horizontal shelves ([#2951](https://github.com/ReVanced/revanced-patches/issues/2951)) ([122f042](122f04219f))
2024-04-06 18:51:17 +00:00
nullptr
122f04219f feat(YouTube - Hide layout components): Add option to hide horizontal shelves (#2951)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2024-04-06 20:49:03 +02:00
semantic-release-bot
80763bcef6 chore(release): 4.6.1-dev.3 [skip ci]
## [4.6.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.2...v4.6.1-dev.3) (2024-04-06)

### Bug Fixes

* **YouTube - GmsCore support:** Prompt to disable battery optimizations, if not done already ([#2958](https://github.com/ReVanced/revanced-patches/issues/2958)) ([b80bb89](b80bb8969c))
2024-04-06 18:48:03 +00:00
LisoUseInAIKyrios
b80bb8969c fix(YouTube - GmsCore support): Prompt to disable battery optimizations, if not done already (#2958)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-04-06 20:45:59 +02:00
oSumAtrIX
2a86a670f0 ci: Only push strings once a month 2024-04-05 01:16:20 +02:00
LisoUseInAIKyrios
dba37b834d chore: Add comments for translations 2024-04-05 01:15:06 +04:00
semantic-release-bot
3ad4eb8dbc chore(release): 4.6.1-dev.2 [skip ci]
## [4.6.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.1...v4.6.1-dev.2) (2024-04-04)

### Bug Fixes

* **YouTube - Hide load more button:** Include patch with `Hide layout components`, and hide button only in search feed  ([#2959](https://github.com/ReVanced/revanced-patches/issues/2959)) ([0e88306](0e88306f3f))
2024-04-04 21:11:39 +00:00
nullptr
0e88306f3f fix(YouTube - Hide load more button): Include patch with Hide layout components, and hide button only in search feed (#2959) 2024-04-05 01:09:28 +04:00
LisoUseInAIKyrios
87cb63f2e7 chore: Fix typo 2024-04-04 14:25:36 +04:00
LisoUseInAIKyrios
0fead38701 chore: Add comments for translations 2024-04-04 14:19:03 +04:00
semantic-release-bot
19a31019c2 chore(release): 4.6.1-dev.1 [skip ci]
## [4.6.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.6.0...v4.6.1-dev.1) (2024-04-04)

### Bug Fixes

* **YouTube - Player flyout menu:** Add hide Lock screen menu ([#2985](https://github.com/ReVanced/revanced-patches/issues/2985)) ([6175841](61758414c2))
2024-04-04 06:49:26 +00:00
LisoUseInAIKyrios
61758414c2 fix(YouTube - Player flyout menu): Add hide Lock screen menu (#2985) 2024-04-04 10:47:09 +04:00
LisoUseInAIKyrios
b4ee8b6da4 chore: Remove unused string 2024-04-02 16:40:19 +04:00
semantic-release-bot
e86e3d88cf chore(release): 4.6.0 [skip ci]
# [4.6.0](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.6.0) (2024-04-02)

### Bug Fixes

* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([fef5f35](fef5f35788))
* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([1a53a93](1a53a93cd2))

### Features

* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2f28e95](2f28e95252))
2024-04-02 00:25:07 +00:00
oSumAtrIX
8cf444962c chore: Merge branch dev to main (#2957) 2024-04-02 02:23:06 +02:00
Ushie
48bf632dbe ci: Push strings to Crowdin on string changes (#2979)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-04-02 01:34:22 +02:00
Ushie
03e91d4251 ci: Don't sync Crowdin every hour (#2967) 2024-04-01 17:17:16 +04:00
semantic-release-bot
8caf70719e chore(release): 4.6.0-dev.1 [skip ci]
# [4.6.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.2...v4.6.0-dev.1) (2024-03-31)

### Features

* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2f28e95](2f28e95252))
2024-03-31 00:49:07 +00:00
Temm
2f28e95252 feat(Tumblr): Add Fix old versions patch (#2954)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-31 01:46:50 +01:00
semantic-release-bot
d819e7bbe9 chore(release): 4.5.1-dev.2 [skip ci]
## [4.5.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.1...v4.5.1-dev.2) (2024-03-30)

### Bug Fixes

* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([fef5f35](fef5f35788))
2024-03-30 22:54:45 +00:00
Michał Pisarski
fef5f35788 fix(Mi Fitness - Fix login): Patch correct register (#2942)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-30 23:52:45 +01:00
LisoUseInAIKyrios
80034bc70a chore: Add string format indexes, to allow more flexible translations (#2956) 2024-03-31 02:12:33 +04:00
semantic-release-bot
c40911a815 chore(release): 4.5.1-dev.1 [skip ci]
## [4.5.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.5.1-dev.1) (2024-03-30)

### Bug Fixes

* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([1a53a93](1a53a93cd2))
2024-03-30 22:10:49 +00:00
Temm
1a53a93cd2 fix(Tumblr): Restore compatibility with latest versions (#2955) 2024-03-30 23:08:34 +01:00
semantic-release-bot
2e68c65c9f chore(release): 4.5.0 [skip ci]
# [4.5.0](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0) (2024-03-30)

### Features

* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([a272962](a27296223f))
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([9b3c060](9b3c060acb))
2024-03-30 19:42:19 +00:00
oSumAtrIX
6f8d92827b chore: Merge branch dev to main (#2943) 2024-03-30 20:40:10 +01:00
semantic-release-bot
ab2260acfd chore(release): 4.5.0-dev.2 [skip ci]
# [4.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.0-dev.1...v4.5.0-dev.2) (2024-03-30)

### Features

* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([9b3c060](9b3c060acb))
2024-03-30 18:54:26 +00:00
oSumAtrIX
9b3c060acb feat(YouTube - GmsCore): Require ignoring battery optimizations (#2952) 2024-03-30 19:52:22 +01:00
LisoUseInAIKyrios
bbc4a6bfa0 chore: fix typo 2024-03-30 20:33:28 +04:00
Ushie
4df9b9d5b1 ci: Add workflow to sync Crowdin translations (#2953) 2024-03-30 03:15:07 +01:00
semantic-release-bot
eebf72f476 chore(release): 4.5.0-dev.1 [skip ci]
# [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29)

### Features

* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([a272962](a27296223f))
2024-03-29 09:31:55 +00:00
LisoUseInAIKyrios
a27296223f feat(YouTube - Alternative thumbnails): Selectively enable for home / subscription / search (#2926)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-29 13:30:00 +04:00
LisoUseInAIKyrios
77a9a56e2d Merge remote-tracking branch 'upstream/dev' into upstream-dev 2024-03-28 17:15:53 +04:00
LisoUseInAIKyrios
3df3441385 chore: fix typo 2024-03-28 17:15:40 +04:00
semantic-release-bot
86def3efea chore(release): 4.4.0 [skip ci]
# [4.4.0](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0) (2024-03-27)

### Bug Fixes

* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([e6a468c](e6a468cf7a))
* **YouTube - Client spoof:** Spoof all user agents ([d18719c](d18719c59c))
* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([5cca421](5cca42121a))
* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([2fcd786](2fcd786cc7))
* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([7f852e8](7f852e8f32))
* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([0bd0c82](0bd0c827a4))
* **YouTube:** Move setting to correct screen ([46ff5b8](46ff5b8b92))

### Features

* **Instagram - Hide timeline ads:** Make compatible with latest versions ([8306f70](8306f70fd1))
* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([2679fad](2679fad25f))
* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([08c4468](08c4468ff1))
* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([bc8bc8c](bc8bc8c798))
* **YouTube - External downloader:** Add ability to use in-app download button ([7f8b7c0](7f8b7c08b2))
* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([cb4b651](cb4b6514db))
* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([069f26d](069f26de20))
* **YouTube - Hide Shorts components:** Hide sound metadata label ([a9f418a](a9f418a19f))
* **YouTube - Hide Shorts components:** Hide title and full video link label ([5b0360c](5b0360c067))
* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([5b7b134](5b7b134d73))
* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([32139f1](32139f151b))
* **YouTube Vanced:** Remove `Hide ads` patch ([bcce7be](bcce7bee9a))
* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([122ef68](122ef68a4b))
2024-03-27 18:37:58 +00:00
oSumAtrIX
bc9a612824 chore: Merge branch dev to main (#2804) 2024-03-27 19:35:49 +01:00
semantic-release-bot
f378ddc6d5 chore(release): 4.4.0-dev.15 [skip ci]
# [4.4.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.14...v4.4.0-dev.15) (2024-03-27)

### Bug Fixes

* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([7f852e8](7f852e8f32))

### Features

* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([5b7b134](5b7b134d73))
2024-03-27 18:18:21 +00:00
oSumAtrIX
7f852e8f32 fix(YouTube Music): Fix compatibility with latest versions (#2924) 2024-03-27 19:08:18 +01:00
LisoUseInAIKyrios
5b7b134d73 feat(YouTube - Hide Shorts components): Selectively hide Shorts for home / subscription / search (#2925) 2024-03-27 15:02:34 +01:00
oSumAtrIX
df9361ea2b refactor: Move integrations to correct package 2024-03-27 15:02:34 +01:00
LisoUseInAIKyrios
8c226c4bdc chore: fix typo 2024-03-27 13:09:23 +04:00
semantic-release-bot
c87f8a376d chore(release): 4.4.0-dev.14 [skip ci]
# [4.4.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.13...v4.4.0-dev.14) (2024-03-27)

### Features

* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([cb4b651](cb4b6514db))
2024-03-27 07:28:55 +00:00
LisoUseInAIKyrios
cb4b6514db feat(YouTube - Hide layout components): Filter home/search results by keywords (#2853)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-27 11:26:40 +04:00
semantic-release-bot
5a172c9deb chore(release): 4.4.0-dev.13 [skip ci]
# [4.4.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.12...v4.4.0-dev.13) (2024-03-26)

### Bug Fixes

* **YouTube:** Move setting to correct screen ([46ff5b8](46ff5b8b92))

### Features

* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([069f26d](069f26de20))
* **YouTube - Hide Shorts components:** Hide sound metadata label ([a9f418a](a9f418a19f))
* **YouTube - Hide Shorts components:** Hide title and full video link label ([5b0360c](5b0360c067))
2024-03-26 01:20:59 +00:00
oSumAtrIX
a9f418a19f feat(YouTube - Hide Shorts components): Hide sound metadata label 2024-03-26 02:18:47 +01:00
oSumAtrIX
5b0360c067 feat(YouTube - Hide Shorts components): Hide title and full video link label 2024-03-26 02:18:46 +01:00
oSumAtrIX
069f26de20 feat(YouTube - Hide Shorts components): Hide like and dislike buttons 2024-03-26 02:18:23 +01:00
oSumAtrIX
46ff5b8b92 fix(YouTube): Move setting to correct screen 2024-03-26 01:48:57 +01:00
semantic-release-bot
69721509bf chore(release): 4.4.0-dev.12 [skip ci]
# [4.4.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.11...v4.4.0-dev.12) (2024-03-25)

### Bug Fixes

* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([0bd0c82](0bd0c827a4))
2024-03-25 23:35:10 +00:00
oSumAtrIX
0bd0c827a4 fix(YouTube): Fix video playback by switching to ReVanced GmsCore vendor (#2907)
The previous vendor did not update GmsCore, resulting in missing features required for playback, specifically PoToken, which was added to requests recently. Because the PoToken was missing, playback failed.
2024-03-26 00:32:59 +01:00
semantic-release-bot
cbae1383ca chore(release): 4.4.0-dev.11 [skip ci]
# [4.4.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.10...v4.4.0-dev.11) (2024-03-25)

### Features

* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([2679fad](2679fad25f))
* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([08c4468](08c4468ff1))
2024-03-25 20:55:19 +00:00
Michał Pisarski
2679fad25f feat(Mi Fitness): Add Force English locale and Fix login patch (#2734)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-25 21:53:23 +01:00
Lightdm
08c4468ff1 feat(Sync for Lemmy): Add Disable ads patch (#2872)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-25 21:52:23 +01:00
semantic-release-bot
7c981f6759 chore(release): 4.4.0-dev.10 [skip ci]
# [4.4.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.9...v4.4.0-dev.10) (2024-03-25)

### Bug Fixes

* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([2fcd786](2fcd786cc7))
2024-03-25 16:15:34 +00:00
LisoUseInAIKyrios
2fcd786cc7 fix(YouTube - Hide ads): Prevent app crash if hiding fullscreen ads is not possible (#2910)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-25 20:13:28 +04:00
semantic-release-bot
60ace80cbd chore(release): 4.4.0-dev.9 [skip ci]
# [4.4.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.8...v4.4.0-dev.9) (2024-03-18)

### Bug Fixes

* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([e6a468c](e6a468cf7a))
2024-03-18 00:23:31 +00:00
LisoUseInAIKyrios
e6a468cf7a fix(TikTok): Hook application context earlier to prevent crash (#2893) 2024-03-18 04:21:34 +04:00
semantic-release-bot
38392de4a1 chore(release): 4.4.0-dev.8 [skip ci]
# [4.4.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.7...v4.4.0-dev.8) (2024-03-15)

### Features

* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([bc8bc8c](bc8bc8c798))
2024-03-15 12:35:13 +00:00
LisoUseInAIKyrios
bc8bc8c798 feat(YouTube - Downloads): Use external downloader when selecting 'Download' in home feed flyout menu (#2881) 2024-03-15 16:33:02 +04:00
semantic-release-bot
76805e4f31 chore(release): 4.4.0-dev.7 [skip ci]
# [4.4.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.6...v4.4.0-dev.7) (2024-03-14)

### Bug Fixes

* **YouTube - Client spoof:** Spoof all user agents ([d18719c](d18719c59c))
2024-03-14 23:30:09 +00:00
oSumAtrIX
d18719c59c fix(YouTube - Client spoof): Spoof all user agents 2024-03-15 00:28:01 +01:00
semantic-release-bot
743a02f983 chore(release): 4.4.0-dev.6 [skip ci]
# [4.4.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.5...v4.4.0-dev.6) (2024-03-12)

### Features

* **Instagram - Hide timeline ads:** Make compatible with latest versions ([8306f70](8306f70fd1))
2024-03-12 17:27:42 +00:00
oSumAtrIX
8306f70fd1 feat(Instagram - Hide timeline ads): Make compatible with latest versions 2024-03-12 18:25:23 +01:00
semantic-release-bot
5d71f23471 chore(release): 4.4.0-dev.5 [skip ci]
# [4.4.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.4...v4.4.0-dev.5) (2024-03-11)

### Features

* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([122ef68](122ef68a4b))
2024-03-11 13:22:02 +00:00
LisoUseInAIKyrios
122ef68a4b feat(YouTube): Support version 19.05, 19.06, 19.07, 19.08 and 19.09 (#2862) 2024-03-11 17:20:07 +04:00
semantic-release-bot
b2a7a65bc0 chore(release): 4.4.0-dev.4 [skip ci]
# [4.4.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.3...v4.4.0-dev.4) (2024-03-11)

### Features

* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([32139f1](32139f151b))
2024-03-11 09:35:36 +00:00
LisoUseInAIKyrios
32139f151b feat(YouTube ): Remove HDR auto brightness patch (#2863)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-11 13:33:30 +04:00
semantic-release-bot
e55364ca87 chore(release): 4.4.0-dev.3 [skip ci]
# [4.4.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.2...v4.4.0-dev.3) (2024-03-08)

### Bug Fixes

* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([5cca421](5cca42121a))
2024-03-08 05:11:28 +00:00
LisoUseInAIKyrios
5cca42121a fix(YouTube - Downloads): Use new task context (#2841) 2024-03-08 09:09:15 +04:00
semantic-release-bot
7b0365360e chore(release): 4.4.0-dev.2 [skip ci]
# [4.4.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.1...v4.4.0-dev.2) (2024-03-04)

### Features

* **YouTube - External downloader:** Add ability to use in-app download button ([7f8b7c0](7f8b7c08b2))
2024-03-04 19:38:46 +00:00
oSumAtrIX
7f8b7c08b2 feat(YouTube - External downloader): Add ability to use in-app download button 2024-03-04 20:36:25 +01:00
oSumAtrIX
058acff28c build: Set target bytecode level to JVM 11 2024-03-04 18:10:12 +01:00
semantic-release-bot
060b2c2323 chore(release): 4.4.0-dev.1 [skip ci]
# [4.4.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0-dev.1) (2024-03-04)

### Features

* **YouTube Vanced:** Remove `Hide ads` patch ([bcce7be](bcce7bee9a))
2024-03-04 14:01:53 +00:00
oSumAtrIX
bcce7bee9a feat(YouTube Vanced): Remove Hide ads patch 2024-03-04 14:59:32 +01:00
oSumAtrIX
d3f83230f8 build: Bump dependencies 2024-03-02 20:51:11 +01:00
semantic-release-bot
0ad377bb4c chore(release): 4.3.0 [skip ci]
# [4.3.0](https://github.com/ReVanced/revanced-patches/compare/v4.2.0...v4.3.0) (2024-03-02)

### Bug Fixes

* Compile DEX without debugging information ([afe7f06](afe7f0605e))
* **Override certificate pinning:** Always overwrite with a generic network security configuration ([16eee2f](16eee2f03f))
* Remove extra space from patch description ([#2780](https://github.com/ReVanced/revanced-patches/issues/2780)) ([a6f5dd9](a6f5dd933f))
* Use deprecated members to ensure backwards compatibility ([a6d8e42](a6d8e4210f))
* **YouTube - Spoof app version:** Remove broken versions ([#2776](https://github.com/ReVanced/revanced-patches/issues/2776)) ([2fe9060](2fe9060944))
* **YouTube - Spoof signature:** Fix tracking such as history or watch time ([f2edae2](f2edae2ac1))

### Features

* **OpeningHours:** Add `Fix crash` patch ([#2697](https://github.com/ReVanced/revanced-patches/issues/2697)) ([6742cd9](6742cd9232))
* Remove unnecessary description from patch ([348e42a](348e42a374))
* **Sync for Reddit:** Add `Fix /s/ links` patch ([0434d88](0434d8812b))
* **Twitter - Unlock downloads:** Unlock GIF downloads ([3200da8](3200da8657))
* **VSCO - Unlock pro:** Constrain to last working version ([0f7ed84](0f7ed841d1))
* **X:** Add `Open links as query` patch ([#2730](https://github.com/ReVanced/revanced-patches/issues/2730)) ([43359b9](43359b95eb))
* **YouTube - Change header:** Improve patch option description ([e775bc2](e775bc2cae))
* **YouTube - Change start page:** Add more start pages ([96f9b73](96f9b73c74))
* **YouTube - Custom branding:** Improve patch option description ([f4b888b](f4b888be56))
* **YouTube - Spoof app version:** Add target versions ([#2787](https://github.com/ReVanced/revanced-patches/issues/2787)) ([f9ae1a4](f9ae1a46d2))
* **YouTube:** Reorganize settings menu ([#2737](https://github.com/ReVanced/revanced-patches/issues/2737)) ([3b4b21f](3b4b21ff2e))
2024-03-02 18:59:36 +00:00
oSumAtrIX
9917ddd9c1 chore: Merge branch dev to main (#2707) 2024-03-02 19:57:07 +01:00
semantic-release-bot
951ebc54ca chore(release): 4.3.0-dev.13 [skip ci]
# [4.3.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.12...v4.3.0-dev.13) (2024-03-02)

### Features

* **YouTube:** Reorganize settings menu ([#2737](https://github.com/ReVanced/revanced-patches/issues/2737)) ([3b4b21f](3b4b21ff2e))
2024-03-02 07:29:04 +00:00
LisoUseInAIKyrios
3b4b21ff2e feat(YouTube): Reorganize settings menu (#2737)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: dic1911 <htk030@protonmail.com>
2024-03-02 08:27:05 +01:00
semantic-release-bot
2f2ad3e584 chore(release): 4.3.0-dev.12 [skip ci]
# [4.3.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.11...v4.3.0-dev.12) (2024-03-02)

### Features

* **YouTube - Spoof app version:** Add target versions ([#2787](https://github.com/ReVanced/revanced-patches/issues/2787)) ([f9ae1a4](f9ae1a46d2))
2024-03-02 07:12:52 +00:00
kitadai31
f9ae1a46d2 feat(YouTube - Spoof app version): Add target versions (#2787) 2024-03-02 08:10:07 +01:00
semantic-release-bot
e386313deb chore(release): 4.3.0-dev.11 [skip ci]
# [4.3.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.10...v4.3.0-dev.11) (2024-03-02)

### Bug Fixes

* **YouTube - Spoof signature:** Fix tracking such as history or watch time ([f2edae2](f2edae2ac1))
2024-03-02 07:05:33 +00:00
oSumAtrIX
f2edae2ac1 fix(YouTube - Spoof signature): Fix tracking such as history or watch time 2024-03-02 08:03:07 +01:00
semantic-release-bot
c153979981 chore(release): 4.3.0-dev.10 [skip ci]
# [4.3.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.9...v4.3.0-dev.10) (2024-02-29)

### Bug Fixes

* **YouTube - Spoof app version:** Remove broken versions ([#2776](https://github.com/ReVanced/revanced-patches/issues/2776)) ([2fe9060](2fe9060944))
2024-02-29 00:18:20 +00:00
oSumAtrIX
2fe9060944 fix(YouTube - Spoof app version): Remove broken versions (#2776) 2024-02-29 01:16:06 +01:00
semantic-release-bot
212a94cbb3 chore(release): 4.3.0-dev.9 [skip ci]
# [4.3.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.8...v4.3.0-dev.9) (2024-02-28)

### Bug Fixes

* **Override certificate pinning:** Always overwrite with a generic network security configuration ([16eee2f](16eee2f03f))
2024-02-28 22:04:01 +00:00
oSumAtrIX
16eee2f03f fix(Override certificate pinning): Always overwrite with a generic network security configuration
Previously some conditional checks prevented to patch YouTube for example. The current configuration should work globally for all apps.
2024-02-28 23:01:56 +01:00
semantic-release-bot
4937fa5fbd chore(release): 4.3.0-dev.8 [skip ci]
# [4.3.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.7...v4.3.0-dev.8) (2024-02-28)

### Bug Fixes

* Remove extra space from patch description ([#2780](https://github.com/ReVanced/revanced-patches/issues/2780)) ([a6f5dd9](a6f5dd933f))
2024-02-28 20:35:11 +00:00
KobeW50
a6f5dd933f fix: Remove extra space from patch description (#2780) 2024-02-28 21:32:55 +01:00
semantic-release-bot
97c4682ccc chore(release): 4.3.0-dev.7 [skip ci]
# [4.3.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.6...v4.3.0-dev.7) (2024-02-26)

### Features

* **OpeningHours:** Add `Fix crash` patch ([#2697](https://github.com/ReVanced/revanced-patches/issues/2697)) ([6742cd9](6742cd9232))
2024-02-26 03:52:58 +00:00
Linus
6742cd9232 feat(OpeningHours): Add Fix crash patch (#2697)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-02-26 04:50:59 +01:00
oSumAtrIX
5b2cc10adb docs: Fix broken links 2024-02-26 04:37:44 +01:00
semantic-release-bot
dbad6252fb chore(release): 4.3.0-dev.6 [skip ci]
# [4.3.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.5...v4.3.0-dev.6) (2024-02-25)

### Features

* **VSCO - Unlock pro:** Constrain to last working version ([0f7ed84](0f7ed841d1))
2024-02-25 18:30:14 +00:00
oSumAtrIX
0f7ed841d1 feat(VSCO - Unlock pro): Constrain to last working version 2024-02-25 19:28:12 +01:00
semantic-release-bot
d33d7d8f35 chore(release): 4.3.0-dev.5 [skip ci]
# [4.3.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.4...v4.3.0-dev.5) (2024-02-25)

### Features

* Remove unnecessary description from patch ([348e42a](348e42a374))
* **Twitter - Unlock downloads:** Unlock GIF downloads ([3200da8](3200da8657))
2024-02-25 07:02:56 +00:00
oSumAtrIX
3200da8657 feat(Twitter - Unlock downloads): Unlock GIF downloads 2024-02-25 08:00:29 +01:00
oSumAtrIX
348e42a374 feat: Remove unnecessary description from patch 2024-02-25 06:51:51 +01:00
oSumAtrIX
cbbac445b6 chore: Rename issue templates 2024-02-25 03:37:53 +01:00
oSumAtrIX
1593d1352a ci: Fix indentation in workflow 2024-02-24 01:14:45 +01:00
oSumAtrIX
c6fedaa7bc docs: Break long lines 2024-02-23 04:12:28 +01:00
oSumAtrIX
d070aebec4 docs: Fix mistakes and wording 2024-02-23 04:12:28 +01:00
oSumAtrIX
d583256f06 docs: Remove documentation section
The documentation for patches is being moved to the ReVanced Patcher repository. The reason for this is because the documentation about how to create patches using ReVanced Patcher, belongs in the ReVanced Patcher repository, whereas documentation specific to the public API of ReVanced Patches belongs in this repository. Because the public API has no documentation yet, the section is removed until then.
2024-02-23 02:55:45 +01:00
oSumAtrIX
fc67d284f7 ci: Fix PR builds by adding missing GitHub token 2024-02-23 02:23:50 +01:00
semantic-release-bot
d3f3f81b75 chore(release): 4.3.0-dev.4 [skip ci]
# [4.3.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.3...v4.3.0-dev.4) (2024-02-22)

### Bug Fixes

* Compile DEX without debugging information ([afe7f06](afe7f0605e))
* Use deprecated members to ensure backwards compatibility ([a6d8e42](a6d8e4210f))

### Features

* **X:** Add `Open links as query` patch ([#2730](https://github.com/ReVanced/revanced-patches/issues/2730)) ([43359b9](43359b95eb))
2024-02-22 00:13:48 +00:00
oSumAtrIX
8e8600c7c3 chore: Update fingerprint
The compiler of ReVanced Integrations now compiles the target method without `AccessFlags.Public`.
2024-02-22 01:11:17 +01:00
oSumAtrIX
ea33863083 ci: Do not start a Gradle daemon for PR builds
Because there are no subsequent builds, a daemon is not necessary
2024-02-22 01:10:09 +01:00
oSumAtrIX
a6d8e4210f fix: Use deprecated members to ensure backwards compatibility
By migrating to early to new APIs of ReVanced Patcher, if you were to use old versions of ReVanced Patcher, you would get compatibility issues. By using deprecated members until most have updated ReVanced Patcher, we can ensure seamless migration.
2024-02-22 01:10:09 +01:00
oSumAtrIX
1e3356808d ci: Split release into a separate PR build workflow
Because the release workflow already runs on dev and main, it is not necessary to also trigger it for PRs.
2024-02-22 01:07:05 +01:00
dic1911
43359b95eb feat(X): Add Open links as query patch (#2730)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-02-22 01:07:05 +01:00
oSumAtrIX
afe7f0605e fix: Compile DEX without debugging information 2024-02-21 04:15:38 +01:00
oSumAtrIX
8916789f7a build: Publish to GitHub Packages 2024-02-21 04:15:38 +01:00
oSumAtrIX
0d14aa1191 build: Sign release artifacts 2024-02-21 04:15:38 +01:00
oSumAtrIX
376dda6e81 build: Bump dependencies
This commit also migrates away from deprecated to new APIs
2024-02-21 04:07:32 +01:00
semantic-release-bot
ff8b58b645 chore(release): 4.3.0-dev.3 [skip ci]
# [4.3.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.2...v4.3.0-dev.3) (2024-02-20)

### Features

* **YouTube - Change header:** Improve patch option description ([e775bc2](e775bc2cae))
* **YouTube - Custom branding:** Improve patch option description ([f4b888b](f4b888be56))
2024-02-20 21:43:11 +00:00
oSumAtrIX
f4b888be56 feat(YouTube - Custom branding): Improve patch option description 2024-02-20 22:41:06 +01:00
oSumAtrIX
e775bc2cae feat(YouTube - Change header): Improve patch option description 2024-02-20 22:41:06 +01:00
oSumAtrIX
5c566753a8 build: Bump dependencies 2024-02-14 02:44:25 +01:00
oSumAtrIX
968ebf9f50 build: Bump Gradle 2024-02-14 02:41:21 +01:00
oSumAtrIX
75c510d876 chore: Fix ReplaceWith of Deprecated annotation 2024-02-13 03:27:03 +01:00
oSumAtrIX
72528cb2f1 chore: Remove dummy subproject
It is not necessary anymore
2024-02-13 02:58:24 +01:00
oSumAtrIX
81d79111cf chore: Add .editorconfig 2024-02-13 02:55:07 +01:00
oSumAtrIX
33036092b4 build: Bump dependencies 2024-02-13 02:54:40 +01:00
semantic-release-bot
f5f88092b6 chore(release): 4.3.0-dev.2 [skip ci]
# [4.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.1...v4.3.0-dev.2) (2024-02-09)

### Features

* **Sync for Reddit:** Add `Fix /s/ links` patch ([0434d88](0434d8812b))
2024-02-09 02:47:31 +00:00
oSumAtrIX
0434d8812b feat(Sync for Reddit): Add Fix /s/ links patch 2024-02-09 03:45:37 +01:00
semantic-release-bot
ec38b8e51c chore(release): 4.3.0-dev.1 [skip ci]
# [4.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.2.0...v4.3.0-dev.1) (2024-02-09)

### Features

* **YouTube - Change start page:** Add more start pages ([96f9b73](96f9b73c74))
2024-02-09 00:17:34 +00:00
oSumAtrIX
96f9b73c74 feat(YouTube - Change start page): Add more start pages 2024-02-09 00:50:16 +01:00
semantic-release-bot
1502fe1f7f chore(release): 4.2.0 [skip ci]
# [4.2.0](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.2.0) (2024-02-08)

### Bug Fixes

* **Infinity for Reddit - Unlock subscription:** Do not crash by patching billing client ([53b29ea](53b29ea270))

### Features

* **X:** Add `Hide view count` patch ([1bf9582](1bf9582437))
* **X:** Add `Unlock downloads` patch ([3343b5c](3343b5cb12))
2024-02-08 19:17:40 +00:00
oSumAtrIX
824d094394 chore: Merge branch dev to main (#2693) 2024-02-08 20:15:32 +01:00
semantic-release-bot
010471a745 chore(release): 4.2.0-dev.1 [skip ci]
# [4.2.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.1.1-dev.1...v4.2.0-dev.1) (2024-02-08)

### Features

* **X:** Add `Hide view count` patch ([1bf9582](1bf9582437))
* **X:** Add `Unlock downloads` patch ([3343b5c](3343b5cb12))
2024-02-08 19:13:57 +00:00
oSumAtrIX
3343b5cb12 feat(X): Add Unlock downloads patch 2024-02-08 20:11:18 +01:00
oSumAtrIX
1bf9582437 feat(X): Add Hide view count patch 2024-02-08 20:08:44 +01:00
semantic-release-bot
ea09d4b520 chore(release): 4.1.1-dev.1 [skip ci]
## [4.1.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.1.1-dev.1) (2024-02-07)

### Bug Fixes

* **Infinity for Reddit - Unlock subscription:** Do not crash by patching billing client ([53b29ea](53b29ea270))
2024-02-07 15:19:04 +00:00
oSumAtrIX
53b29ea270 fix(Infinity for Reddit - Unlock subscription): Do not crash by patching billing client 2024-02-07 16:16:33 +01:00
oSumAtrIX
fd11e2b969 chore: Fix typo in README 2024-02-05 23:24:05 +01:00
semantic-release-bot
65a32ee52e chore(release): 4.1.0 [skip ci]
# [4.1.0](https://github.com/ReVanced/revanced-patches/compare/v4.0.2...v4.1.0) (2024-02-05)

### Bug Fixes

* **Infinity for Reddit - Unlock subscription:** Restore functionality on v7.0.0 ([2c50c25](2c50c25a36))
* **YouTube:** Correctly show channel page on tablet devices ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([047069c](047069ca8a))

### Features

* **YouTube - Custom filter:** Custom filtering of the protocol buffer ([#2682](https://github.com/ReVanced/revanced-patches/issues/2682)) ([19a9d11](19a9d113d9))
* **YouTube:** Support version `19.04.37` ([#2687](https://github.com/ReVanced/revanced-patches/issues/2687)) ([8b1cdd5](8b1cdd5c6a))
2024-02-05 19:26:27 +00:00
oSumAtrIX
7b2e32d88c chore: Merge branch dev to main (#2657) 2024-02-05 20:24:31 +01:00
semantic-release-bot
f18edb262d chore(release): 4.1.0-dev.2 [skip ci]
# [4.1.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.1.0-dev.1...v4.1.0-dev.2) (2024-02-04)

### Features

* **YouTube:** Support version `19.04.37` ([#2687](https://github.com/ReVanced/revanced-patches/issues/2687)) ([8b1cdd5](8b1cdd5c6a))
2024-02-04 17:40:14 +00:00
LisoUseInAIKyrios
8b1cdd5c6a feat(YouTube): Support version 19.04.37 (#2687) 2024-02-04 21:38:19 +04:00
semantic-release-bot
3bd41fb67f chore(release): 4.1.0-dev.1 [skip ci]
# [4.1.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.0.3-dev.2...v4.1.0-dev.1) (2024-02-02)

### Features

* **YouTube - Custom filter:** Custom filtering of the protocol buffer ([#2682](https://github.com/ReVanced/revanced-patches/issues/2682)) ([19a9d11](19a9d113d9))
2024-02-02 08:17:53 +00:00
LisoUseInAIKyrios
19a9d113d9 feat(YouTube - Custom filter): Custom filtering of the protocol buffer (#2682) 2024-02-02 12:15:34 +04:00
255 changed files with 4685 additions and 2589 deletions

3
.editorconfig Normal file
View File

@@ -0,0 +1,3 @@
[*.{kt,kts}]
ktlint_code_style = intellij_idea
ktlint_standard_no-wildcard-imports = disabled

View File

@@ -0,0 +1,25 @@
name: Build pull request
on:
workflow_dispatch:
pull_request:
branches:
- dev
jobs:
release:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache Gradle
uses: burrunan/gradle-cache-action@v1
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew build --no-daemon

34
.github/workflows/pull_strings.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Pull strings
on:
workflow_dispatch:
schedule:
- cron: 0 0 1 * *
jobs:
pull:
name: Pull strings
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Pull strings
uses: crowdin/github-action@v1
with:
config: crowdin.yml
download_translations: true
localization_branch_name: feat/translations
create_pull_request: true
pull_request_title: "chore: Sync translations"
pull_request_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)"
pull_request_base_branch_name: "dev"
commit_message: "chore: Sync translations"
github_user_name: revanced-bot
github_user_email: github@revanced.app
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

27
.github/workflows/push_strings.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Push strings
on:
workflow_dispatch:
push:
paths:
- /src/main/resources/addresources/values/strings.xml
jobs:
push:
name: Push strings
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Push strings
uses: crowdin/github-action@v1
with:
config: crowdin.yml
upload_sources: true
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

@@ -6,10 +6,6 @@ on:
branches:
- main
- dev
pull_request:
branches:
- main
- dev
jobs:
release:
@@ -41,6 +37,13 @@ jobs:
- name: Install dependencies
run: npm install
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
fingerprint: ${{ env.GPG_FINGERPRINT }}
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}

View File

@@ -33,7 +33,7 @@
{
"assets": [
{
"path": "build/libs/*.jar"
"path": "build/libs/revanced-patches*"
},
{
"path": "patches.json"

View File

@@ -1,3 +1,431 @@
# [4.7.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.2...v4.7.0-dev.3) (2024-04-09)
### Bug Fixes
* **Tumblr - Fix old versions:** Improve reliability by removing remnances of Tumblr Live ([#2988](https://github.com/ReVanced/revanced-patches/issues/2988)) ([897b4db](https://github.com/ReVanced/revanced-patches/commit/897b4dbce984270ae1fd7de5bd30bd05153e45f2))
# [4.7.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.7.0-dev.1...v4.7.0-dev.2) (2024-04-06)
### Features
* **Strava - Unlock subscription:** Remove compatible version constraint ([80a5599](https://github.com/ReVanced/revanced-patches/commit/80a55991683d7b22626224fa2935a5bf9bfcbfee))
# [4.7.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.3...v4.7.0-dev.1) (2024-04-06)
### Features
* **YouTube - Hide layout components:** Add option to hide horizontal shelves ([#2951](https://github.com/ReVanced/revanced-patches/issues/2951)) ([9ae0650](https://github.com/ReVanced/revanced-patches/commit/9ae0650c0005d882299996aa442410bab4261395))
## [4.6.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.2...v4.6.1-dev.3) (2024-04-06)
### Bug Fixes
* **YouTube - GmsCore support:** Prompt to disable battery optimizations, if not done already ([#2958](https://github.com/ReVanced/revanced-patches/issues/2958)) ([82acb84](https://github.com/ReVanced/revanced-patches/commit/82acb84b5f6ff0722a2eb080b53da9dd3622502f))
## [4.6.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.6.1-dev.1...v4.6.1-dev.2) (2024-04-04)
### Bug Fixes
* **YouTube - Hide load more button:** Include patch with `Hide layout components`, and hide button only in search feed ([#2959](https://github.com/ReVanced/revanced-patches/issues/2959)) ([b007e8e](https://github.com/ReVanced/revanced-patches/commit/b007e8e06a3afad79b40bec1c6a14604f059049c))
## [4.6.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.6.0...v4.6.1-dev.1) (2024-04-04)
### Bug Fixes
* **YouTube - Player flyout menu:** Add hide Lock screen menu ([#2985](https://github.com/ReVanced/revanced-patches/issues/2985)) ([308de4a](https://github.com/ReVanced/revanced-patches/commit/308de4a63ca99b8d30d6b3242f98d6f0e2aefb37))
# [4.6.0](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.6.0) (2024-04-02)
### Bug Fixes
* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([dc96942](https://github.com/ReVanced/revanced-patches/commit/dc969422b5d50f21e6ea7a64b67dfc650fee6e36))
* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([2954ba7](https://github.com/ReVanced/revanced-patches/commit/2954ba78d21d77308404961f79234bbec606d42e))
### Features
* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2fde60e](https://github.com/ReVanced/revanced-patches/commit/2fde60eceb0a96fa857c32cd55c1fd7fe776a679))
# [4.6.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.2...v4.6.0-dev.1) (2024-03-31)
### Features
* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2fde60e](https://github.com/ReVanced/revanced-patches/commit/2fde60eceb0a96fa857c32cd55c1fd7fe776a679))
## [4.5.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.1...v4.5.1-dev.2) (2024-03-30)
### Bug Fixes
* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([dc96942](https://github.com/ReVanced/revanced-patches/commit/dc969422b5d50f21e6ea7a64b67dfc650fee6e36))
## [4.5.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.5.1-dev.1) (2024-03-30)
### Bug Fixes
* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([2954ba7](https://github.com/ReVanced/revanced-patches/commit/2954ba78d21d77308404961f79234bbec606d42e))
# [4.5.0](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0) (2024-03-30)
### Features
* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949))
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730))
# [4.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.0-dev.1...v4.5.0-dev.2) (2024-03-30)
### Features
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730))
# [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29)
### Features
* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949))
# [4.4.0](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0) (2024-03-27)
### Bug Fixes
* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([395ccda](https://github.com/ReVanced/revanced-patches/commit/395ccda7b9218c522c7ca0f99f75a12036d3e3f3))
* **YouTube - Client spoof:** Spoof all user agents ([44a8a13](https://github.com/ReVanced/revanced-patches/commit/44a8a1399897caaff3ff45db8549ddedb2f01b68))
* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([6d88cb4](https://github.com/ReVanced/revanced-patches/commit/6d88cb49ec739700866290babcba5fb3032dbced))
* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([9f50470](https://github.com/ReVanced/revanced-patches/commit/9f50470bf6582fe2f20a903a97bf66c41f296fb2))
* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([8378c84](https://github.com/ReVanced/revanced-patches/commit/8378c8481634a63a5568480475757e64b7ec466e))
* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([33ea122](https://github.com/ReVanced/revanced-patches/commit/33ea12228c2ae5dcadf3e7c7016d4bf6006d899a))
* **YouTube:** Move setting to correct screen ([a16eda8](https://github.com/ReVanced/revanced-patches/commit/a16eda864515612d3a6b846082844df15eb49f56))
### Features
* **Instagram - Hide timeline ads:** Make compatible with latest versions ([a212f29](https://github.com/ReVanced/revanced-patches/commit/a212f29bd33bb5e10f024e058d26e20ee926190b))
* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([7a25791](https://github.com/ReVanced/revanced-patches/commit/7a25791d53530b1236896b2c3d6275ee7556e8b7))
* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([0785819](https://github.com/ReVanced/revanced-patches/commit/0785819dd5ad487c778b5baf09004cdab3687184))
* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([10afc8c](https://github.com/ReVanced/revanced-patches/commit/10afc8cc71ff29fea4937fb12fd3d1edf9c581f5))
* **YouTube - External downloader:** Add ability to use in-app download button ([d900011](https://github.com/ReVanced/revanced-patches/commit/d9000113a905c14f8409aa75008f1ef6a1aecd0c))
* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([5916204](https://github.com/ReVanced/revanced-patches/commit/59162042b0a68edf7f94a3c21f838dada3c3f9c3))
* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([2df0892](https://github.com/ReVanced/revanced-patches/commit/2df0892682406e67283c4aeaacebf8f222029833))
* **YouTube - Hide Shorts components:** Hide sound metadata label ([ea7d1e0](https://github.com/ReVanced/revanced-patches/commit/ea7d1e0d08cc245117ffe8ad0df3c31c5e87f739))
* **YouTube - Hide Shorts components:** Hide title and full video link label ([e7b64e1](https://github.com/ReVanced/revanced-patches/commit/e7b64e154e7fb8edd0037f5e171f4aa3ed9017f8))
* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([497c067](https://github.com/ReVanced/revanced-patches/commit/497c067e80e560eb125f5fc30eef9763929b4ee4))
* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([b4c7bf4](https://github.com/ReVanced/revanced-patches/commit/b4c7bf48084184e5f031f7f5139a9a29341d8ebf))
* **YouTube Vanced:** Remove `Hide ads` patch ([87887e4](https://github.com/ReVanced/revanced-patches/commit/87887e4163dd9e242209f4d0fefb415f9bc7ca75))
* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([f044dde](https://github.com/ReVanced/revanced-patches/commit/f044dde054861ff16846a6be6287f86fa3afb3d8))
# [4.4.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.14...v4.4.0-dev.15) (2024-03-27)
### Bug Fixes
* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([8378c84](https://github.com/ReVanced/revanced-patches/commit/8378c8481634a63a5568480475757e64b7ec466e))
### Features
* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([497c067](https://github.com/ReVanced/revanced-patches/commit/497c067e80e560eb125f5fc30eef9763929b4ee4))
# [4.4.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.13...v4.4.0-dev.14) (2024-03-27)
### Features
* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([5916204](https://github.com/ReVanced/revanced-patches/commit/59162042b0a68edf7f94a3c21f838dada3c3f9c3))
# [4.4.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.12...v4.4.0-dev.13) (2024-03-26)
### Bug Fixes
* **YouTube:** Move setting to correct screen ([a16eda8](https://github.com/ReVanced/revanced-patches/commit/a16eda864515612d3a6b846082844df15eb49f56))
### Features
* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([2df0892](https://github.com/ReVanced/revanced-patches/commit/2df0892682406e67283c4aeaacebf8f222029833))
* **YouTube - Hide Shorts components:** Hide sound metadata label ([ea7d1e0](https://github.com/ReVanced/revanced-patches/commit/ea7d1e0d08cc245117ffe8ad0df3c31c5e87f739))
* **YouTube - Hide Shorts components:** Hide title and full video link label ([e7b64e1](https://github.com/ReVanced/revanced-patches/commit/e7b64e154e7fb8edd0037f5e171f4aa3ed9017f8))
# [4.4.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.11...v4.4.0-dev.12) (2024-03-25)
### Bug Fixes
* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([33ea122](https://github.com/ReVanced/revanced-patches/commit/33ea12228c2ae5dcadf3e7c7016d4bf6006d899a))
# [4.4.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.10...v4.4.0-dev.11) (2024-03-25)
### Features
* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([7a25791](https://github.com/ReVanced/revanced-patches/commit/7a25791d53530b1236896b2c3d6275ee7556e8b7))
* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([0785819](https://github.com/ReVanced/revanced-patches/commit/0785819dd5ad487c778b5baf09004cdab3687184))
# [4.4.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.9...v4.4.0-dev.10) (2024-03-25)
### Bug Fixes
* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([9f50470](https://github.com/ReVanced/revanced-patches/commit/9f50470bf6582fe2f20a903a97bf66c41f296fb2))
# [4.4.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.8...v4.4.0-dev.9) (2024-03-18)
### Bug Fixes
* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([395ccda](https://github.com/ReVanced/revanced-patches/commit/395ccda7b9218c522c7ca0f99f75a12036d3e3f3))
# [4.4.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.7...v4.4.0-dev.8) (2024-03-15)
### Features
* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([10afc8c](https://github.com/ReVanced/revanced-patches/commit/10afc8cc71ff29fea4937fb12fd3d1edf9c581f5))
# [4.4.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.6...v4.4.0-dev.7) (2024-03-14)
### Bug Fixes
* **YouTube - Client spoof:** Spoof all user agents ([44a8a13](https://github.com/ReVanced/revanced-patches/commit/44a8a1399897caaff3ff45db8549ddedb2f01b68))
# [4.4.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.5...v4.4.0-dev.6) (2024-03-12)
### Features
* **Instagram - Hide timeline ads:** Make compatible with latest versions ([a212f29](https://github.com/ReVanced/revanced-patches/commit/a212f29bd33bb5e10f024e058d26e20ee926190b))
# [4.4.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.4...v4.4.0-dev.5) (2024-03-11)
### Features
* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([f044dde](https://github.com/ReVanced/revanced-patches/commit/f044dde054861ff16846a6be6287f86fa3afb3d8))
# [4.4.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.3...v4.4.0-dev.4) (2024-03-11)
### Features
* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([b4c7bf4](https://github.com/ReVanced/revanced-patches/commit/b4c7bf48084184e5f031f7f5139a9a29341d8ebf))
# [4.4.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.2...v4.4.0-dev.3) (2024-03-08)
### Bug Fixes
* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([6d88cb4](https://github.com/ReVanced/revanced-patches/commit/6d88cb49ec739700866290babcba5fb3032dbced))
# [4.4.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.1...v4.4.0-dev.2) (2024-03-04)
### Features
* **YouTube - External downloader:** Add ability to use in-app download button ([d900011](https://github.com/ReVanced/revanced-patches/commit/d9000113a905c14f8409aa75008f1ef6a1aecd0c))
# [4.4.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0-dev.1) (2024-03-04)
### Features
* **YouTube Vanced:** Remove `Hide ads` patch ([87887e4](https://github.com/ReVanced/revanced-patches/commit/87887e4163dd9e242209f4d0fefb415f9bc7ca75))
# [4.3.0](https://github.com/ReVanced/revanced-patches/compare/v4.2.0...v4.3.0) (2024-03-02)
### Bug Fixes
* Compile DEX without debugging information ([f5df957](https://github.com/ReVanced/revanced-patches/commit/f5df9578669f71a67411bc93a25a7e8da43610d0))
* **Override certificate pinning:** Always overwrite with a generic network security configuration ([2a842a1](https://github.com/ReVanced/revanced-patches/commit/2a842a1e14e1993eb028ae0bd1a93e227bb929a6))
* Remove extra space from patch description ([#2780](https://github.com/ReVanced/revanced-patches/issues/2780)) ([96a3f35](https://github.com/ReVanced/revanced-patches/commit/96a3f359266ff8d16ae9ee3c6ce2f16ce67a3b93))
* Use deprecated members to ensure backwards compatibility ([083bd40](https://github.com/ReVanced/revanced-patches/commit/083bd4009231b9612394b4496ca1d329947d6577))
* **YouTube - Spoof app version:** Remove broken versions ([#2776](https://github.com/ReVanced/revanced-patches/issues/2776)) ([9466d97](https://github.com/ReVanced/revanced-patches/commit/9466d973c6d7a2891e3fa9f283107b64399152ea))
* **YouTube - Spoof signature:** Fix tracking such as history or watch time ([bcd8b48](https://github.com/ReVanced/revanced-patches/commit/bcd8b48e70693dac1bfcc0bf4971d6b526065b59))
### Features
* **OpeningHours:** Add `Fix crash` patch ([#2697](https://github.com/ReVanced/revanced-patches/issues/2697)) ([0d011b8](https://github.com/ReVanced/revanced-patches/commit/0d011b876ecf05031a7daa54ab7e6d3506728a47))
* Remove unnecessary description from patch ([1a89dd9](https://github.com/ReVanced/revanced-patches/commit/1a89dd9f8cd0c614055a9da97338839b77a25ed1))
* **Sync for Reddit:** Add `Fix /s/ links` patch ([f15ef3f](https://github.com/ReVanced/revanced-patches/commit/f15ef3f63460254236185f8e22c9395db4db9465))
* **Twitter - Unlock downloads:** Unlock GIF downloads ([d0f91c8](https://github.com/ReVanced/revanced-patches/commit/d0f91c8550592723e1252e1af2971b508591dd59))
* **VSCO - Unlock pro:** Constrain to last working version ([6dd4a7c](https://github.com/ReVanced/revanced-patches/commit/6dd4a7c29e48c3bc517bbdd7ed160624c36c2333))
* **X:** Add `Open links as query` patch ([#2730](https://github.com/ReVanced/revanced-patches/issues/2730)) ([ba75a51](https://github.com/ReVanced/revanced-patches/commit/ba75a51b71dbb9157db230b3e97a90361019fe30))
* **YouTube - Change header:** Improve patch option description ([3b8bc08](https://github.com/ReVanced/revanced-patches/commit/3b8bc08d4ed3a3a0f96d2f476e5059840b9f9d9b))
* **YouTube - Change start page:** Add more start pages ([cc1d9b7](https://github.com/ReVanced/revanced-patches/commit/cc1d9b743633c619fb6acc428e884c1c9b53e10b))
* **YouTube - Custom branding:** Improve patch option description ([e27f56c](https://github.com/ReVanced/revanced-patches/commit/e27f56c8a34d41167b290f47280276c1c6003876))
* **YouTube - Spoof app version:** Add target versions ([#2787](https://github.com/ReVanced/revanced-patches/issues/2787)) ([83a7bd8](https://github.com/ReVanced/revanced-patches/commit/83a7bd8d69e62623fc4d2ba73d9fb49e92751d89))
* **YouTube:** Reorganize settings menu ([#2737](https://github.com/ReVanced/revanced-patches/issues/2737)) ([36132df](https://github.com/ReVanced/revanced-patches/commit/36132df4be6a04c08b6f3dd79de1bcea93a80fb8))
# [4.3.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.12...v4.3.0-dev.13) (2024-03-02)
### Features
* **YouTube:** Reorganize settings menu ([#2737](https://github.com/ReVanced/revanced-patches/issues/2737)) ([36132df](https://github.com/ReVanced/revanced-patches/commit/36132df4be6a04c08b6f3dd79de1bcea93a80fb8))
# [4.3.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.11...v4.3.0-dev.12) (2024-03-02)
### Features
* **YouTube - Spoof app version:** Add target versions ([#2787](https://github.com/ReVanced/revanced-patches/issues/2787)) ([83a7bd8](https://github.com/ReVanced/revanced-patches/commit/83a7bd8d69e62623fc4d2ba73d9fb49e92751d89))
# [4.3.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.10...v4.3.0-dev.11) (2024-03-02)
### Bug Fixes
* **YouTube - Spoof signature:** Fix tracking such as history or watch time ([bcd8b48](https://github.com/ReVanced/revanced-patches/commit/bcd8b48e70693dac1bfcc0bf4971d6b526065b59))
# [4.3.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.9...v4.3.0-dev.10) (2024-02-29)
### Bug Fixes
* **YouTube - Spoof app version:** Remove broken versions ([#2776](https://github.com/ReVanced/revanced-patches/issues/2776)) ([9466d97](https://github.com/ReVanced/revanced-patches/commit/9466d973c6d7a2891e3fa9f283107b64399152ea))
# [4.3.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.8...v4.3.0-dev.9) (2024-02-28)
### Bug Fixes
* **Override certificate pinning:** Always overwrite with a generic network security configuration ([2a842a1](https://github.com/ReVanced/revanced-patches/commit/2a842a1e14e1993eb028ae0bd1a93e227bb929a6))
# [4.3.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.7...v4.3.0-dev.8) (2024-02-28)
### Bug Fixes
* Remove extra space from patch description ([#2780](https://github.com/ReVanced/revanced-patches/issues/2780)) ([96a3f35](https://github.com/ReVanced/revanced-patches/commit/96a3f359266ff8d16ae9ee3c6ce2f16ce67a3b93))
# [4.3.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.6...v4.3.0-dev.7) (2024-02-26)
### Features
* **OpeningHours:** Add `Fix crash` patch ([#2697](https://github.com/ReVanced/revanced-patches/issues/2697)) ([0d011b8](https://github.com/ReVanced/revanced-patches/commit/0d011b876ecf05031a7daa54ab7e6d3506728a47))
# [4.3.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.5...v4.3.0-dev.6) (2024-02-25)
### Features
* **VSCO - Unlock pro:** Constrain to last working version ([6dd4a7c](https://github.com/ReVanced/revanced-patches/commit/6dd4a7c29e48c3bc517bbdd7ed160624c36c2333))
# [4.3.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.4...v4.3.0-dev.5) (2024-02-25)
### Features
* Remove unnecessary description from patch ([1a89dd9](https://github.com/ReVanced/revanced-patches/commit/1a89dd9f8cd0c614055a9da97338839b77a25ed1))
* **Twitter - Unlock downloads:** Unlock GIF downloads ([d0f91c8](https://github.com/ReVanced/revanced-patches/commit/d0f91c8550592723e1252e1af2971b508591dd59))
# [4.3.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.3...v4.3.0-dev.4) (2024-02-22)
### Bug Fixes
* Compile DEX without debugging information ([f5df957](https://github.com/ReVanced/revanced-patches/commit/f5df9578669f71a67411bc93a25a7e8da43610d0))
* Use deprecated members to ensure backwards compatibility ([083bd40](https://github.com/ReVanced/revanced-patches/commit/083bd4009231b9612394b4496ca1d329947d6577))
### Features
* **X:** Add `Open links as query` patch ([#2730](https://github.com/ReVanced/revanced-patches/issues/2730)) ([ba75a51](https://github.com/ReVanced/revanced-patches/commit/ba75a51b71dbb9157db230b3e97a90361019fe30))
# [4.3.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.2...v4.3.0-dev.3) (2024-02-20)
### Features
* **YouTube - Change header:** Improve patch option description ([3b8bc08](https://github.com/ReVanced/revanced-patches/commit/3b8bc08d4ed3a3a0f96d2f476e5059840b9f9d9b))
* **YouTube - Custom branding:** Improve patch option description ([e27f56c](https://github.com/ReVanced/revanced-patches/commit/e27f56c8a34d41167b290f47280276c1c6003876))
# [4.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.3.0-dev.1...v4.3.0-dev.2) (2024-02-09)
### Features
* **Sync for Reddit:** Add `Fix /s/ links` patch ([f15ef3f](https://github.com/ReVanced/revanced-patches/commit/f15ef3f63460254236185f8e22c9395db4db9465))
# [4.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.2.0...v4.3.0-dev.1) (2024-02-09)
### Features
* **YouTube - Change start page:** Add more start pages ([cc1d9b7](https://github.com/ReVanced/revanced-patches/commit/cc1d9b743633c619fb6acc428e884c1c9b53e10b))
# [4.2.0](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.2.0) (2024-02-08)
### Bug Fixes
* **Infinity for Reddit - Unlock subscription:** Do not crash by patching billing client ([7d76e2e](https://github.com/ReVanced/revanced-patches/commit/7d76e2e43c69b2b75f40a15a9147d041c77cbcd9))
### Features
* **X:** Add `Hide view count` patch ([bf064ec](https://github.com/ReVanced/revanced-patches/commit/bf064ecc1d5de8b592d14d34acfa1a4314c374ba))
* **X:** Add `Unlock downloads` patch ([2c20844](https://github.com/ReVanced/revanced-patches/commit/2c20844eaae698f185a9d321e2c70bde4b485cee))
# [4.2.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.1.1-dev.1...v4.2.0-dev.1) (2024-02-08)
### Features
* **X:** Add `Hide view count` patch ([bf064ec](https://github.com/ReVanced/revanced-patches/commit/bf064ecc1d5de8b592d14d34acfa1a4314c374ba))
* **X:** Add `Unlock downloads` patch ([2c20844](https://github.com/ReVanced/revanced-patches/commit/2c20844eaae698f185a9d321e2c70bde4b485cee))
## [4.1.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.1.0...v4.1.1-dev.1) (2024-02-07)
### Bug Fixes
* **Infinity for Reddit - Unlock subscription:** Do not crash by patching billing client ([7d76e2e](https://github.com/ReVanced/revanced-patches/commit/7d76e2e43c69b2b75f40a15a9147d041c77cbcd9))
# [4.1.0](https://github.com/ReVanced/revanced-patches/compare/v4.0.2...v4.1.0) (2024-02-05)
### Bug Fixes
* **Infinity for Reddit - Unlock subscription:** Restore functionality on v7.0.0 ([bf19af9](https://github.com/ReVanced/revanced-patches/commit/bf19af99cb522f9027a4b3ae42d6258ac71758e5))
* **YouTube:** Correctly show channel page on tablet devices ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([c7c9700](https://github.com/ReVanced/revanced-patches/commit/c7c9700d93caeae105916d33376670f525276fac))
### Features
* **YouTube - Custom filter:** Custom filtering of the protocol buffer ([#2682](https://github.com/ReVanced/revanced-patches/issues/2682)) ([872a5b6](https://github.com/ReVanced/revanced-patches/commit/872a5b6d8969ab1569cd57ece3c400c3741049be))
* **YouTube:** Support version `19.04.37` ([#2687](https://github.com/ReVanced/revanced-patches/issues/2687)) ([c23e023](https://github.com/ReVanced/revanced-patches/commit/c23e0233cf5c28d354132443d227b42ddc4a3dad))
# [4.1.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.1.0-dev.1...v4.1.0-dev.2) (2024-02-04)
### Features
* **YouTube:** Support version `19.04.37` ([#2687](https://github.com/ReVanced/revanced-patches/issues/2687)) ([c23e023](https://github.com/ReVanced/revanced-patches/commit/c23e0233cf5c28d354132443d227b42ddc4a3dad))
# [4.1.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.0.3-dev.2...v4.1.0-dev.1) (2024-02-02)
### Features
* **YouTube - Custom filter:** Custom filtering of the protocol buffer ([#2682](https://github.com/ReVanced/revanced-patches/issues/2682)) ([872a5b6](https://github.com/ReVanced/revanced-patches/commit/872a5b6d8969ab1569cd57ece3c400c3741049be))
## [4.0.3-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.3-dev.1...v4.0.3-dev.2) (2024-02-01)

View File

@@ -64,15 +64,15 @@ This document describes how to contribute to ReVanced Patches.
## 📖 Resources to help you get started
* The [documentation](https://github.com/ReVanced/revanced-patches/tree/docs/docs) provides the fundamentals of patches
and everything necessary to create your own patch from scratch
* The [documentation](https://github.com/ReVanced/revanced-patcher/tree/docs/docs) contains the fundamentals
of ReVanced Patcher and how to use ReVanced Patcher to create patches
* [Our backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on
* [Issues](https://github.com/ReVanced/revanced-patches/issues) are where we keep track of bugs and feature requests
## 🙏 Submitting a feature request
Features can be requested by opening an issue using the
[Feature request issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Feature+request&projects=&template=feature-request.yml&title=feat%3A+).
[Feature request issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Feature+request&projects=&template=feature_request.yml&title=feat%3A+).
> **Note**
> Requests can be accepted or rejected at the discretion of maintainers of ReVanced Patches.
@@ -81,7 +81,7 @@ Features can be requested by opening an issue using the
## 🐞 Submitting a bug report
If you encounter a bug while using ReVanced Patches, open an issue using the
[Bug report issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Bug+report&projects=&template=bug-report.yml&title=bug%3A+).
[Bug report issue template](https://github.com/ReVanced/revanced-patches/issues/new?assignees=&labels=Bug+report&projects=&template=bug_report.yml&title=bug%3A+).
## 🧑‍⚖️ Guidelines for requesting or contributing patches
@@ -110,7 +110,7 @@ are unaffected by this change.
## 📝 How to contribute
1. Before contributing, it is recommended to open an issue to discuss your change
1. Before contributing, it is recommended to open an issue to discuss your change
with the maintainers of ReVanced Patches. This will help you determine whether your change is acceptable
and whether it is worth your time to implement it
2. Development happens on the `dev` branch. Fork the repository and create your branch from `dev`

View File

@@ -67,7 +67,7 @@ This repository contains a collection of ReVanced Patches.
## ❓ About
Patches are small modifications to Android apps that allow you to change the behaviour of or add new features,
Patches are small modifications to Android apps that allow you to change the behavior of or add new features,
block ads, customize the appearance, and much more.
## 💪 Features
@@ -77,11 +77,11 @@ Some of the features the patches provide are:
* 🚫 **Block ads**: Say goodbye to ads
***Customize your app**: Personalize the appearance of apps with various layouts and themes
* 🪄 **Add new features**: Extend the functionality of apps with lots of new features
* ⚙️ **Miscellaneous and general purpose**: Rename packages, enable debugging, disable screen capture restrictions,
export activities, etc.
* ⚙️ **Miscellaneous and general purpose**: Rename packages, enable debugging, disable screen capture restrictions,
export activities, etc.
***And much more!**
For a full list of all available patches, visit [revanced.app/patches](https://revanced.app/patches).
For a complete list of all available patches, visit [revanced.app/patches](https://revanced.app/patches).
## 🚀 How to get started
@@ -93,17 +93,13 @@ You can use [ReVanced CLI](https://github.com/ReVanced/revanced-cli) or [ReVance
Thank you for considering contributing to ReVanced Patches. You can find the contribution guidelines [here](CONTRIBUTING.md).
### 📃 Documentation
The documentation provides the fundamentals of patches and everything necessary to create your own patch from scratch.
You can find it [here](https://github.com/ReVanced/revanced-patches/tree/docs/docs).
### 🛠️ Building
In order to build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
To build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
## 📜 Licence
ReVanced Patches is licensed under the GPLv3 licence. Please see the [licence file](LICENSE) for more information.
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced patches as long as you track changes/dates in source files.
Any modifications to ReVanced Patches must also be made available under the GPL along with build & install instructions.
ReVanced Patches is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Patches as long as you track changes/dates in source files.
Any modifications to ReVanced Patches must also be made available under the GPL,
along with build & install instructions.

View File

@@ -1,3 +1,7 @@
public final class app/revanced/generator/MainKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class app/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/all/activity/exportall/ExportAllActivitiesPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
@@ -280,12 +284,30 @@ public final class app/revanced/patches/messenger/inputfield/patch/DisableTyping
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/mifitness/misc/login/FixLoginPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/login/FixLoginPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/moneymanager/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/moneymanager/UnlockProPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/ad/video/HideMusicVideoAds : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/ad/video/HideMusicVideoAds;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/ad/video/MusicVideoAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/ad/video/MusicVideoAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -298,6 +320,12 @@ public final class app/revanced/patches/music/audio/codecs/CodecsUnlockPatch : a
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -310,6 +338,12 @@ public final class app/revanced/patches/music/interaction/permanentrepeat/Perman
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -322,6 +356,12 @@ public final class app/revanced/patches/music/layout/compactheader/CompactHeader
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/layout/compactheader/HideCategoryBar : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/layout/compactheader/HideCategoryBar;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -406,6 +446,12 @@ public final class app/revanced/patches/nyx/misc/pro/UnlockProPatch : app/revanc
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -471,6 +517,13 @@ public final class app/revanced/patches/reddit/customclients/Constants {
public static final field OAUTH_USER_AGENT Ljava/lang/String;
}
public abstract class app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public fun <init> (Ljava/util/Set;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch;
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -526,10 +579,12 @@ public final class app/revanced/patches/reddit/customclients/slide/api/SpoofClie
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public final class app/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch : app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch;
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch : app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/DisableSyncForLemmyBottomSheetPatch : app/revanced/patcher/patch/BytecodePatch {
@@ -550,6 +605,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/detec
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -599,6 +660,7 @@ public abstract class app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportRes
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
protected final fun getGmsCoreVendor ()Ljava/lang/String;
protected final fun getGmsCoreVendorGroupId ()Ljava/lang/String;
}
public abstract class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch : app/revanced/patcher/patch/BytecodePatch {
@@ -612,9 +674,19 @@ public abstract class app/revanced/patches/shared/misc/integrations/BaseIntegrat
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun invoke (Ljava/lang/String;)V
}
public abstract interface class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver : kotlin/jvm/functions/Function1 {
public abstract fun invoke (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer;
}
public final class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver$DefaultImpls {
public static fun invoke (Lapp/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver;Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer;
}
public abstract interface class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IRegisterResolver : kotlin/jvm/functions/Function1 {
public abstract fun invoke (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer;
}
@@ -707,10 +779,8 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
}
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;)V
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
public final fun getCategories ()Ljava/util/Set;
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
@@ -782,12 +852,22 @@ public class app/revanced/patches/shared/misc/settings/preference/PreferenceCate
}
public class app/revanced/patches/shared/misc/settings/preference/PreferenceScreen : app/revanced/patches/shared/misc/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getPreferences ()Ljava/util/Set;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
public final class app/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting : java/lang/Enum {
public static final field BY_KEY Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
public static final field BY_TITLE Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
public static final field UNSORTED Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getKeySuffix ()Ljava/lang/String;
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
public static fun values ()[Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen$Sorting;
}
public final class app/revanced/patches/shared/misc/settings/preference/SummaryType : java/lang/Enum {
public static final field DEFAULT Lapp/revanced/patches/shared/misc/settings/preference/SummaryType;
public static final field OFF Lapp/revanced/patches/shared/misc/settings/preference/SummaryType;
@@ -976,6 +1056,12 @@ public final class app/revanced/patches/tumblr/featureflags/OverrideFeatureFlags
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/tumblr/fixes/FixOldVersionsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/tumblr/fixes/FixOldVersionsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/tumblr/live/DisableTumblrLivePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/tumblr/live/DisableTumblrLivePatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1065,6 +1151,18 @@ public final class app/revanced/patches/twitch/misc/settings/SettingsResourcePat
public static final field INSTANCE Lapp/revanced/patches/twitch/misc/settings/SettingsResourcePatch;
}
public final class app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/twitter/layout/viewcount/HideViewCountPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/twitter/layout/viewcount/HideViewCountPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
@@ -1092,6 +1190,12 @@ public final class app/revanced/patches/twitter/misc/hook/patch/recommendation/H
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch;
}
public final class app/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/vsco/misc/pro/UnlockProPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1152,8 +1256,8 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch;
public final class app/revanced/patches/youtube/interaction/downloads/DownloadsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/DownloadsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
@@ -1420,6 +1524,10 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint;
}
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1430,7 +1538,6 @@ public final class app/revanced/patches/youtube/layout/tabletminiplayer/TabletMi
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
public final fun unwrap (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lkotlin/Triple;
}
public final class app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
@@ -1469,10 +1576,12 @@ public final class app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDevic
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch : app/revanced/patcher/patch/BytecodePatch {
public final class app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Lkotlin/Triple;
public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Triple;)V
}
public final class app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch : app/revanced/patcher/patch/BytecodePatch {
@@ -1530,6 +1639,13 @@ public final class app/revanced/patches/youtube/misc/minimizedplayback/Minimized
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
public final fun getHookNavigationButtonCreated ()Lkotlin/jvm/functions/Function1;
}
public final class app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch;
public final fun addControls (Ljava/lang/String;)V
@@ -1579,9 +1695,14 @@ public final class app/revanced/patches/youtube/misc/settings/SettingsPatch$Pref
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/settings/SettingsPatch$PreferenceScreen;
public fun commit (Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreen;)V
public final fun getADS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getINTERACTIONS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getLAYOUT ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getALTERNATIVE_THUMBNAILS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getFEED ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getGENERAL_LAYOUT ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getMISC ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getPLAYER ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getSEEKBAR ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getSHORTS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getSWIPE_CONTROLS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getVIDEO ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
}
@@ -1698,6 +1819,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I
public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
public static final fun returnEarly (Ljava/util/List;Z)V
public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V

View File

@@ -1,9 +1,11 @@
import org.gradle.kotlin.dsl.support.listFilesOrdered
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
kotlin("jvm") version "1.9.22"
alias(libs.plugins.kotlin)
alias(libs.plugins.binary.compatibility.validator)
`maven-publish`
signing
}
group = "app.revanced"
@@ -12,7 +14,14 @@ repositories {
mavenCentral()
mavenLocal()
google()
maven { url = uri("https://jitpack.io") }
maven {
// A repository must be specified for some reason. "registry" is a dummy.
url = uri("https://maven.pkg.github.com/revanced/registry")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
}
}
}
dependencies {
@@ -22,34 +31,38 @@ 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"))
}
kotlin {
jvmToolchain(11)
}
tasks.withType(Jar::class) {
exclude("app/revanced/meta")
manifest {
attributes["Name"] = "ReVanced Patches"
attributes["Description"] = "Patches for ReVanced."
attributes["Version"] = version
attributes["Timestamp"] = System.currentTimeMillis().toString()
attributes["Source"] = "git@github.com:revanced/revanced-patches.git"
attributes["Author"] = "ReVanced"
attributes["Contact"] = "contact@revanced.app"
attributes["Origin"] = "https://revanced.app"
attributes["License"] = "GNU General Public License v3.0"
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
java {
targetCompatibility = JavaVersion.VERSION_11
}
tasks {
register<DefaultTask>("generateBundle") {
description = "Generate DEX files and add them in the JAR file"
withType(Jar::class) {
exclude("app/revanced/meta")
manifest {
attributes["Name"] = "ReVanced Patches"
attributes["Description"] = "Patches for ReVanced."
attributes["Version"] = version
attributes["Timestamp"] = System.currentTimeMillis().toString()
attributes["Source"] = "git@github.com:revanced/revanced-patches.git"
attributes["Author"] = "ReVanced"
attributes["Contact"] = "contact@revanced.app"
attributes["Origin"] = "https://revanced.app"
attributes["License"] = "GNU General Public License v3.0"
}
}
register("buildDexJar") {
description = "Build and add a DEX to the JAR file"
group = "build"
dependsOn(build)
@@ -57,39 +70,50 @@ tasks {
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 patchesJar = configurations.archives.get().allArtifacts.files.files.first().absolutePath
val workingDirectory = layout.buildDirectory.dir("libs").get().asFile
exec {
workingDir = workingDirectory
commandLine = listOf(d8, artifacts)
commandLine = listOf(d8, "--release", patchesJar)
}
exec {
workingDir = workingDirectory
commandLine = listOf("zip", "-u", artifacts, "classes.dex")
commandLine = listOf("zip", "-u", patchesJar, "classes.dex")
}
}
}
register<JavaExec>("generateMeta") {
description = "Generate metadata for this bundle"
register<JavaExec>("generatePatchesFiles") {
description = "Generate patches files"
dependsOn(build)
classpath = sourceSets["main"].runtimeClasspath
mainClass.set("app.revanced.meta.IPatchesFileGenerator")
mainClass.set("app.revanced.generator.MainKt")
}
// Required to run tasks because Gradle semantic-release plugin runs the publish task.
// Needed by gradle-semantic-release-plugin.
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
named("publish") {
dependsOn("generateBundle")
dependsOn("generateMeta")
publish {
dependsOn("buildDexJar")
dependsOn("generatePatchesFiles")
}
}
publishing {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/revanced/revanced-patches")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
create<MavenPublication>("revanced-patches-publication") {
from(components["java"])
@@ -120,4 +144,10 @@ publishing {
}
}
}
}
}
signing {
useGpgCmd()
sign(publishing.publications["revanced-patches-publication"])
}

8
crowdin.yml Normal file
View File

@@ -0,0 +1,8 @@
project_id_env: "CROWDIN_PROJECT_ID"
api_token_env: "CROWDIN_PERSONAL_TOKEN"
preserve_hierarchy: false
files:
- source: src/main/resources/addresources/values/strings.xml
translation: src/main/resources/addresources/values-%android_code%/strings.xml
skip_untranslated_strings: true

View File

@@ -1,9 +0,0 @@
plugins {
id("java")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}

View File

@@ -1,9 +0,0 @@
package android.os;
import java.io.File;
public final class Environment {
public static File getExternalStorageDirectory() {
throw new UnsupportedOperationException("Stub");
}
}

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 4.0.3-dev.2
version = 4.7.0-dev.3

View File

@@ -1,9 +1,10 @@
[versions]
revanced-patcher = "19.2.0"
smali = "3.0.3"
revanced-patcher = "19.3.1"
smali = "3.0.5"
guava = "33.0.0-jre"
gson = "2.10.1"
binary-compatibility-validator = "0.13.2"
binary-compatibility-validator = "0.14.0"
kotlin = "1.9.22"
[libraries]
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
@@ -13,3 +14,4 @@ gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
[plugins]
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }

View File

@@ -1,8 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dist

280
package-lock.json generated
View File

@@ -9,7 +9,7 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.9.1",
"semantic-release": "^23.0.0"
"semantic-release": "^23.0.2"
}
},
"node_modules/@babel/code-frame": {
@@ -326,9 +326,9 @@
}
},
"node_modules/@octokit/request": {
"version": "8.1.6",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz",
"integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.2.0.tgz",
"integrity": "sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==",
"dev": true,
"dependencies": {
"@octokit/endpoint": "^9.0.0",
@@ -564,6 +564,26 @@
"node": ">= 16"
}
},
"node_modules/@saithodev/semantic-release-backmerge/node_modules/marked-terminal": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz",
"integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==",
"dev": true,
"dependencies": {
"ansi-escapes": "^6.2.0",
"cardinal": "^2.1.1",
"chalk": "^5.3.0",
"cli-table3": "^0.6.3",
"node-emoji": "^2.1.3",
"supports-hyperlinks": "^3.0.0"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"marked": ">=1 <12"
}
},
"node_modules/@saithodev/semantic-release-backmerge/node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
@@ -1195,9 +1215,9 @@
}
},
"node_modules/@sindresorhus/merge-streams": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz",
"integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.2.0.tgz",
"integrity": "sha512-UTce8mUwUW0RikMb/eseJ7ys0BRkZVFB86orHzrfW12ZmFtym5zua8joZ4L7okH2dDFHkcFjqnZ5GocWBXOFtA==",
"dev": true,
"engines": {
"node": ">=18"
@@ -1282,6 +1302,12 @@
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
"dev": true
},
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
"dev": true
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -1376,6 +1402,81 @@
"node": ">=6"
}
},
"node_modules/cli-highlight": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
"integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
"highlight.js": "^10.7.1",
"mz": "^2.4.0",
"parse5": "^5.1.1",
"parse5-htmlparser2-tree-adapter": "^6.0.0",
"yargs": "^16.0.0"
},
"bin": {
"highlight": "bin/highlight"
},
"engines": {
"node": ">=8.0.0",
"npm": ">=5.0.0"
}
},
"node_modules/cli-highlight/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/cli-highlight/node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"node_modules/cli-highlight/node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/cli-highlight/node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/cli-table3": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
@@ -1818,9 +1919,9 @@
}
},
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"dev": true,
"engines": {
"node": ">=6"
@@ -1888,9 +1989,9 @@
}
},
"node_modules/fastq": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
"integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
"dev": true,
"dependencies": {
"reusify": "^1.0.4"
@@ -2052,12 +2153,12 @@
}
},
"node_modules/globby": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz",
"integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==",
"version": "14.0.1",
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz",
"integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==",
"dev": true,
"dependencies": {
"@sindresorhus/merge-streams": "^1.0.0",
"@sindresorhus/merge-streams": "^2.1.0",
"fast-glob": "^3.3.2",
"ignore": "^5.2.4",
"path-type": "^5.0.0",
@@ -2142,9 +2243,9 @@
}
},
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
"integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
@@ -2153,6 +2254,15 @@
"node": ">= 0.4"
}
},
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
"dev": true,
"engines": {
"node": "*"
}
},
"node_modules/hook-std": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz",
@@ -2178,9 +2288,9 @@
}
},
"node_modules/http-proxy-agent": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz",
"integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==",
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.1.tgz",
"integrity": "sha512-My1KCEPs6A0hb4qCVzYp8iEvA8j8YqcvXLZZH8C9OFuTYpYjHE7N2dtG3mRl1HMD4+VGXpF3XcDVcxGBT7yDZQ==",
"dev": true,
"dependencies": {
"agent-base": "^7.1.0",
@@ -2191,9 +2301,9 @@
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
"integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.3.tgz",
"integrity": "sha512-kCnwztfX0KZJSLOBrcL0emLeFako55NWMovvyPP2AjsghNk9RB1yjSI+jVumPHYZsNXegNoqupSW9IY3afSH8w==",
"dev": true,
"dependencies": {
"agent-base": "^7.0.2",
@@ -2213,9 +2323,9 @@
}
},
"node_modules/ignore": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"dev": true,
"engines": {
"node": ">= 4"
@@ -2629,9 +2739,9 @@
}
},
"node_modules/marked": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz",
"integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==",
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz",
"integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==",
"dev": true,
"bin": {
"marked": "bin/marked.js"
@@ -2641,14 +2751,14 @@
}
},
"node_modules/marked-terminal": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz",
"integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.0.0.tgz",
"integrity": "sha512-sNEx8nn9Ktcm6pL0TnRz8tnXq/mSS0Q1FRSwJOAqw4lAB4l49UeDf85Gm1n9RPFm5qurCPjwi1StAQT2XExhZw==",
"dev": true,
"dependencies": {
"ansi-escapes": "^6.2.0",
"cardinal": "^2.1.1",
"chalk": "^5.3.0",
"cli-highlight": "^2.1.11",
"cli-table3": "^0.6.3",
"node-emoji": "^2.1.3",
"supports-hyperlinks": "^3.0.0"
@@ -2657,7 +2767,7 @@
"node": ">=16.0.0"
},
"peerDependencies": {
"marked": ">=1 <12"
"marked": ">=1 <13"
}
},
"node_modules/meow": {
@@ -2739,6 +2849,17 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"dev": true,
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
"thenify-all": "^1.0.0"
}
},
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
@@ -5551,6 +5672,15 @@
"inBundle": true,
"license": "ISC"
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -5695,6 +5825,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse5": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
"dev": true
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
"dev": true,
"dependencies": {
"parse5": "^6.0.1"
}
},
"node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
"dev": true
},
"node_modules/parsimmon": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.18.1.tgz",
@@ -5860,9 +6011,9 @@
}
},
"node_modules/read-pkg-up/node_modules/type-fest": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.1.tgz",
"integrity": "sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==",
"version": "4.10.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
"dev": true,
"engines": {
"node": ">=16"
@@ -5889,9 +6040,9 @@
}
},
"node_modules/read-pkg/node_modules/type-fest": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.1.tgz",
"integrity": "sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==",
"version": "4.10.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
"dev": true,
"engines": {
"node": ">=16"
@@ -5994,9 +6145,9 @@
"dev": true
},
"node_modules/semantic-release": {
"version": "23.0.0",
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.0.tgz",
"integrity": "sha512-Jz7jEWO2igTtske112gC4PPE2whCMVrsgxUPG3/SZI7VE357suIUZFlJd1Yu0g2I6RPc2HxNEfUg7KhmDTjwqg==",
"version": "23.0.2",
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.2.tgz",
"integrity": "sha512-OnVYJ6Xgzwe1x8MKswba7RU9+5djS1MWRTrTn5qsq3xZYpslroZkV9Pt0dA2YcIuieeuSZWJhn+yUWoBUHO5Fw==",
"dev": true,
"dependencies": {
"@semantic-release/commit-analyzer": "^11.0.0",
@@ -6017,8 +6168,8 @@
"hosted-git-info": "^7.0.0",
"import-from-esm": "^1.3.1",
"lodash-es": "^4.17.21",
"marked": "^11.0.0",
"marked-terminal": "^6.0.0",
"marked": "^12.0.0",
"marked-terminal": "^7.0.0",
"micromatch": "^4.0.2",
"p-each-series": "^3.0.0",
"p-reduce": "^3.0.0",
@@ -6247,9 +6398,9 @@
}
},
"node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@@ -6481,9 +6632,9 @@
}
},
"node_modules/spdx-license-ids": {
"version": "3.0.16",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
"integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
"version": "3.0.17",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
"integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
"dev": true
},
"node_modules/split2": {
@@ -6655,6 +6806,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
"dev": true,
"dependencies": {
"any-promise": "^1.0.0"
}
},
"node_modules/thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",

View File

@@ -4,6 +4,6 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.9.1",
"semantic-release": "^23.0.0"
"semantic-release": "^23.0.2"
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,3 @@
include("dummy")
rootProject.name = "revanced-patches"
buildCache {

View File

@@ -1,11 +1,11 @@
package app.revanced.meta
package app.revanced.generator
import app.revanced.patcher.PatchSet
import app.revanced.patcher.patch.Patch
import com.google.gson.GsonBuilder
import java.io.File
internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
internal class JsonPatchesFileGenerator : PatchesFileGenerator {
override fun generate(patches: PatchSet) = patches.map {
JsonPatch(
it.name!!,
@@ -20,9 +20,9 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
option.values,
option.title,
option.description,
option.required
option.required,
)
}
},
)
}.let {
File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it))
@@ -35,7 +35,7 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
val compatiblePackages: Set<Patch.CompatiblePackage>? = null,
val use: Boolean = true,
val requiresIntegrations: Boolean = false,
val options: List<Option>
val options: List<Option>,
) {
class Option(
val key: String,
@@ -46,4 +46,4 @@ internal class JsonPatchesFileGenerator : IPatchesFileGenerator {
val required: Boolean,
)
}
}
}

View File

@@ -0,0 +1,12 @@
package app.revanced.generator
import app.revanced.patcher.PatchBundleLoader
import java.io.File
internal fun main() = PatchBundleLoader.Jar(
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first(),
).also { loader ->
if (loader.isEmpty()) throw IllegalStateException("No patches found")
}.let { bundle ->
arrayOf(JsonPatchesFileGenerator()).forEach { generator -> generator.generate(bundle) }
}

View File

@@ -0,0 +1,7 @@
package app.revanced.generator
import app.revanced.patcher.PatchSet
internal interface PatchesFileGenerator {
fun generate(patches: PatchSet)
}

View File

@@ -1,20 +0,0 @@
package app.revanced.meta
import app.revanced.patcher.PatchBundleLoader
import app.revanced.patcher.PatchSet
import java.io.File
internal interface IPatchesFileGenerator {
fun generate(patches: PatchSet)
private companion object {
@JvmStatic
fun main(args: Array<String>) = PatchBundleLoader.Jar(
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first()
).also { loader ->
if (loader.isEmpty()) throw IllegalStateException("No patches found")
}.let { bundle ->
arrayOf(JsonPatchesFileGenerator()).forEach { generator -> generator.generate(bundle) }
}
}
}

View File

@@ -7,29 +7,34 @@ import app.revanced.patcher.patch.annotation.Patch
@Patch(
name = "Export all activities",
description = "Makes all app activities exportable.",
use = false
use = false,
)
@Suppress("unused")
object ExportAllActivitiesPatch : ResourcePatch() {
private const val EXPORTED_FLAG = "android:exported"
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
val activities = document.getElementsByTagName("activity")
for(i in 0..activities.length) {
for (i in 0..activities.length) {
activities.item(i)?.apply {
val exportedAttribute = attributes.getNamedItem(EXPORTED_FLAG)
if (exportedAttribute != null) {
if (exportedAttribute.nodeValue != "true")
if (exportedAttribute.nodeValue != "true") {
exportedAttribute.nodeValue = "true"
}
}
// Reason why the attribute is added in the case it does not exist:
// https://github.com/revanced/revanced-patches/pull/1751/files#r1141481604
else document.createAttribute(EXPORTED_FLAG)
.apply { value = "true" }
.let(attributes::setNamedItem)
else {
document.createAttribute(EXPORTED_FLAG)
.apply { value = "true" }
.let(attributes::setNamedItem)
}
}
}
}

View File

@@ -7,7 +7,7 @@ import app.revanced.patcher.patch.annotation.Patch
@Patch(
name = "Predictive back gesture",
description = "Enables the predictive back gesture introduced on Android 13.",
use = false
use = false,
)
@Suppress("unused")
object PredictiveBackGesturePatch : ResourcePatch() {

View File

@@ -8,16 +8,18 @@ import org.w3c.dom.Element
@Patch(
name = "Enable Android debugging",
description = "Enables Android debugging capabilities. This can slow down the app.",
use = false
use = false,
)
@Suppress("unused")
object EnableAndroidDebuggingPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { dom ->
val applicationNode = dom
.file
.getElementsByTagName("application")
.item(0) as Element
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
val applicationNode =
document
.getElementsByTagName("application")
.item(0) as Element
// set application as debuggable
applicationNode.setAttribute("android:debuggable", "true")

View File

@@ -4,6 +4,7 @@ import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch
import app.revanced.util.Utils.trimIndentMultiline
import org.w3c.dom.Element
import java.io.File
@@ -11,16 +12,17 @@ import java.io.File
name = "Override certificate pinning",
description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
dependencies = [EnableAndroidDebuggingPatch::class],
use = false
use = false,
)
@Suppress("unused")
object OverrideCertificatePinningPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
val resXmlDirectory = context["res/xml"]
val resXmlDirectory = context.get("res/xml")
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
val applicationNode = document.getElementsByTagName("application").item(0) as Element
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
@@ -31,10 +33,8 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
// In case the file does not exist create the "network_security_config.xml" file.
File(resXmlDirectory, "network_security_config.xml").apply {
if (!exists()) {
createNewFile()
writeText(
"""
writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
@@ -54,22 +54,8 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
</trust-anchors>
</debug-overrides>
</network-security-config>
"""
)
} else {
// If the file already exists.
readText().let { text ->
if (!text.contains("<certificates src=\"user\" />")) {
writeText(
text.replace(
"<trust-anchors>",
"<trust-anchors>\n<certificates src=\"user\" overridePins=\"true\" />\n<certificates src=\"system\" />"
)
)
}
}
}
""".trimIndentMultiline(),
)
}
}
}

View File

@@ -11,20 +11,21 @@ import java.io.Closeable
@Patch(
name = "Change package name",
description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.",
use = false
use = false,
)
@Suppress("unused")
object ChangePackageNamePatch : ResourcePatch(), Closeable {
private val packageNameOption = stringPatchOption(
key = "packageName",
default = "Default",
values = mapOf("Default" to "Default"),
title = "Package name",
description = "The name of the package to rename the app to.",
required = true
) {
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
}
private val packageNameOption =
stringPatchOption(
key = "packageName",
default = "Default",
values = mapOf("Default" to "Default"),
title = "Package name",
description = "The name of the package to rename the app to.",
required = true,
) {
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
}
private lateinit var context: ResourceContext
@@ -43,20 +44,27 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
val packageName = packageNameOption.value!!
return if (packageName == packageNameOption.default)
return if (packageName == packageNameOption.default) {
fallbackPackageName.also { packageNameOption.value = it }
else
} else {
packageName
}
}
override fun close() = context.xmlEditor["AndroidManifest.xml"].use { editor ->
val replacementPackageName = packageNameOption.value
override fun close() =
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
manifest.setAttribute(
"package",
if (replacementPackageName != packageNameOption.default) replacementPackageName
else "${manifest.getAttribute("package")}.revanced"
)
}
val replacementPackageName = packageNameOption.value
val manifest = document.getElementsByTagName("manifest").item(0) as Element
manifest.setAttribute(
"package",
if (replacementPackageName != packageNameOption.default) {
replacementPackageName
} else {
"${manifest.getAttribute("package")}.revanced"
},
)
}
}

View File

@@ -19,6 +19,7 @@ import java.util.*
* An identifier of an app. For example, `youtube`.
*/
private typealias AppId = String
/**
* An identifier of a patch. For example, `ad.general.HideAdsPatch`.
*/
@@ -28,10 +29,12 @@ private typealias PatchId = String
* A set of resources of a patch.
*/
private typealias PatchResources = MutableSet<BaseResource>
/**
* A map of resources belonging to a patch.
*/
private typealias AppResources = MutableMap<PatchId, PatchResources>
/**
* A map of resources belonging to an app.
*/
@@ -67,40 +70,44 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
override fun execute(context: ResourceContext) {
this.context = context
resources = buildMap {
/**
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
*
* @param value The value of the resource. For example, `values` or `values-de`.
* @param resourceKind The kind of the resource. For example, `strings` or `arrays`.
* @param transform A function that transforms the [Node]s from the XML files to a [BaseResource].
*/
fun addResources(
value: Value,
resourceKind: String,
transform: (Node) -> BaseResource,
) {
inputStreamFromBundledResource(
"addresources",
"$value/$resourceKind.xml"
)?.let { stream ->
// Add the resources associated with the given value to the map,
// instead of overwriting it.
// This covers the example case such as adding strings and arrays of the same value.
getOrPut(value, ::mutableMapOf).apply {
context.xmlEditor[stream].use {
it.file.getElementsByTagName("app").asSequence().forEach { app ->
val appId = app.attributes.getNamedItem("id").textContent
resources =
buildMap {
/**
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
*
* @param value The value of the resource. For example, `values` or `values-de`.
* @param resourceKind The kind of the resource. For example, `strings` or `arrays`.
* @param transform A function that transforms the [Node]s from the XML files to a [BaseResource].
*/
fun addResources(
value: Value,
resourceKind: String,
transform: (Node) -> BaseResource,
) {
inputStreamFromBundledResource(
"addresources",
"$value/$resourceKind.xml",
)?.let { stream ->
// Add the resources associated with the given value to the map,
// instead of overwriting it.
// This covers the example case such as adding strings and arrays of the same value.
getOrPut(value, ::mutableMapOf).apply {
context.xmlEditor[stream].use { editor ->
val document = editor.file
getOrPut(appId, ::mutableMapOf).apply {
app.forEachChildElement { patch ->
val patchId = patch.attributes.getNamedItem("id").textContent
document.getElementsByTagName("app").asSequence().forEach { app ->
val appId = app.attributes.getNamedItem("id").textContent
getOrPut(patchId, ::mutableSetOf).apply {
patch.forEachChildElement { resourceNode ->
val resource = transform(resourceNode)
getOrPut(appId, ::mutableMapOf).apply {
app.forEachChildElement { patch ->
val patchId = patch.attributes.getNamedItem("id").textContent
add(resource)
getOrPut(patchId, ::mutableSetOf).apply {
patch.forEachChildElement { resourceNode ->
val resource = transform(resourceNode)
add(resource)
}
}
}
}
@@ -109,23 +116,22 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
}
}
}
}
// Stage all resources to a temporary map.
// Staged resources consumed by AddResourcesPatch#invoke(PatchClass)
// are later used in AddResourcesPatch#close.
try {
val addStringResources = { value: Value ->
addResources(value, "strings", StringResource::fromNode)
// Stage all resources to a temporary map.
// Staged resources consumed by AddResourcesPatch#invoke(PatchClass)
// are later used in AddResourcesPatch#close.
try {
val addStringResources = { value: Value ->
addResources(value, "strings", StringResource::fromNode)
}
Locale.getISOLanguages().asSequence().map { "values-$it" }.forEach { addStringResources(it) }
addStringResources("values")
addResources("values", "arrays", ArrayResource::fromNode)
} catch (e: Exception) {
throw PatchException("Failed to read resources", e)
}
Locale.getISOLanguages().asSequence().map { "values-$it" }.forEach { addStringResources(it) }
addStringResources("values")
addResources("values", "arrays", ArrayResource::fromNode)
} catch (e: Exception) {
throw PatchException("Failed to read resources", e)
}
}
}
/**
@@ -136,8 +142,10 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
*
* @return True if the resource was added, false if it already existed.
*/
operator fun invoke(value: Value, resource: BaseResource) =
getOrPut(value, ::mutableSetOf).add(resource)
operator fun invoke(
value: Value,
resource: BaseResource,
) = getOrPut(value, ::mutableSetOf).add(resource)
/**
* Adds a list of [BaseResource]s to the map using [MutableMap.getOrPut].
@@ -147,8 +155,10 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
*
* @return True if the resources were added, false if they already existed.
*/
operator fun invoke(value: Value, resources: Iterable<BaseResource>) =
getOrPut(value, ::mutableSetOf).addAll(resources)
operator fun invoke(
value: Value,
resources: Iterable<BaseResource>,
) = getOrPut(value, ::mutableSetOf).addAll(resources)
/**
* Adds a [StringResource].
@@ -177,10 +187,9 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
*/
operator fun invoke(
name: String,
items: List<String>
items: List<String>,
) = invoke("values", ArrayResource(name, items))
/**
* Puts all resources of any [Value] staged in [resources] for the given [PatchClass] to [AddResourcesPatch].
*
@@ -209,7 +218,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
appId to patchId
}
}
},
): Boolean {
val (appId, patchId) = patch.parseIds()
@@ -218,7 +227,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
// Stage resources for the given patch to AddResourcesPatch associated with their value.
resources.forEach { (value, resources) ->
resources[appId]?.get(patchId)?.let { patchResources ->
if (invoke(value, patchResources)) result = true
if (invoke(value, patchResources)) result = true
}
}
@@ -232,28 +241,32 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
override fun close() {
operator fun MutableMap<String, Pair<DomFileEditor, Node>>.invoke(
value: Value,
resource: BaseResource
resource: BaseResource,
) {
// TODO: Fix open-closed principle violation by modifying BaseResource#serialize so that it accepts
// a Value and the map of editors. It will then get or put the editor suitable for its resource type
// a Value and the map of documents. It will then get or put the document suitable for its resource type
// to serialize itself to it.
val resourceFileName = when (resource) {
is StringResource -> "strings"
is ArrayResource -> "arrays"
else -> throw NotImplementedError("Unsupported resource type")
}
getOrPut(resourceFileName) {
val targetFile = context["res/$value/$resourceFileName.xml"].also {
it.parentFile?.mkdirs()
it.createNewFile()
val resourceFileName =
when (resource) {
is StringResource -> "strings"
is ArrayResource -> "arrays"
else -> throw NotImplementedError("Unsupported resource type")
}
getOrPut(resourceFileName) {
val targetFile =
context.get("res/$value/$resourceFileName.xml").also {
it.parentFile?.mkdirs()
it.createNewFile()
}
context.xmlEditor[targetFile.path].let { editor ->
val document = editor.file
// Save the target node here as well
// in order to avoid having to call editor.getNode("resources")
// every time addUsingEditors is called but also save the editor so that it can be closed later.
editor to editor.getNode("resources")
// in order to avoid having to call document.getNode("resources")
// but also save the document so that it can be closed later.
editor to document.getNode("resources")
}
}.let { (_, targetNode) ->
targetNode.addResource(resource) { invoke(value, it) }
@@ -261,17 +274,17 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
}
forEach { (value, resources) ->
// A map of editors associated by their kind (e.g. strings, arrays).
// Each editor is accompanied by the target node to which resources are added.
// A map is used because Map#getOrPut allows opening a new editor for the duration of a resource value.
// A map of document associated by their kind (e.g. strings, arrays).
// Each document is accompanied by the target node to which resources are added.
// A map is used because Map#getOrPut allows opening a new document for the duration of a resource value.
// This is done to prevent having to open the files for every resource that is added.
// Instead, it is cached once and reused for resources of the same value.
// This map is later accessed to close all editors for the current resource value.
val resourceFileEditors = mutableMapOf<String, Pair<DomFileEditor, Node>>()
// This map is later accessed to close all documents for the current resource value.
val documents = mutableMapOf<String, Pair<DomFileEditor, Node>>()
resources.forEach { resource -> resourceFileEditors(value, resource) }
resources.forEach { resource -> documents(value, resource) }
resourceFileEditors.values.forEach { (editor, _) -> editor.close() }
documents.values.forEach { (document, _) -> document.close() }
}
}
}

View File

@@ -9,12 +9,12 @@ import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@Suppress("MemberVisibilityCanBePrivate")
abstract class BaseTransformInstructionsPatch<T> : BytecodePatch() {
abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
abstract fun filterMap(
classDef: ClassDef,
method: Method,
instruction: Instruction,
instructionIndex: Int
instructionIndex: Int,
): T?
abstract fun transform(mutableMethod: MutableMethod, entry: T)

View File

@@ -8,16 +8,17 @@ import org.w3c.dom.Element
@Patch(description = "Sets allowAudioPlaybackCapture in manifest to true.")
internal object RemoveCaptureRestrictionResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
// create an xml editor instance
context.xmlEditor["AndroidManifest.xml"].use { dom ->
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
// get the application node
val applicationNode = dom
.file
.getElementsByTagName("application")
.item(0) as Element
val applicationNode =
document
.getElementsByTagName("application")
.item(0) as Element
// set allowAudioPlaybackCapture attribute to true
applicationNode.setAttribute("android:allowAudioPlaybackCapture", "true")
}
}
}
}

View File

@@ -1,102 +1,63 @@
package app.revanced.patches.instagram.patches.ads.timeline
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
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.instagram.patches.ads.timeline.fingerprints.MediaFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckOneFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckTwoFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.GenericMediaAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide timeline ads",
description = "Removes ads from the timeline.",
compatiblePackages = [CompatiblePackage("com.instagram.android", ["275.0.0.27.98"])]
compatiblePackages = [CompatiblePackage("com.instagram.android")],
)
@Suppress("unused")
object HideTimelineAdsPatch : BytecodePatch(
setOf(
ShowAdFingerprint,
MediaFingerprint,
PaidPartnershipAdFingerprint // Unlike the other ads this one is resolved from all classes.
)
IsAdCheckOneFingerprint,
IsAdCheckTwoFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
// region Resolve required methods to check for ads.
// The exact function of the following methods is unknown.
// They are used to check if a post is an ad.
val isAdCheckOneMethod = IsAdCheckOneFingerprint.result?.method ?: throw IsAdCheckOneFingerprint.exception
val isAdCheckTwoMethod = IsAdCheckTwoFingerprint.result?.method ?: throw IsAdCheckTwoFingerprint.exception
ShowAdFingerprint.result ?: throw ShowAdFingerprint.exception
ShowAdFingerprint.result?.let {
it.mutableMethod.apply {
// The register that holds the post object.
val postRegister = getInstruction<FiveRegisterInstruction>(1).registerC
PaidPartnershipAdFingerprint.result ?: throw PaidPartnershipAdFingerprint.exception
// At this index the check for an ad can be performed.
val checkIndex = it.scanResult.patternScanResult!!.endIndex
MediaFingerprint.result?.let {
GenericMediaAdFingerprint.resolve(context, it.classDef)
ShoppingAdFingerprint.resolve(context, it.classDef)
return@let
} ?: throw MediaFingerprint.exception
// endregion
ShowAdFingerprint.result!!.apply {
// region Create instructions.
val scanStart = scanResult.patternScanResult!!.startIndex
val jumpIndex = scanStart - 1
val mediaInstanceRegister = mutableMethod.getInstruction<FiveRegisterInstruction>(scanStart).registerC
val freeRegister = mutableMethod.getInstruction<OneRegisterInstruction>(jumpIndex).registerA
val returnFalseLabel = "an_ad"
val checkForAdInstructions =
listOf(GenericMediaAdFingerprint, PaidPartnershipAdFingerprint, ShoppingAdFingerprint)
.map(MediaAdFingerprint::toString)
.joinToString("\n") {
"""
invoke-virtual {v$mediaInstanceRegister}, $it
move-result v$freeRegister
if-nez v$freeRegister, :$returnFalseLabel
""".trimIndent()
}.let { "$it\nconst/4 v0, 0x1\nreturn v0" }
// endregion
// region Patch.
val insertIndex = scanStart + 3
mutableMethod.addInstructionsWithLabels(
insertIndex,
checkForAdInstructions,
ExternalLabel(
returnFalseLabel,
mutableMethod.getInstruction(mutableMethod.implementation!!.instructions.size - 2 /* return false = ad */)
)
)
// endregion
// region Jump to checks for ads from previous patch.
mutableMethod.apply {
// If either check returns true, the post is an ad and is hidden by returning false.
addInstructionsWithLabels(
jumpIndex + 1,
"if-nez v$freeRegister, :start_check",
ExternalLabel("start_check", getInstruction(insertIndex))
checkIndex,
"""
invoke-virtual { v$postRegister }, $isAdCheckOneMethod
move-result v0
if-nez v0, :hide_ad
invoke-static { v$postRegister }, $isAdCheckTwoMethod
move-result v0
if-eqz v0, :not_an_ad
:hide_ad
const/4 v0, 0x0 # Returning false to hide the ad.
return v0
""",
ExternalLabel("not_an_ad", getInstruction(checkIndex)),
)
}.removeInstruction(jumpIndex)
// endregion
}
}
} ?: throw ShowAdFingerprint.exception
}
}
}

View File

@@ -0,0 +1,18 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object IsAdCheckOneFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
opcodes = listOf(
Opcode.XOR_INT_LIT8,
Opcode.IF_NE,
Opcode.RETURN,
Opcode.INVOKE_VIRTUAL,
),
)

View File

@@ -1,8 +1,14 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object GenericMediaAdFingerprint : MediaAdFingerprint(
internal object IsAdCheckTwoFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
@@ -12,7 +18,5 @@ internal object GenericMediaAdFingerprint : MediaAdFingerprint(
Opcode.IF_EQZ,
Opcode.CONST_4,
Opcode.RETURN,
)
) {
override fun toString() = result!!.method.toString()
}
),
)

View File

@@ -1,7 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object MediaFingerprint : MethodFingerprint(
strings = listOf("force_overlay", "Media#updateFields", "live_reels_metadata")
)

View File

@@ -10,16 +10,12 @@ internal object ShowAdFingerprint : MethodFingerprint(
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
listOf("L", "L", "Z", "Z"),
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.IF_NE,
Opcode.IF_NEZ,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.RETURN,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
),
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
internal abstract class MediaAdFingerprint(
returnType: String? = "Z",
accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters: Iterable<String>? = listOf(),
opcodes: Iterable<Opcode>?,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
) : MethodFingerprint(
returnType,
accessFlags,
parameters,
opcodes,
customFingerprint = customFingerprint
) {
abstract override fun toString(): String
}

View File

@@ -1,29 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object PaidPartnershipAdFingerprint : MediaAdFingerprint(
"V",
null,
listOf("L", "L"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IPUT_BOOLEAN,
Opcode.IPUT_BOOLEAN
),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("ClipsEditMetadataController;")
}
) {
override fun toString() = result!!.let {
val adCheckIndex = it.scanResult.patternScanResult!!.startIndex
val adCheckInstruction = it.method.implementation!!.instructions.elementAt(adCheckIndex)
val adCheckMethod = (adCheckInstruction as ReferenceInstruction).reference as MethodReference
adCheckMethod.toString()
}
}

View File

@@ -1,21 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode
internal object ShoppingAdFingerprint : MediaAdFingerprint(
opcodes = listOf(
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.XOR_INT_LIT8,
Opcode.IF_EQZ,
)
) {
override fun toString() = result!!.method.toString()
}

View File

@@ -0,0 +1,39 @@
package app.revanced.patches.mifitness.misc.locale
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.mifitness.misc.locale.fingerprints.SyncBluetoothLanguageFingerprint
import app.revanced.patches.mifitness.misc.login.FixLoginPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Force English locale",
description = "Forces wearable devices to use the English locale.",
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
dependencies = [FixLoginPatch::class],
)
@Suppress("unused")
object ForceEnglishLocalePatch : BytecodePatch(
setOf(SyncBluetoothLanguageFingerprint),
) {
override fun execute(context: BytecodeContext) {
SyncBluetoothLanguageFingerprint.result?.let {
val resolvePhoneLocaleInstruction = it.scanResult.patternScanResult!!.startIndex
it.mutableMethod.apply {
val registerIndexToUpdate =
getInstruction<OneRegisterInstruction>(resolvePhoneLocaleInstruction).registerA
replaceInstruction(
resolvePhoneLocaleInstruction,
"const-string v$registerIndexToUpdate, \"en_gb\"",
)
}
} ?: throw SyncBluetoothLanguageFingerprint.exception
}
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.mifitness.misc.locale.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object SyncBluetoothLanguageFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" &&
methodDef.name == "syncBluetoothLanguage"
},
opcodes = listOf(Opcode.MOVE_RESULT_OBJECT),
)

View File

@@ -0,0 +1,26 @@
package app.revanced.patches.mifitness.misc.login
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.mifitness.misc.login.fingerprints.XiaomiAccountManagerConstructorFingerprint
import app.revanced.util.exception
@Patch(
name = "Fix login",
description = "Fixes login for uncertified Mi Fitness app",
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
)
@Suppress("unused")
object FixLoginPatch : BytecodePatch(
setOf(XiaomiAccountManagerConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
XiaomiAccountManagerConstructorFingerprint.result?.mutableMethod?.addInstruction(
0,
"const/16 p2, 0x0",
) ?: throw XiaomiAccountManagerConstructorFingerprint.exception
}
}

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.mifitness.misc.login.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;"
},
parameters = listOf(
"Landroid/content/Context;",
"Z",
),
)

View File

@@ -0,0 +1,37 @@
package app.revanced.patches.music.ad.video
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.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsParentFingerprint
import app.revanced.util.exception
@Patch(
name = "Hide music video ads",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object HideMusicVideoAds : BytecodePatch(
setOf(ShowMusicVideoAdsParentFingerprint),
) {
override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsParentFingerprint.result?.let {
val showMusicVideoAdsMethod = context
.toMethodWalker(it.mutableMethod)
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod
showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
} ?: throw ShowMusicVideoAdsParentFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to HideMusicVideoAds.")
object MusicVideoAdsPatch : BytecodePatch(
dependencies = setOf(HideMusicVideoAds::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -1,32 +0,0 @@
package app.revanced.patches.music.ad.video
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.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
@Patch(
name = "Music video ads",
description = "Removes ads in the music player.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
)
@Suppress("unused")
object MusicVideoAdsPatch : BytecodePatch(
setOf(ShowMusicVideoAdsConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
val result = ShowMusicVideoAdsFingerprint.result!!
result.mutableMethod.addInstruction(
result.scanResult.patternScanResult!!.startIndex,
"""
const/4 p1, 0x0
"""
)
}
}

View File

@@ -1,27 +0,0 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
Opcode.INVOKE_DIRECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.CONST_4,
Opcode.IPUT_BOOLEAN,
Opcode.RETURN_VOID
)
)

View File

@@ -1,14 +0,0 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object ShowMusicVideoAdsFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf(
Opcode.IPUT_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
)
)

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
),
strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error."),
)

View File

@@ -10,13 +10,12 @@ import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprin
import com.android.tools.smali.dexlib2.Opcode
@Patch(
name = "Codecs unlock",
description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
@Deprecated("This patch is no longer needed as the feature is now enabled by default.")
object CodecsUnlockPatch : BytecodePatch(
setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint)
setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint),
) {
override fun execute(context: BytecodeContext) {
val codecsLockResult = CodecsLockFingerprint.result!!
@@ -25,13 +24,13 @@ object CodecsUnlockPatch : BytecodePatch(
val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex
val instructionIndex = scanResultStartIndex +
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
// for 5.16.xx and lower
-3
} else {
// since 5.17.xx
-2
}
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
// for 5.16.xx and lower
-3
} else {
// since 5.17.xx
-2
}
val allCodecsResult = AllCodecsReferenceFingerprint.result!!
val allCodecsMethod =
@@ -41,7 +40,7 @@ object CodecsUnlockPatch : BytecodePatch(
implementation.replaceInstruction(
instructionIndex,
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction()
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction(),
)
}
}

View File

@@ -1,31 +1,36 @@
package app.revanced.patches.music.audio.exclusiveaudio
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AllowExclusiveAudioPlaybackFingerprint
import app.revanced.util.exception
@Patch(
name = "Exclusive audio playback",
name = "Enable exclusive audio playback",
description = "Enables the option to play audio without video.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object ExclusiveAudioPatch : BytecodePatch(
setOf(AllowExclusiveAudioPlaybackFingerprint)
object EnableExclusiveAudioPlayback : BytecodePatch(
setOf(AllowExclusiveAudioPlaybackFingerprint),
) {
override fun execute(context: BytecodeContext) {
AllowExclusiveAudioPlaybackFingerprint.result?.mutableMethod?.apply {
addInstructions(
0,
"""
"""
const/4 v0, 0x1
return v0
"""
""",
)
} ?: throw AllowExclusiveAudioPlaybackFingerprint.exception
}
}
}
@Deprecated("This patch class has been renamed to EnableExclusiveAudioPlayback.")
object ExclusiveAudioPatch : BytecodePatch(emptySet()) {
override fun execute(context: BytecodeContext) = EnableExclusiveAudioPlayback.execute(context)
}

View File

@@ -1,51 +0,0 @@
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object ExclusiveAudioFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.NOP,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.RETURN_VOID
)
)

View File

@@ -1,25 +1,32 @@
package app.revanced.patches.music.interaction.permanentshuffle
import app.revanced.util.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.music.interaction.permanentshuffle.fingerprints.DisableShuffleFingerprint
import app.revanced.util.exception
@Patch(
name = "Permanent shuffle",
description = "Permanently remember your shuffle preference " +
"even if the playlist ends or another track is played.",
"even if the playlist ends or another track is played.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false
use = false,
)
@Suppress("unused")
object PermanentShuffleTogglePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
override fun execute(context: BytecodeContext) {
DisableShuffleFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
?: throw DisableShuffleFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to PermanentShufflePatch.")
object PermanentShuffleTogglePatch : BytecodePatch(
dependencies = setOf(PermanentShufflePatch::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -1,34 +0,0 @@
package app.revanced.patches.music.layout.compactheader
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x
@Patch(
name = "Compact header",
description = "Hides the music category bar at the top of the homepage.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false
)
@Suppress("unused")
object CompactHeaderPatch : BytecodePatch(
setOf(CompactHeaderConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
val result = CompactHeaderConstructorFingerprint.result!!
val method = result.mutableMethod
val insertIndex = result.scanResult.patternScanResult!!.endIndex
val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
method.addInstructions(
insertIndex, """
const/16 v2, 0x8
invoke-virtual {v${register}, v2}, Landroid/view/View;->setVisibility(I)V
"""
)
}
}

View File

@@ -0,0 +1,47 @@
package app.revanced.patches.music.layout.compactheader
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.compactheader.fingerprints.ConstructCategoryBarFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide category bar",
description = "Hides the category bar at the top of the homepage.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false,
)
@Suppress("unused")
object HideCategoryBar : BytecodePatch(
setOf(ConstructCategoryBarFingerprint),
) {
override fun execute(context: BytecodeContext) {
ConstructCategoryBarFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
addInstructions(
insertIndex,
"""
const/16 v2, 0x8
invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V
""",
)
}
} ?: throw ConstructCategoryBarFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to HideCategoryBar.")
object CompactHeaderPatch : BytecodePatch(
dependencies = setOf(HideCategoryBar::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -5,19 +5,19 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object CompactHeaderConstructorFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L"), listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
internal object ConstructCategoryBarFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("Landroid/content/Context;", "L", "L", "L"),
listOf(
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST
)
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
),
)

View File

@@ -1,26 +1,39 @@
package app.revanced.patches.music.layout.minimizedplayback
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.BackgroundPlaybackDisableFingerprint
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint
import app.revanced.util.exception
@Patch(
name = "Minimized playback music",
description = "Enables minimized playback on Kids music.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
name = "Minimized playback",
description = "Unlocks options for picture-in-picture and background playback.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object MinimizedPlaybackPatch : BytecodePatch(setOf(MinimizedPlaybackManagerFingerprint)) {
override fun execute(context: BytecodeContext) =
MinimizedPlaybackManagerFingerprint.result?.mutableMethod?.addInstruction(
object MinimizedPlaybackPatch : BytecodePatch(
setOf(
KidsMinimizedPlaybackPolicyControllerFingerprint,
BackgroundPlaybackDisableFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction(
0,
"return-void",
) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
return-void
"""
) ?: throw MinimizedPlaybackManagerFingerprint.exception
const/4 v0, 0x1
return v0
""",
) ?: throw BackgroundPlaybackDisableFingerprint.exception
}
}

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
"Z",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L"),
listOf(
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.AND_INT_LIT16,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
),
)

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
internal object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("I", "L", "Z"),
@@ -22,5 +22,5 @@ internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
Opcode.CONST_4,
Opcode.IF_NE,
Opcode.IPUT_BOOLEAN,
)
),
)

View File

@@ -2,41 +2,44 @@ package app.revanced.patches.music.layout.premium
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
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.music.layout.premium.fingerprints.HideGetPremiumFingerprint
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Hide get premium",
description = "Removes all \"Get Premium\" evidences from the avatar menu.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
name = "Hide 'Get Music Premium' label",
description = "Hides the red \"Get Music Premium\" label from the account menu.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object HideGetPremiumPatch : BytecodePatch(setOf(HideGetPremiumParentFingerprint)) {
object HideGetPremiumPatch : BytecodePatch(
setOf(HideGetPremiumFingerprint),
) {
override fun execute(context: BytecodeContext) {
val parentResult = HideGetPremiumParentFingerprint.result!!
HideGetPremiumFingerprint.resolve(context, parentResult.classDef)
HideGetPremiumFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val startIndex = parentResult.scanResult.patternScanResult!!.startIndex
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(insertIndex)
val getPremiumViewRegister = setVisibilityInstruction.registerC
val visibilityRegister = setVisibilityInstruction.registerD
val parentMethod = parentResult.mutableMethod
parentMethod.replaceInstruction(
startIndex,
"""
const/4 v1, 0x0
"""
)
replaceInstruction(
insertIndex,
"const/16 v$visibilityRegister, 0x8",
)
val result = HideGetPremiumFingerprint.result!!
val method = result.mutableMethod
method.addInstruction(
startIndex,
"""
const/16 v0, 0x8
"""
)
addInstruction(
insertIndex + 1,
"invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " +
"Landroid/view/View;->setVisibility(I)V",
)
}
} ?: throw HideGetPremiumFingerprint.exception
}
}

View File

@@ -6,11 +6,13 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object HideGetPremiumFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf(),
listOf(
Opcode.IF_NEZ,
Opcode.CONST_16,
Opcode.GOTO,
Opcode.NOP,
Opcode.INVOKE_VIRTUAL
)
Opcode.INVOKE_VIRTUAL,
),
listOf("FEmusic_history", "FEmusic_offline"),
)

View File

@@ -1,19 +0,0 @@
package app.revanced.patches.music.layout.premium.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object HideGetPremiumParentFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC
),
listOf("FEmusic_history"),
)

View File

@@ -1,71 +1,84 @@
package app.revanced.patches.music.layout.upgradebutton
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.newLabel
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.toInstructions
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch(
name = "Remove upgrade button",
description = "Removes the upgrade tab from the pivot bar.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object RemoveUpgradeButtonPatch : BytecodePatch(
setOf(PivotBarConstructorFingerprint)
setOf(PivotBarConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
val result = PivotBarConstructorFingerprint.result!!
val implementation = result.mutableMethod.implementation!!
PivotBarConstructorFingerprint.result?.let {
it.mutableMethod.apply {
val pivotBarElementFieldReference = getInstruction(it.scanResult.patternScanResult!!.endIndex - 1)
.getReference<FieldReference>()
val pivotBarElementFieldRef =
(implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference
val register = (getInstructions().first() as Instruction35c).registerC
val register = (implementation.instructions.first() as Instruction35c).registerC
// first compile all the needed instructions
val instructionList = """
invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1
const/4 v2, 0x4
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
iput-object v0, v$register, $pivotBarElementFieldRef
""".toInstructions().toMutableList()
// First compile all the needed instructions.
val instructionList = """
invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1
const/4 v2, 0x4
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
iput-object v0, v$register, $pivotBarElementFieldReference
""".toInstructions().toMutableList()
val endIndex = it.scanResult.patternScanResult!!.endIndex
val endIndex = result.scanResult.patternScanResult!!.endIndex
// Replace the instruction to retain the label at given index.
replaceInstruction(
endIndex - 1,
instructionList[0], // invoke-interface.
)
// Do not forget to remove this instruction since we added it already.
instructionList.removeFirst()
// replace the instruction to retain the label at given index
implementation.replaceInstruction(
endIndex - 1, instructionList[0] // invoke-interface
)
// do not forget to remove this instruction since we added it already
instructionList.removeFirst()
val exitInstruction = instructionList.last() // iput-object
addInstruction(
endIndex,
exitInstruction,
)
// Do not forget to remove this instruction since we added it already.
instructionList.removeLast()
val exitInstruction = instructionList.last() // iput-object
implementation.addInstruction(
endIndex, exitInstruction
)
// do not forget to remove this instruction since we added it already
instructionList.removeLast()
// Add the necessary if statement to remove the upgrade tab button in case it exists.
instructionList.add(
2, // if-le.
BuilderInstruction22t(
Opcode.IF_LE,
1,
2,
newLabel(endIndex),
),
)
// add the necessary if statement to remove the upgrade tab button in case it exists
instructionList.add(
2, // if-le
BuilderInstruction22t(
Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(endIndex)
)
)
implementation.addInstructions(
endIndex, instructionList
)
addInstructions(
endIndex,
instructionList,
)
}
} ?: throw PivotBarConstructorFingerprint.exception
}
}

View File

@@ -1,62 +1,19 @@
package app.revanced.patches.music.layout.upgradebutton.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object PivotBarConstructorFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.CONST_4,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.GOTO,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.NOP,
Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID
)
)
Opcode.RETURN_VOID,
),
)

View File

@@ -2,12 +2,11 @@ package app.revanced.patches.music.misc.gms
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorOption
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
import app.revanced.patches.music.misc.gms.fingerprints.*
import app.revanced.patches.music.misc.integrations.fingerprints.ApplicationInitFingerprint
import app.revanced.patches.music.misc.integrations.IntegrationsPatch
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
import app.revanced.patches.shared.fingerprints.CastContextFetchFingerprint
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
@Suppress("unused")
object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
@@ -21,7 +20,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint,
),
mainActivityOnCreateFingerprint = ApplicationInitFingerprint,
mainActivityOnCreateFingerprint = MusicActivityOnCreateFingerprint,
integrationsPatchDependency = IntegrationsPatch::class,
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
compatiblePackages = setOf(CompatiblePackage("com.google.android.apps.youtube.music")),
@@ -32,7 +31,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint,
PrimeMethodFingerprint,
)
),
) {
override val gmsCoreVendor by gmsCoreVendorOption
override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
}

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.music.misc.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object MusicActivityOnCreateFingerprint : MethodFingerprint(
returnType = "V",
parameters = listOf("Landroid/os/Bundle;"),
customFingerprint = { methodDef, classDef ->
methodDef.name == "onCreate" && classDef.type.endsWith("/MusicActivity;")
}
)

View File

@@ -1,14 +1,12 @@
package app.revanced.patches.music.misc.gms.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object ServiceCheckFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L", "I"),
strings = listOf("Google Play Services not available")
strings = listOf("Google Play Services not available"),
)

View File

@@ -6,8 +6,5 @@ import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
@Patch(requiresIntegrations = true)
object IntegrationsPatch : BaseIntegrationsPatch(
"Lapp/revanced/integrations/utils/ReVancedUtils;",
setOf(
ApplicationInitFingerprint,
),
setOf(ApplicationInitFingerprint),
)

View File

@@ -1,26 +1,12 @@
package app.revanced.patches.music.premium.backgroundplay
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
@Patch(
name = "Background play",
description = "Enables playing music in the background.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
)
@Suppress("unused")
object BackgroundPlayPatch : BytecodePatch(setOf(BackgroundPlaybackDisableFingerprint)) {
override fun execute(context: BytecodeContext) =
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
0, """
const/4 v0, 0x1
return v0
"""
) ?: throw BackgroundPlaybackDisableFingerprint.exception
}
import app.revanced.patches.music.layout.minimizedplayback.MinimizedPlaybackPatch
@Deprecated("This patch has been merged into MinimizedPlaybackPatch.")
object BackgroundPlayPatch : BytecodePatch(
dependencies = setOf(MinimizedPlaybackPatch::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -1,43 +0,0 @@
package app.revanced.patches.music.premium.backgroundplay.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf(
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.AND_INT_LIT16,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_BOOLEAN,
Opcode.IF_EQZ,
Opcode.CONST_4,
Opcode.RETURN,
Opcode.RETURN,
Opcode.RETURN
)
)

View File

@@ -6,23 +6,24 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import org.w3c.dom.Element
@Patch(
name = "Remove broadcasts restriction",
description = "Enables starting/stopping NetGuard via broadcasts.",
compatiblePackages = [CompatiblePackage("eu.faircode.netguard")],
use = false
use = false,
)
@Suppress("unused")
object RemoveBroadcastsRestrictionPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
context.xmlEditor["AndroidManifest.xml"].use { dom ->
val applicationNode = dom
.file
.getElementsByTagName("application")
.item(0) as Element
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
applicationNode.getElementsByTagName("receiver").also { list ->
val applicationNode =
document
.getElementsByTagName("application")
.item(0) as Element
applicationNode.getElementsByTagName("receiver").also { list ->
for (i in 0 until list.length) {
val element = list.item(i) as? Element ?: continue
if (element.getAttribute("android:name") == "eu.faircode.netguard.WidgetAdmin") {

View File

@@ -0,0 +1,115 @@
package app.revanced.patches.openinghours.misc.fix.crash
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.newLabel
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.openinghours.misc.fix.crash.fingerprints.SetPlaceFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21t
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Fix crash",
compatiblePackages = [CompatiblePackage("de.simon.openinghours", ["1.0"])],
)
@Suppress("unused")
object FixCrashPatch : BytecodePatch(
setOf(SetPlaceFingerprint),
) {
override fun execute(context: BytecodeContext) {
SetPlaceFingerprint.result?.let {
val indexedInstructions = it.mutableMethod.getInstructions().withIndex().toList()
/**
* This function replaces all `checkNotNull` instructions in the integer interval
* from [startIndex] to [endIndex], both inclusive. In place of the `checkNotNull`
* instruction an if-null check is inserted. If the if-null check yields that
* the value is indeed null, we jump to a newly created label at `endIndex + 1`.
*/
fun avoidNullPointerException(startIndex: Int, endIndex: Int) {
val continueLabel = it.mutableMethod.newLabel(endIndex + 1)
for (index in startIndex..endIndex) {
val instruction = indexedInstructions[index].value
if (!instruction.isCheckNotNullInstruction) {
continue
}
val checkNotNullInstruction = instruction as FiveRegisterInstruction
val originalRegister = checkNotNullInstruction.registerC
it.mutableMethod.replaceInstruction(
index,
BuilderInstruction21t(
Opcode.IF_EQZ,
originalRegister,
continueLabel,
),
)
}
}
val getOpeningHoursIndex = getIndicesOfInvoke(
indexedInstructions,
"Lde/simon/openinghours/models/Place;",
"getOpeningHours",
)
val setWeekDayTextIndex = getIndexOfInvoke(
indexedInstructions,
"Lde/simon/openinghours/views/custom/PlaceCard;",
"setWeekDayText",
)
val startCalculateStatusIndex = getIndexOfInvoke(
indexedInstructions,
"Lde/simon/openinghours/views/custom/PlaceCard;",
"startCalculateStatus",
)
// Replace the Intrinsics;->checkNotNull instructions with a null check
// and jump to our newly created label if it returns true.
// This avoids the NullPointerExceptions.
avoidNullPointerException(getOpeningHoursIndex[1], startCalculateStatusIndex)
avoidNullPointerException(getOpeningHoursIndex[0], setWeekDayTextIndex)
} ?: throw SetPlaceFingerprint.exception
}
private fun isInvokeInstruction(instruction: Instruction, className: String, methodName: String): Boolean {
val methodRef = instruction.getReference<MethodReference>() ?: return false
return methodRef.definingClass == className && methodRef.name == methodName
}
private fun getIndicesOfInvoke(
instructions: List<IndexedValue<Instruction>>,
className: String,
methodName: String,
): List<Int> = instructions.mapNotNull { (index, instruction) ->
if (isInvokeInstruction(instruction, className, methodName)) {
index
} else {
null
}
}
private fun getIndexOfInvoke(
instructions: List<IndexedValue<Instruction>>,
className: String,
methodName: String,
): Int = instructions.first { (_, instruction) ->
isInvokeInstruction(instruction, className, methodName)
}.index
private val Instruction.isCheckNotNullInstruction
get() = isInvokeInstruction(this, "Lkotlin/jvm/internal/Intrinsics;", "checkNotNull")
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.openinghours.misc.fix.crash.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object SetPlaceFingerprint : MethodFingerprint(
"V",
parameters = listOf("Lde/simon/openinghours/models/Place;"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lde/simon/openinghours/views/custom/PlaceCard;" &&
methodDef.name == "setPlace"
},
)

View File

@@ -9,8 +9,10 @@ object HideBannerPatch : ResourcePatch() {
private const val RESOURCE_FILE_PATH = "res/layout/merge_listheader_link_detail.xml"
override fun execute(context: ResourceContext) {
context.xmlEditor[RESOURCE_FILE_PATH].use {
it.file.getElementsByTagName("merge").item(0).childNodes.apply {
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
val document = editor.file
document.getElementsByTagName("merge").item(0).childNodes.apply {
val attributes = arrayOf("height", "width")
for (i in 1 until length) {
@@ -30,4 +32,3 @@ object HideBannerPatch : ResourcePatch() {
}
}
}

View File

@@ -7,7 +7,7 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.ad.comments.fingerprints.HideCommentAdsFingerprint
@Patch(description = "Removes ads in the comments.",)
@Patch(description = "Removes ads in the comments.")
object HideCommentAdsPatch : BytecodePatch(
setOf(HideCommentAdsFingerprint)
) {

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.reddit.customclients.ads
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.reddit.customclients.ads.fingerprints.IsAdsEnabledFingerprint
import app.revanced.util.returnEarly
abstract class BaseDisableAdsPatch(
dependencies: Set<PatchClass> = emptySet(),
compatiblePackages: Set<CompatiblePackage>,
) : BytecodePatch(
name = "Disable ads",
dependencies = dependencies,
compatiblePackages = compatiblePackages,
fingerprints = setOf(IsAdsEnabledFingerprint),
) {
override fun execute(context: BytecodeContext) = listOf(IsAdsEnabledFingerprint).returnEarly()
}

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints
package app.revanced.patches.reddit.customclients.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
@@ -7,5 +7,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object IsAdsEnabledFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf("SyncIapHelper")
)
strings = listOf("SyncIapHelper"),
)

View File

@@ -5,22 +5,22 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.infinityforreddit.api.SpoofClientPatch
import app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints.BillingClientOnServiceConnected
import app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints.StartSubscriptionActivityFingerprint
import app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints.SubscriptionActivityOnCreateFingerprint
import app.revanced.util.returnEarly
@Patch(
name = "Unlock subscription",
description = "Unlocks the subscription feature but requires a custom client ID.",
compatiblePackages = [
CompatiblePackage("ml.docilealligator.infinityforreddit")
CompatiblePackage("ml.docilealligator.infinityforreddit"),
],
dependencies = [SpoofClientPatch::class]
dependencies = [SpoofClientPatch::class],
)
@Suppress("unused")
object UnlockSubscriptionPatch : BytecodePatch(
setOf(StartSubscriptionActivityFingerprint, SubscriptionActivityOnCreateFingerprint)
setOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected),
) {
override fun execute(context: BytecodeContext) =
listOf(StartSubscriptionActivityFingerprint, SubscriptionActivityOnCreateFingerprint).returnEarly()
listOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected).returnEarly()
}

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object BillingClientOnServiceConnected : MethodFingerprint(
strings = listOf("Billing service connected"),
)

View File

@@ -1,13 +0,0 @@
package app.revanced.patches.reddit.customclients.infinityforreddit.subscription.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object SubscriptionActivityOnCreateFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC.value,
parameters = listOf("Landroid/os/Bundle;"),
customFingerprint = { method, classDef ->
method.name == "onCreate" && classDef.type.endsWith("SubscriptionActivity;")
}
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforlemmy.ads
import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
@Suppress("unused")
object DisableAdsPatch : BaseDisableAdsPatch(
dependencies = setOf(DisablePiracyDetectionPatch::class),
compatiblePackages = setOf(CompatiblePackage("com.laurencedawson.reddit_sync")),
)

View File

@@ -1,30 +1,8 @@
package app.revanced.patches.reddit.customclients.syncforreddit.ads
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch
@Patch(
name = "Disable ads",
dependencies = [DisablePiracyDetectionPatch::class],
compatiblePackages = [CompatiblePackage("com.laurencedawson.reddit_sync")]
)
@Suppress("unused")
object DisableAdsPatch : BytecodePatch(setOf(IsAdsEnabledFingerprint)) {
override fun execute(context: BytecodeContext) {
IsAdsEnabledFingerprint.result?.mutableMethod?.apply {
addInstructions(
0,
"""
const/4 v0, 0x0
return v0
"""
)
} ?: throw IsAdsEnabledFingerprint.exception
}
}
object DisableAdsPatch : BaseDisableAdsPatch(
compatiblePackages = setOf(CompatiblePackage("io.syncapps.lemmy_sync")),
)

View File

@@ -6,18 +6,13 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
@Patch(description = "Disables detection of modified versions.",)
@Patch(description = "Disables detection of modified versions.")
object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
override fun execute(context: BytecodeContext) {
// 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(
0,
"""
return-void
"""
)
addInstruction(0, "return-void")
}
}
}
}

View File

@@ -0,0 +1,32 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.slink
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints.LinkHelperOpenLinkFingerprint
import app.revanced.util.exception
@Patch(
name = "Fix /s/ links",
description = "Fixes the issue where /s/ links do not work.",
compatiblePackages = [
CompatiblePackage("com.laurencedawson.reddit_sync"),
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
CompatiblePackage("com.laurencedawson.reddit_sync.dev")
],
requiresIntegrations = true
)
object FixSLinksPatch : BytecodePatch(
setOf(LinkHelperOpenLinkFingerprint)
) {
override fun execute(context: BytecodeContext) =
LinkHelperOpenLinkFingerprint.result?.mutableMethod?.addInstructions(
1,
"""
invoke-static { p3 }, Lapp/revanced/integrations/syncforreddit/FixSLinksPatch;->resolveSLink(Ljava/lang/String;)Ljava/lang/String;
move-result-object p3
"""
) ?: throw LinkHelperOpenLinkFingerprint.exception
}

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object LinkHelperOpenLinkFingerprint: MethodFingerprint(
strings = listOf("Link title: ")
)

View File

@@ -2,7 +2,7 @@ package app.revanced.patches.shared.misc.gms
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
@@ -12,7 +12,7 @@ import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AC
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_METHOD_NAME
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.returnEarly
@@ -32,7 +32,7 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
* @param toPackageName The package name to fall back to if no custom package name is specified in patch options.
* @param primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched.
* @param earlyReturnFingerprints The fingerprints of methods that need to be returned early.
* @param mainActivityOnCreateFingerprint The fingerprint of the main activity's onCreate method.
* @param mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method.
* @param integrationsPatchDependency The patch responsible for the integrations.
* @param gmsCoreSupportResourcePatch The corresponding resource patch that is used to patch the resources.
* @param dependencies Additional dependencies of this patch.
@@ -53,22 +53,25 @@ abstract class BaseGmsCoreSupportPatch(
) : BytecodePatch(
name = "GmsCore support",
description = "Allows patched Google apps to run without root and under a different package name " +
"by using GmsCore instead of Google Play Services.",
"by using GmsCore instead of Google Play Services.",
dependencies = setOf(
ChangePackageNamePatch::class,
gmsCoreSupportResourcePatch::class,
integrationsPatchDependency
integrationsPatchDependency,
) + dependencies,
compatiblePackages = compatiblePackages,
fingerprints = setOf(GmsCoreSupportFingerprint, mainActivityOnCreateFingerprint) + fingerprints,
requiresIntegrations = true
fingerprints = setOf(
GmsCoreSupportFingerprint,
mainActivityOnCreateFingerprint,
) + fingerprints,
requiresIntegrations = true,
) {
init {
// Manually register all options of the resource patch so that they are visible in the patch API.
gmsCoreSupportResourcePatch.options.values.forEach(options::register)
}
internal abstract val gmsCoreVendor: String?
internal abstract val gmsCoreVendorGroupId: String?
override fun execute(context: BytecodeContext) {
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
@@ -77,7 +80,7 @@ abstract class BaseGmsCoreSupportPatch(
val transformations = arrayOf(
::commonTransform,
::contentUrisTransform,
packageNameTransform(fromPackageName, packageName)
packageNameTransform(fromPackageName, packageName),
)
context.transformStringReferences transform@{ string ->
transformations.forEach { transform ->
@@ -93,16 +96,17 @@ abstract class BaseGmsCoreSupportPatch(
// Return these methods early to prevent the app from crashing.
earlyReturnFingerprints.toList().returnEarly()
// Check the availability of GmsCore.
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstruction(
1, // Hack to not disturb other patches (such as the integrations patch).
"invoke-static {}, Lapp/revanced/integrations/youtube/patches/GmsCoreSupport;->checkAvailability()V"
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
0,
"invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" +
"checkGmsCore(Landroid/app/Activity;)V",
) ?: throw mainActivityOnCreateFingerprint.exception
// Change the vendor of GmsCore in ReVanced Integrations.
GmsCoreSupportFingerprint.result?.mutableClass?.methods
?.single { it.name == GET_GMS_CORE_VENDOR_METHOD_NAME }
?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendor\"")
?.single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME }
?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"")
?: throw GmsCoreSupportFingerprint.exception
}
@@ -130,8 +134,8 @@ abstract class BaseGmsCoreSupportPatch(
BuilderInstruction21c(
Opcode.CONST_STRING,
instruction.registerA,
ImmutableStringReference(transformedString)
)
ImmutableStringReference(transformedString),
),
)
}
}
@@ -145,10 +149,11 @@ abstract class BaseGmsCoreSupportPatch(
"com.google.android.gms",
in PERMISSIONS,
in ACTIONS,
in AUTHORITIES -> referencedString.replace("com.google", gmsCoreVendor!!)
in AUTHORITIES,
-> referencedString.replace("com.google", gmsCoreVendorGroupId!!)
// No vendor prefix for whatever reason...
"subscribedfeeds" -> "$gmsCoreVendor.subscribedfeeds"
"subscribedfeeds" -> "$gmsCoreVendorGroupId.subscribedfeeds"
else -> null
}
@@ -161,7 +166,7 @@ abstract class BaseGmsCoreSupportPatch(
if (str.startsWith(uriPrefix)) {
return str.replace(
uriPrefix,
"content://${authority.replace("com.google", gmsCoreVendor!!)}"
"content://${authority.replace("com.google", gmsCoreVendorGroupId!!)}",
)
}
}
@@ -169,18 +174,18 @@ abstract class BaseGmsCoreSupportPatch(
// gms also has a 'subscribedfeeds' authority, check for that one too
val subFeedsUriPrefix = "content://subscribedfeeds"
if (str.startsWith(subFeedsUriPrefix)) {
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendor.subscribedfeeds")
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.subscribedfeeds")
}
}
return null
}
private fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string ->
when (string) {
"$fromPackageName.SuggestionsProvider",
"$fromPackageName.fileprovider" -> string.replace(fromPackageName, toPackageName)
"$fromPackageName.fileprovider",
-> string.replace(fromPackageName, toPackageName)
else -> null
}
@@ -273,6 +278,9 @@ abstract class BaseGmsCoreSupportPatch(
// fido
"com.google.android.gms.fido.fido2.privileged.START",
// gass
"com.google.android.gms.gass.START",
// games
"com.google.android.gms.games.service.START",
"com.google.android.gms.games.PLAY_GAMES_UPGRADE",
@@ -292,8 +300,18 @@ abstract class BaseGmsCoreSupportPatch(
// misc
"com.google.android.gms.gmscompliance.service.START",
"com.google.android.gms.oss.licenses.service.START",
"com.google.android.gms.tapandpay.service.BIND",
"com.google.android.gms.measurement.START",
"com.google.android.gms.languageprofile.service.START",
"com.google.android.gms.clearcut.service.START",
"com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE",
// potoken
"com.google.android.gms.potokens.service.START",
// droidguard/ safetynet
"com.google.android.gms.droidguard.service.START",
"com.google.android.gms.safetynet.service.START",
"com.google.android.gms.tapandpay.service.BIND"
)
/**
@@ -314,9 +332,9 @@ abstract class BaseGmsCoreSupportPatch(
"com.google.android.gms.fonts",
// phenotype
"com.google.android.gms.phenotype"
"com.google.android.gms.phenotype",
)
}
// endregion
}
}

View File

@@ -22,21 +22,25 @@ abstract class BaseGmsCoreSupportResourcePatch(
private val fromPackageName: String,
private val toPackageName: String,
private val spoofedPackageSignature: String,
dependencies: Set<PatchClass> = setOf()
dependencies: Set<PatchClass> = setOf(),
) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class, AddResourcesPatch::class) + dependencies) {
internal val gmsCoreVendorOption = stringPatchOption(
key = "gmsCoreVendor",
default = "com.mgoogle",
values = mapOf(
"Vanced" to "com.mgoogle",
"ReVanced" to "app.revanced"
),
title = "GmsCore Vendor",
description = "The group id of the GmsCore vendor.",
required = true
) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) }
internal val gmsCoreVendorGroupIdOption =
stringPatchOption(
key = "gmsCoreVendorGroupId",
default = "app.revanced",
values =
mapOf(
"ReVanced" to "app.revanced",
),
title = "GmsCore vendor group ID",
description = "The vendor's group ID for GmsCore.",
required = true,
) { it!!.matches(Regex(PACKAGE_NAME_REGEX_PATTERN)) }
protected val gmsCoreVendor by gmsCoreVendorOption
protected val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
@Deprecated("Use gmsCoreVendorGroupId instead.", ReplaceWith("gmsCoreVendorGroupId"))
protected val gmsCoreVendor by gmsCoreVendorGroupIdOption
override fun execute(context: ResourceContext) {
AddResourcesPatch(BaseGmsCoreSupportResourcePatch::class)
@@ -49,26 +53,31 @@ abstract class BaseGmsCoreSupportResourcePatch(
* Add metadata to manifest to support spoofing the package name and signature of GmsCore.
*/
private fun ResourceContext.addSpoofingMetadata() {
fun Node.adoptChild(tagName: String, block: Element.() -> Unit) {
fun Node.adoptChild(
tagName: String,
block: Element.() -> Unit,
) {
val child = ownerDocument.createElement(tagName)
child.block()
appendChild(child)
}
xmlEditor["AndroidManifest.xml"].use {
val applicationNode = it
.file
.getElementsByTagName("application")
.item(0)
xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
val applicationNode =
document
.getElementsByTagName("application")
.item(0)
// Spoof package name and signature.
applicationNode.adoptChild("meta-data") {
setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_NAME")
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME")
setAttribute("android:value", fromPackageName)
}
applicationNode.adoptChild("meta-data") {
setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_SIGNATURE")
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_SIGNATURE")
setAttribute("android:value", spoofedPackageSignature)
}
@@ -76,7 +85,7 @@ abstract class BaseGmsCoreSupportResourcePatch(
applicationNode.adoptChild("meta-data") {
// TODO: The name of this metadata should be dynamic.
setAttribute("android:name", "app.revanced.MICROG_PACKAGE_NAME")
setAttribute("android:value", "$gmsCoreVendor.android.gms")
setAttribute("android:value", "$gmsCoreVendorGroupId.android.gms")
}
}
}
@@ -87,27 +96,31 @@ abstract class BaseGmsCoreSupportResourcePatch(
private fun ResourceContext.patchManifest() {
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
val manifest = this["AndroidManifest.xml"].readText()
this["AndroidManifest.xml"].writeText(
val manifest = this.get("AndroidManifest.xml").readText()
this.get("AndroidManifest.xml").writeText(
manifest.replace(
"package=\"$fromPackageName",
"package=\"$packageName"
"package=\"$packageName",
).replace(
"android:authorities=\"$fromPackageName",
"android:authorities=\"$packageName"
"android:authorities=\"$packageName",
).replace(
"$fromPackageName.permission.C2D_MESSAGE",
"$packageName.permission.C2D_MESSAGE"
"$packageName.permission.C2D_MESSAGE",
).replace(
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
).replace(
"com.google.android.c2dm",
"$gmsCoreVendor.android.c2dm"
"$gmsCoreVendorGroupId.android.c2dm",
).replace(
"</queries>",
"<package android:name=\"$gmsCoreVendor.android.gms\"/></queries>"
)
"<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
),
)
}
}
private companion object {
private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$"
}
}

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object GmsCoreSupportFingerprint : MethodFingerprint(
customFingerprint = { _, classDef ->
classDef.type.endsWith("GmsCoreSupport;")
}
},
) {
const val GET_GMS_CORE_VENDOR_METHOD_NAME = "getGmsCoreVendor"
const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId"
}

View File

@@ -11,23 +11,25 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
abstract class BaseIntegrationsPatch(
private val hooks: Set<IntegrationsFingerprint>
private val hooks: Set<IntegrationsFingerprint>,
) : BytecodePatch(hooks) {
@Deprecated(
"Use the constructor without the integrationsDescriptor parameter",
ReplaceWith("AbstractIntegrationsPatch(hooks)")
ReplaceWith("BaseIntegrationsPatch(hooks)"),
)
@Suppress("UNUSED_PARAMETER")
constructor(
integrationsDescriptor: String,
hooks: Set<IntegrationsFingerprint>
hooks: Set<IntegrationsFingerprint>,
) : this(hooks)
override fun execute(context: BytecodeContext) {
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) throw PatchException(
"Integrations have not been merged yet. This patch can not succeed without merging the integrations."
)
if (context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) == null) {
throw PatchException(
"Integrations have not been merged yet. This patch can not succeed without merging the integrations.",
)
}
hooks.forEach { hook ->
hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR)
@@ -47,6 +49,7 @@ abstract class BaseIntegrationsPatch(
opcodes: Iterable<Opcode?>? = null,
strings: Iterable<String>? = null,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
private val insertIndexResolver: ((Method) -> Int) = object : IHookInsertIndexResolver {},
private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
) : MethodFingerprint(
returnType,
@@ -54,20 +57,47 @@ abstract class BaseIntegrationsPatch(
parameters,
opcodes,
strings,
customFingerprint
customFingerprint,
) {
@Deprecated("Previous constructor that is missing the insert index." +
"Here only for binary compatibility, " +
"and this can be removed after the next major version update.")
constructor(
returnType: String? = null,
accessFlags: Int? = null,
parameters: Iterable<String>? = null,
opcodes: Iterable<Opcode?>? = null,
strings: Iterable<String>? = null,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
) : this(
returnType,
accessFlags,
parameters,
opcodes,
strings,
customFingerprint,
object : IHookInsertIndexResolver {},
contextRegisterResolver
)
fun invoke(integrationsDescriptor: String) {
result?.mutableMethod?.let { method ->
val insertIndex = insertIndexResolver(method)
val contextRegister = contextRegisterResolver(method)
method.addInstruction(
0,
"sput-object v$contextRegister, " +
"$integrationsDescriptor->context:Landroid/content/Context;"
insertIndex,
"invoke-static/range { v$contextRegister .. v$contextRegister }, " +
"$integrationsDescriptor->setContext(Landroid/content/Context;)V",
)
} ?: throw PatchException("Could not find hook target fingerprint.")
}
interface IHookInsertIndexResolver : (Method) -> Int {
override operator fun invoke(method: Method) = 0
}
interface IRegisterResolver : (Method) -> Int {
override operator fun invoke(method: Method) = method.implementation!!.registerCount - 1
}
@@ -76,4 +106,4 @@ abstract class BaseIntegrationsPatch(
private companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/shared/Utils;"
}
}
}

View File

@@ -7,7 +7,6 @@ import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
object ResourceMappingPatch : ResourcePatch() {
internal lateinit var resourceMappings: List<ResourceElement>
private set
@@ -17,7 +16,7 @@ object ResourceMappingPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
// save the file in memory to concurrently read from
val resourceXmlFile = context["res/values/public.xml"].readBytes()
val resourceXmlFile = context.get("res/values/public.xml").readBytes()
// create a synchronized list to store the resource mappings
val mappings = Collections.synchronizedList(mutableListOf<ResourceElement>())
@@ -25,7 +24,9 @@ object ResourceMappingPatch : ResourcePatch() {
for (threadIndex in 0 until THREAD_COUNT) {
threadPoolExecutor.execute thread@{
context.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
val resources = editor.file.documentElement.childNodes
val document = editor.file
val resources = document.documentElement.childNodes
val resourcesLength = resources.length
val jobSize = resourcesLength / THREAD_COUNT
@@ -59,4 +60,4 @@ object ResourceMappingPatch : ResourcePatch() {
}
data class ResourceElement(val type: String, val name: String, val id: Long)
}
}

View File

@@ -21,16 +21,18 @@ import java.io.Closeable
*/
abstract class BaseSettingsResourcePatch(
private val rootPreference: Pair<IntentPreference, String>? = null,
dependencies: Set<PatchClass> = emptySet()
dependencies: Set<PatchClass> = emptySet(),
) : ResourcePatch(
dependencies = setOf(AddResourcesPatch::class) + dependencies
), MutableSet<BasePreference> by mutableSetOf(), Closeable {
dependencies = setOf(AddResourcesPatch::class) + dependencies,
),
MutableSet<BasePreference> by mutableSetOf(),
Closeable {
private lateinit var context: ResourceContext
override fun execute(context: ResourceContext) {
context.copyResources(
"settings",
ResourceGroup("xml", "revanced_prefs.xml")
ResourceGroup("xml", "revanced_prefs.xml"),
)
this.context = context
@@ -39,24 +41,34 @@ abstract class BaseSettingsResourcePatch(
}
override fun close() {
fun Node.addPreference(preference: BasePreference) {
fun Node.addPreference(preference: BasePreference, prepend: Boolean = false) {
preference.serialize(ownerDocument) { resource ->
// TODO: Currently, resources can only be added to "values", which may not be the correct place.
// It may be necessary to ask for the desired resourceValue in the future.
AddResourcesPatch("values", resource)
}.let(this::appendChild)
}.let { preferenceNode ->
if (prepend && firstChild != null) {
insertBefore(preferenceNode, firstChild)
} else {
appendChild(preferenceNode)
}
}
}
// Add the root preference to an existing fragment if needed.
rootPreference?.let { (intentPreference, fragment) ->
context.xmlEditor["res/xml/$fragment.xml"].use {
it.getNode("PreferenceScreen").addPreference(intentPreference)
context.xmlEditor["res/xml/$fragment.xml"].use { editor ->
val document = editor.file
document.getNode("PreferenceScreen").addPreference(intentPreference, true)
}
}
// Add all preferences to the ReVanced fragment.
context.xmlEditor["res/xml/revanced_prefs.xml"].use { editor ->
val revancedPreferenceScreenNode = editor.getNode("PreferenceScreen")
val document = editor.file
val revancedPreferenceScreenNode = document.getNode("PreferenceScreen")
forEach { revancedPreferenceScreenNode.addPreference(it) }
}
}

View File

@@ -1,9 +1,10 @@
package app.revanced.patches.shared.misc.settings.preference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import java.io.Closeable
abstract class BasePreferenceScreen(
private val root: MutableSet<Screen> = mutableSetOf()
private val root: MutableSet<Screen> = mutableSetOf(),
) : Closeable {
override fun close() {
@@ -24,33 +25,27 @@ abstract class BasePreferenceScreen(
titleKey: String = "${key}_title",
private val summaryKey: String? = "${key}_summary",
preferences: MutableSet<BasePreference> = mutableSetOf(),
val categories: MutableSet<Category> = mutableSetOf()
val categories: MutableSet<Category> = mutableSetOf(),
private val sorting: Sorting = Sorting.BY_TITLE,
) : BasePreferenceCollection(key, titleKey, preferences) {
/**
* Initialize using title and summary keys with suffix "_title" and "_summary".
*/
constructor(
key: String? = null,
preferences: MutableSet<BasePreference> = mutableSetOf(),
categories: MutableSet<Category> = mutableSetOf()
) : this(key, key + "_title", key + "_summary", preferences, categories)
override fun transform(): PreferenceScreen {
return PreferenceScreen(
key,
titleKey,
summaryKey,
sorting,
// Screens and preferences are sorted at runtime by integrations code,
// so they appear in alphabetical order for the localized language in use.
preferences = preferences + categories.map { it.transform() }
// so title sorting uses the localized language in use.
preferences = preferences + categories.map { it.transform() },
)
}
private fun ensureScreenInserted() {
// Add to screens if not yet done
if (!root.contains(this))
if (!root.contains(this)) {
root.add(this)
}
}
fun addPreferences(vararg preferences: BasePreference) {
@@ -61,13 +56,13 @@ abstract class BasePreferenceScreen(
open inner class Category(
key: String? = null,
titleKey: String = "${key}_title",
preferences: MutableSet<BasePreference> = mutableSetOf()
preferences: MutableSet<BasePreference> = mutableSetOf(),
) : BasePreferenceCollection(key, titleKey, preferences) {
override fun transform(): PreferenceCategory {
return PreferenceCategory(
key,
titleKey,
preferences = preferences
preferences = preferences,
)
}
@@ -75,8 +70,9 @@ abstract class BasePreferenceScreen(
ensureScreenInserted()
// Add to the categories if not done yet.
if (!categories.contains(this))
if (!categories.contains(this)) {
categories.add(this)
}
this.preferences.addAll(preferences)
}
@@ -86,8 +82,8 @@ abstract class BasePreferenceScreen(
abstract class BasePreferenceCollection(
val key: String? = null,
val titleKey: String = "${key}_title",
val preferences: MutableSet<BasePreference> = mutableSetOf()
val preferences: MutableSet<BasePreference> = mutableSetOf(),
) {
abstract fun transform(): BasePreference
}
}
}

View File

@@ -1,19 +1,16 @@
package app.revanced.patches.shared.misc.settings.preference
import app.revanced.patches.shared.misc.settings.preference.IntentPreference.Intent
import app.revanced.util.resource.BaseResource
import org.w3c.dom.Document
/**
* A preference that opens an intent.
*
* @param key The preference key. If null, other parameters must be specified.
* @param key Optional preference key.
* @param titleKey The preference title key.
* @param summaryKey The preference summary key.
* @param tag The preference tag.
* @param intent The intent to open.
*
* @see Intent
*/
class IntentPreference(
key: String? = null,
@@ -21,7 +18,7 @@ class IntentPreference(
summaryKey: String? = "${key}_summary",
tag: String = "Preference",
val intent: Intent,
) : BasePreference(null, titleKey, summaryKey, tag) {
) : BasePreference(key, titleKey, summaryKey, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {

View File

@@ -6,10 +6,12 @@ import org.w3c.dom.Document
/**
* A non-interactive preference.
*
* Typically used to present static text, but also used for custom integration code that responds to taps.
*
* @param key The preference key.
* @param summaryKey The preference summary key.
* @param tag The preference tag.
* @param selectable Whether the preference is selectable.
* @param tag The tag or full class name of the preference.
* @param selectable If the preference is selectable and responds to tap events.
*/
@Suppress("MemberVisibilityCanBePrivate")
class NonInteractivePreference(

View File

@@ -9,6 +9,8 @@ import org.w3c.dom.Document
* @param key The key of the preference. If null, other parameters must be specified.
* @param titleKey The key of the preference title.
* @param summaryKey The key of the preference summary.
* @param sorting Sorting to use. If the sorting is not [Sorting.UNSORTED],
* then the key parameter will be modified to include the sort type.
* @param tag The tag or full class name of the preference.
* @param preferences The preferences in this screen.
*/
@@ -17,14 +19,40 @@ open class PreferenceScreen(
key: String? = null,
titleKey: String = "${key}_title",
summaryKey: String? = "${key}_summary",
sorting: Sorting = Sorting.BY_TITLE,
tag: String = "PreferenceScreen",
val preferences: Set<BasePreference>
) : BasePreference(key, titleKey, summaryKey, tag) {
val preferences: Set<BasePreference>,
// Alternatively, instead of repurposing the key for sorting,
// an extra bundle parameter can be added to the preferences XML declaration.
// This would require bundling and referencing an additional XML file
// or adding new attributes to the attrs.xml file.
// Since the key value is not currently used by integrations,
// for now it's much simpler to modify the key to include the sort parameter.
) : BasePreference(if (sorting == Sorting.UNSORTED) key else (key + sorting.keySuffix), titleKey, summaryKey, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
preferences.forEach {
appendChild(it.serialize(ownerDocument, resourceCallback))
}
}
/**
* How a PreferenceScreen should be sorted.
*/
enum class Sorting(val keySuffix: String) {
/**
* Sort by the localized preference title.
*/
BY_TITLE("_sort_by_title"),
/**
* Sort by the preference keys.
*/
BY_KEY("_sort_by_key"),
/**
* Unspecified sorting.
*/
UNSORTED("_sort_by_unsorted"),
}
}

View File

@@ -10,7 +10,7 @@ import org.w3c.dom.Element
@Patch(
name = "Custom theme",
description = "Applies a custom theme.",
compatiblePackages = [CompatiblePackage("com.spotify.music")]
compatiblePackages = [CompatiblePackage("com.spotify.music")],
)
@Suppress("unused")
object CustomThemePatch : ResourcePatch() {
@@ -19,7 +19,7 @@ object CustomThemePatch : ResourcePatch() {
default = "@android:color/black",
title = "Primary background color",
description = "The background color. Can be a hex color or a resource reference.",
required = true
required = true,
)
private var backgroundColorSecondary by stringPatchOption(
@@ -27,7 +27,7 @@ object CustomThemePatch : ResourcePatch() {
default = "#ff282828",
title = "Secondary background color",
description = "The secondary background color. (e.g. search box, artist & podcast). Can be a hex color or a resource reference.",
required = true
required = true,
)
private var accentColor by stringPatchOption(
@@ -35,16 +35,17 @@ object CustomThemePatch : ResourcePatch() {
default = "#ff1ed760",
title = "Accent color",
description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.",
required = true
required = true,
)
private var accentColorPressed by stringPatchOption(
key = "accentColorPressed",
default = "#ff169c46",
title = "Pressed dark theme accent color",
description = "The color when accented buttons are pressed, by default slightly darker than accent. "
+ "Can be a hex color or a resource reference.",
required = true
description =
"The color when accented buttons are pressed, by default slightly darker than accent. " +
"Can be a hex color or a resource reference.",
required = true,
)
override fun execute(context: ResourceContext) {
@@ -54,23 +55,27 @@ object CustomThemePatch : ResourcePatch() {
val accentColorPressed = accentColorPressed!!
context.xmlEditor["res/values/colors.xml"].use { editor ->
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
val document = editor.file
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
for (i in 0 until resourcesNode.childNodes.length) {
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
node.textContent = when (node.getAttribute("name")) {
"dark_base_background_elevated_base", "design_dark_default_color_background",
"design_dark_default_color_surface", "gray_7", "gray_background", "gray_layer",
"sthlm_blk" -> backgroundColor
node.textContent =
when (node.getAttribute("name")) {
"dark_base_background_elevated_base", "design_dark_default_color_background",
"design_dark_default_color_surface", "gray_7", "gray_background", "gray_layer",
"sthlm_blk",
-> backgroundColor
"gray_15" -> backgroundColorSecondary
"gray_15" -> backgroundColorSecondary
"dark_brightaccent_background_base", "dark_base_text_brightaccent", "green_light" -> accentColor
"dark_brightaccent_background_base", "dark_base_text_brightaccent", "green_light" -> accentColor
"dark_brightaccent_background_press" -> accentColorPressed
else -> continue
}
"dark_brightaccent_background_press" -> accentColorPressed
else -> continue
}
}
}
}

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