Compare commits

..

40 Commits

Author SHA1 Message Date
semantic-release-bot
1482e7e1e8 chore(release): 4.0.0-dev.6 [skip ci]
# [4.0.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.5...v4.0.0-dev.6) (2024-01-09)

### Features

* **Tiktok - Playback speed:** Remember playback speed ([#2506](https://github.com/ReVanced/revanced-patches/issues/2506)) ([806e944](806e94481c))
2024-01-09 19:12:34 +00:00
d4rkk3y
806e94481c feat(Tiktok - Playback speed): Remember playback speed (#2506)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-01-09 20:10:29 +01:00
semantic-release-bot
edcb6eac6d chore(release): 4.0.0-dev.5 [skip ci]
# [4.0.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.4...v4.0.0-dev.5) (2024-01-09)

### Bug Fixes

* **YouTube - Change header:** Improve patch descriptions ([#2581](https://github.com/ReVanced/revanced-patches/issues/2581)) ([62c9085](62c9085096))
2024-01-09 19:09:58 +00:00
LisoUseInAIKyrios
4dced95d54 refactor(YouTube - Return YouTube Dislike): Make patch more robust by removing opcode patterns from fingerprints (#2602) 2024-01-09 23:08:01 +04:00
KobeW50
62c9085096 fix(YouTube - Change header): Improve patch descriptions (#2581) 2024-01-09 20:07:11 +01:00
semantic-release-bot
50a9f09703 chore(release): 4.0.0-dev.4 [skip ci]
# [4.0.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.3...v4.0.0-dev.4) (2024-01-09)

### Features

* **MyFitnessPal:** Add `Hide ads` patch ([#2594](https://github.com/ReVanced/revanced-patches/issues/2594)) ([9633b4e](9633b4eef0))
2024-01-09 17:28:21 +00:00
mrwedders
9633b4eef0 feat(MyFitnessPal): Add Hide ads patch (#2594)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-01-09 18:26:15 +01:00
semantic-release-bot
2a94ad681c chore(release): 4.0.0-dev.3 [skip ci]
# [4.0.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.2...v4.0.0-dev.3) (2024-01-09)

### Features

* **Change package name:** Mention caveat of the patch in the description ([9e79e9e](9e79e9e72c))
2024-01-09 15:41:21 +00:00
oSumAtrIX
9e79e9e72c feat(Change package name): Mention caveat of the patch in the description 2024-01-09 16:39:23 +01:00
LisoUseInAIKyrios
429badef1a fix:(YouTube - Spoof app version): Adjust spoof target description (#2578) 2024-01-03 19:14:32 +04:00
semantic-release-bot
138b2f8960 chore(release): 4.0.0-dev.2 [skip ci]
# [4.0.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.1...v4.0.0-dev.2) (2024-01-02)

### Features

* **YouTube - Change header:** Change to ReVanced borderless logo header by default ([#2512](https://github.com/ReVanced/revanced-patches/issues/2512)) ([60d70e5](60d70e5877))
2024-01-02 14:36:22 +00:00
oSumAtrIX
60d70e5877 feat(YouTube - Change header): Change to ReVanced borderless logo header by default (#2512)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2024-01-02 15:34:20 +01:00
semantic-release-bot
2debdc1056 chore(release): 4.0.0-dev.1 [skip ci]
# [4.0.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.2...v4.0.0-dev.1) (2024-01-01)

### Code Refactoring

* Fix package and code structure ([#2541](https://github.com/ReVanced/revanced-patches/issues/2541)) ([ad1ea46](ad1ea4661f))

### BREAKING CHANGES

* Various public APIs have changed names and packages or were removed entirely
2024-01-01 15:35:13 +00:00
oSumAtrIX
ad1ea4661f refactor: Fix package and code structure (#2541)
BREAKING CHANGE: Various public APIs have changed names and packages or were removed entirely
2024-01-01 16:33:07 +01:00
semantic-release-bot
eac46ca216 chore(release): 3.3.0-dev.2 [skip ci]
# [3.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.1...v3.3.0-dev.2) (2024-01-01)

### Features

* **YouTube:** Improve patch descriptions ([#2519](https://github.com/ReVanced/revanced-patches/issues/2519)) ([14e2c07](14e2c07329))
2024-01-01 15:31:56 +00:00
KobeW50
14e2c07329 feat(YouTube): Improve patch descriptions (#2519) 2024-01-01 16:30:04 +01:00
Caner Karaca
9175e50f5d ci: Target branch dev for Dependabot (#2564) 2023-12-29 19:29:54 +01:00
dependabot[bot]
2318c0811f build(deps): bump com.google.guava:guava from 32.1.3-jre to 33.0.0-jre (#2552)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-29 19:15:24 +01:00
dependabot[bot]
bc44eb710d build(deps): bump jvm from 1.9.21 to 1.9.22 (#2553)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-29 19:15:18 +01:00
oSumAtrIX
4bb86f9ec6 ci: Do not use any label for Dependabot 2023-12-28 22:52:17 +01:00
semantic-release-bot
387ceef6cd chore(release): 3.3.0-dev.1 [skip ci]
# [3.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v3.2.0...v3.3.0-dev.1) (2023-12-28)

### Features

* **ID Austria:** Remove constraint on any version ([#2526](https://github.com/ReVanced/revanced-patches/issues/2526)) ([5ba5926](5ba59261f2))
2023-12-28 21:40:18 +00:00
1fexd
5ba59261f2 feat(ID Austria): Remove constraint on any version (#2526) 2023-12-28 22:38:30 +01:00
semantic-release-bot
a89ab13949 chore(release): 3.2.0 [skip ci]
# [3.2.0](https://github.com/ReVanced/revanced-patches/compare/v3.1.0...v3.2.0) (2023-12-28)

### Bug Fixes

* **Spoof SIM country:** Validate patch option value correctly ([4fd77b1](4fd77b130a))
* **Tiktok - Remember clear display:** Use correct name ([2c83b86](2c83b86297))
* **YouTube - Alternative thumbnails:** Clarify DeArrow support is for thumbnails ([#2531](https://github.com/ReVanced/revanced-patches/issues/2531)) ([47f2de4](47f2de4bc8))
* **YouTube - SponsorBlock:** Export local statistics with saved settings ([b9ee462](b9ee4625b6))
* **YouTube:** Fix grammer mistakes in patch descriptions ([#2543](https://github.com/ReVanced/revanced-patches/issues/2543)) ([9148bdf](9148bdfd1c))

### Features

* **Public API:** Deprecate `HideEmailAddressPatch` ([8ad9d7d](8ad9d7dedd))
* **Public API:** Make `BottomControlsResource#addControls` public ([#2514](https://github.com/ReVanced/revanced-patches/issues/2514)) ([26565fd](26565fdb91))
* **Tiktok:** Add `Remember clear mode` patch ([#2509](https://github.com/ReVanced/revanced-patches/issues/2509)) ([fcacd0f](fcacd0f30d))
* **YouTube - Hide ads:** Hide fullscreen ads ([b12a14c](b12a14c4d0))
* **YouTube - Hide layout components:** Hide search result recommendations ([4408209](44082095ba))
* **YouTube - Theme:** Add classic dark color to presets ([#2542](https://github.com/ReVanced/revanced-patches/issues/2542)) ([1ecb6b2](1ecb6b2a6c))
* **YouTube:** Add `Remove viewer discretion dialog` patch ([21136d7](21136d76cd))
* **YouTube:** Remove `Hide email address` patch ([b81c999](b81c99920b))
2023-12-28 21:32:40 +00:00
oSumAtrIX
ef3932c8e6 chore: Merge branch dev to main 2023-12-28 22:30:37 +01:00
semantic-release-bot
9d3dd4d50a chore(release): 3.2.0-dev.9 [skip ci]
# [3.2.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.8...v3.2.0-dev.9) (2023-12-27)

### Features

* **YouTube - Theme:** Add classic dark color to presets ([#2542](https://github.com/ReVanced/revanced-patches/issues/2542)) ([1ecb6b2](1ecb6b2a6c))
* **YouTube:** Add `Remove viewer discretion dialog` patch ([21136d7](21136d76cd))
2023-12-27 04:43:49 +00:00
kitadai31
1ecb6b2a6c feat(YouTube - Theme): Add classic dark color to presets (#2542)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-12-27 05:41:52 +01:00
oSumAtrIX
21136d76cd feat(YouTube): Add Remove viewer discretion dialog patch 2023-12-27 05:39:27 +01:00
semantic-release-bot
c4b3d0fde0 chore(release): 3.2.0-dev.8 [skip ci]
# [3.2.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.7...v3.2.0-dev.8) (2023-12-26)

### Bug Fixes

* **YouTube:** Fix grammer mistakes in patch descriptions ([#2543](https://github.com/ReVanced/revanced-patches/issues/2543)) ([9148bdf](9148bdfd1c))
2023-12-26 23:10:12 +00:00
KobeW50
9148bdfd1c fix(YouTube): Fix grammer mistakes in patch descriptions (#2543) 2023-12-27 00:08:15 +01:00
semantic-release-bot
e2b2b7424b chore(release): 3.2.0-dev.7 [skip ci]
# [3.2.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.6...v3.2.0-dev.7) (2023-12-24)

### Features

* **YouTube - Hide ads:** Hide fullscreen ads ([b12a14c](b12a14c4d0))
* **YouTube - Hide layout components:** Hide search result recommendations ([4408209](44082095ba))
2023-12-24 17:40:36 +00:00
oSumAtrIX
b12a14c4d0 feat(YouTube - Hide ads): Hide fullscreen ads 2023-12-24 18:38:34 +01:00
oSumAtrIX
44082095ba feat(YouTube - Hide layout components): Hide search result recommendations 2023-12-24 18:07:01 +01:00
semantic-release-bot
987e4e7e91 chore(release): 3.2.0-dev.6 [skip ci]
# [3.2.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.5...v3.2.0-dev.6) (2023-12-24)

### Bug Fixes

* **Spoof SIM country:** Validate patch option value correctly ([4fd77b1](4fd77b130a))
2023-12-24 12:41:57 +00:00
oSumAtrIX
4fd77b130a fix(Spoof SIM country): Validate patch option value correctly 2023-12-24 13:39:59 +01:00
semantic-release-bot
47aa56a06e chore(release): 3.2.0-dev.5 [skip ci]
# [3.2.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.4...v3.2.0-dev.5) (2023-12-23)

### Bug Fixes

* **YouTube - Alternative thumbnails:** Clarify DeArrow support is for thumbnails ([#2531](https://github.com/ReVanced/revanced-patches/issues/2531)) ([47f2de4](47f2de4bc8))
2023-12-23 07:49:58 +00:00
Ajay Ramachandran
47f2de4bc8 fix(YouTube - Alternative thumbnails): Clarify DeArrow support is for thumbnails (#2531) 2023-12-23 11:48:06 +04:00
oSumAtrIX
36b929c3b3 refactor(Spoof SIM country): Use existing function to register patch option 2023-12-22 03:30:27 +01:00
oSumAtrIX
7109d8e088 refactor(Spoof SIM country): Reduce code duplication 2023-12-22 03:20:55 +01:00
semantic-release-bot
c91df0f29c chore(release): 3.2.0-dev.4 [skip ci]
# [3.2.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.3...v3.2.0-dev.4) (2023-12-21)

### Bug Fixes

* **Tiktok - Remember clear display:** Use correct name ([2c83b86](2c83b86297))
2023-12-21 14:34:43 +00:00
oSumAtrIX
2c83b86297 fix(Tiktok - Remember clear display): Use correct name 2023-12-21 15:32:18 +01:00
189 changed files with 1194 additions and 747 deletions

View File

@@ -1,16 +1,22 @@
version: 2
updates:
- package-ecosystem: github-actions
labels: []
directory: /
target-branch: dev
schedule:
interval: monthly
- package-ecosystem: npm
labels: []
directory: /
target-branch: dev
schedule:
interval: monthly
- package-ecosystem: gradle
labels: []
directory: /
target-branch: dev
schedule:
interval: monthly

View File

@@ -1,3 +1,131 @@
# [4.0.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.5...v4.0.0-dev.6) (2024-01-09)
### Features
* **Tiktok - Playback speed:** Remember playback speed ([#2506](https://github.com/ReVanced/revanced-patches/issues/2506)) ([d2970e5](https://github.com/ReVanced/revanced-patches/commit/d2970e54fbbd7e4b1ae1d354ae2d5c4bbe9336b0))
# [4.0.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.4...v4.0.0-dev.5) (2024-01-09)
### Bug Fixes
* **YouTube - Change header:** Improve patch descriptions ([#2581](https://github.com/ReVanced/revanced-patches/issues/2581)) ([43a5677](https://github.com/ReVanced/revanced-patches/commit/43a5677397380f14a049ae95532fd5096b94c938))
# [4.0.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.3...v4.0.0-dev.4) (2024-01-09)
### Features
* **MyFitnessPal:** Add `Hide ads` patch ([#2594](https://github.com/ReVanced/revanced-patches/issues/2594)) ([fd4b3c7](https://github.com/ReVanced/revanced-patches/commit/fd4b3c79a83f8de6256611629263d3e29e66f2c2))
# [4.0.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.2...v4.0.0-dev.3) (2024-01-09)
### Features
* **Change package name:** Mention caveat of the patch in the description ([427b81a](https://github.com/ReVanced/revanced-patches/commit/427b81a79a5a1de79f14d2261059fb098b22227f))
# [4.0.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.0.0-dev.1...v4.0.0-dev.2) (2024-01-02)
### Features
* **YouTube - Change header:** Change to ReVanced borderless logo header by default ([#2512](https://github.com/ReVanced/revanced-patches/issues/2512)) ([75f785d](https://github.com/ReVanced/revanced-patches/commit/75f785d1ef6026cbbdf7073c10aace1b28d93a30))
# [4.0.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.2...v4.0.0-dev.1) (2024-01-01)
### Code Refactoring
* Fix package and code structure ([#2541](https://github.com/ReVanced/revanced-patches/issues/2541)) ([a08457e](https://github.com/ReVanced/revanced-patches/commit/a08457e406f4b2e37458a4835c11d370a02d2ce6))
### BREAKING CHANGES
* Various public APIs have changed names and packages or were removed entirely
# [3.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v3.3.0-dev.1...v3.3.0-dev.2) (2024-01-01)
### Features
* **YouTube:** Improve patch descriptions ([#2519](https://github.com/ReVanced/revanced-patches/issues/2519)) ([e8d1389](https://github.com/ReVanced/revanced-patches/commit/e8d1389d3367b2fb688f0b85c136c512981b4fdc))
# [3.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v3.2.0...v3.3.0-dev.1) (2023-12-28)
### Features
* **ID Austria:** Remove constraint on any version ([#2526](https://github.com/ReVanced/revanced-patches/issues/2526)) ([de2cb88](https://github.com/ReVanced/revanced-patches/commit/de2cb886169b3963b9ed70154bde0b7c6baaae40))
# [3.2.0](https://github.com/ReVanced/revanced-patches/compare/v3.1.0...v3.2.0) (2023-12-28)
### Bug Fixes
* **Spoof SIM country:** Validate patch option value correctly ([8105463](https://github.com/ReVanced/revanced-patches/commit/81054637915a5399d15f546b2290b5d939e15732))
* **Tiktok - Remember clear display:** Use correct name ([d7e44cb](https://github.com/ReVanced/revanced-patches/commit/d7e44cb887396bba27ee81c70c006f0cc247c56d))
* **YouTube - Alternative thumbnails:** Clarify DeArrow support is for thumbnails ([#2531](https://github.com/ReVanced/revanced-patches/issues/2531)) ([828abb0](https://github.com/ReVanced/revanced-patches/commit/828abb0558926cd6557c79abcf1a04bfe2c719e6))
* **YouTube - SponsorBlock:** Export local statistics with saved settings ([f8365b4](https://github.com/ReVanced/revanced-patches/commit/f8365b4e3585328506887022ac6168045ac110b9))
* **YouTube:** Fix grammer mistakes in patch descriptions ([#2543](https://github.com/ReVanced/revanced-patches/issues/2543)) ([ebf5993](https://github.com/ReVanced/revanced-patches/commit/ebf599349c508067a28526267d82030b679df045))
### Features
* **Public API:** Deprecate `HideEmailAddressPatch` ([866bceb](https://github.com/ReVanced/revanced-patches/commit/866bcebdd990b964d3dfd5aea792e7fffaedbf44))
* **Public API:** Make `BottomControlsResource#addControls` public ([#2514](https://github.com/ReVanced/revanced-patches/issues/2514)) ([f4e2257](https://github.com/ReVanced/revanced-patches/commit/f4e2257072ca02003f7c272d6c0c8ef1aa6032ae))
* **Tiktok:** Add `Remember clear mode` patch ([#2509](https://github.com/ReVanced/revanced-patches/issues/2509)) ([048bf59](https://github.com/ReVanced/revanced-patches/commit/048bf592ef93ee5138aa1886be1644501f88964a))
* **YouTube - Hide ads:** Hide fullscreen ads ([bdc9a12](https://github.com/ReVanced/revanced-patches/commit/bdc9a129eff3a5051b8b37665b3243a8b61cbbac))
* **YouTube - Hide layout components:** Hide search result recommendations ([55cc7f1](https://github.com/ReVanced/revanced-patches/commit/55cc7f1c7722f56af6d33ea2bd09a1b99d635209))
* **YouTube - Theme:** Add classic dark color to presets ([#2542](https://github.com/ReVanced/revanced-patches/issues/2542)) ([4e1dc00](https://github.com/ReVanced/revanced-patches/commit/4e1dc0041d6693fba08e78514787407f933a6e41))
* **YouTube:** Add `Remove viewer discretion dialog` patch ([a07f83f](https://github.com/ReVanced/revanced-patches/commit/a07f83fe89ce577fc8bd904eacad5383a639b09b))
* **YouTube:** Remove `Hide email address` patch ([3b84305](https://github.com/ReVanced/revanced-patches/commit/3b84305a6b97800cb147f86c642f19689548aca5))
# [3.2.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.8...v3.2.0-dev.9) (2023-12-27)
### Features
* **YouTube - Theme:** Add classic dark color to presets ([#2542](https://github.com/ReVanced/revanced-patches/issues/2542)) ([4e1dc00](https://github.com/ReVanced/revanced-patches/commit/4e1dc0041d6693fba08e78514787407f933a6e41))
* **YouTube:** Add `Remove viewer discretion dialog` patch ([a07f83f](https://github.com/ReVanced/revanced-patches/commit/a07f83fe89ce577fc8bd904eacad5383a639b09b))
# [3.2.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.7...v3.2.0-dev.8) (2023-12-26)
### Bug Fixes
* **YouTube:** Fix grammer mistakes in patch descriptions ([#2543](https://github.com/ReVanced/revanced-patches/issues/2543)) ([ebf5993](https://github.com/ReVanced/revanced-patches/commit/ebf599349c508067a28526267d82030b679df045))
# [3.2.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.6...v3.2.0-dev.7) (2023-12-24)
### Features
* **YouTube - Hide ads:** Hide fullscreen ads ([bdc9a12](https://github.com/ReVanced/revanced-patches/commit/bdc9a129eff3a5051b8b37665b3243a8b61cbbac))
* **YouTube - Hide layout components:** Hide search result recommendations ([55cc7f1](https://github.com/ReVanced/revanced-patches/commit/55cc7f1c7722f56af6d33ea2bd09a1b99d635209))
# [3.2.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.5...v3.2.0-dev.6) (2023-12-24)
### Bug Fixes
* **Spoof SIM country:** Validate patch option value correctly ([8105463](https://github.com/ReVanced/revanced-patches/commit/81054637915a5399d15f546b2290b5d939e15732))
# [3.2.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.4...v3.2.0-dev.5) (2023-12-23)
### Bug Fixes
* **YouTube - Alternative thumbnails:** Clarify DeArrow support is for thumbnails ([#2531](https://github.com/ReVanced/revanced-patches/issues/2531)) ([828abb0](https://github.com/ReVanced/revanced-patches/commit/828abb0558926cd6557c79abcf1a04bfe2c719e6))
# [3.2.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.3...v3.2.0-dev.4) (2023-12-21)
### Bug Fixes
* **Tiktok - Remember clear display:** Use correct name ([d7e44cb](https://github.com/ReVanced/revanced-patches/commit/d7e44cb887396bba27ee81c70c006f0cc247c56d))
# [3.2.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v3.2.0-dev.2...v3.2.0-dev.3) (2023-12-21)

View File

@@ -333,6 +333,20 @@ public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatch : app
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/myfitnesspal/ads/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/myfitnesspal/ads/HideAdsPatch;
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/myfitnesspal/ads/fingerprints/IsPremiumUseCaseImplFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
public static final field INSTANCE Lapp/revanced/patches/myfitnesspal/ads/fingerprints/IsPremiumUseCaseImplFingerprint;
}
public final class app/revanced/patches/myfitnesspal/ads/fingerprints/MainActivityNavigateToNativePremiumUpsellFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
public static final field INSTANCE Lapp/revanced/patches/myfitnesspal/ads/fingerprints/MainActivityNavigateToNativePremiumUpsellFingerprint;
}
public final class app/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/netguard/broadcasts/removerestriction/RemoveBroadcastsRestrictionPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
@@ -525,6 +539,7 @@ public final class app/revanced/patches/shared/fingerprints/HomeActivityFingerpr
public abstract class app/revanced/patches/shared/integrations/AbstractIntegrationsPatch : app/revanced/patcher/patch/BytecodePatch {
public fun <init> (Ljava/lang/String;Ljava/util/Set;)V
public fun <init> (Ljava/util/Set;)V
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
@@ -616,13 +631,6 @@ public abstract class app/revanced/patches/shared/settings/preference/BaseResour
public static synthetic fun serialize$default (Lapp/revanced/patches/shared/settings/preference/BaseResource;Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/w3c/dom/Element;
}
public abstract class app/revanced/patches/shared/settings/preference/DefaultBasePreference : app/revanced/patches/shared/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;Ljava/lang/Object;)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getDefault ()Ljava/lang/Object;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
public final class app/revanced/patches/shared/settings/preference/SummaryType : java/lang/Enum {
public static final field DEFAULT Lapp/revanced/patches/shared/settings/preference/SummaryType;
public static final field OFF Lapp/revanced/patches/shared/settings/preference/SummaryType;
@@ -650,11 +658,9 @@ public final class app/revanced/patches/shared/settings/preference/impl/InputTyp
public static fun values ()[Lapp/revanced/patches/shared/settings/preference/impl/InputType;
}
public final class app/revanced/patches/shared/settings/preference/impl/ListPreference : app/revanced/patches/shared/settings/preference/DefaultBasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getEntries ()Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;
public final fun getEntryValues ()Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;
public final class app/revanced/patches/shared/settings/preference/impl/ListPreference : app/revanced/patches/shared/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/ArrayResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
@@ -700,18 +706,18 @@ public final class app/revanced/patches/shared/settings/preference/impl/StringRe
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
public final class app/revanced/patches/shared/settings/preference/impl/SwitchPreference : app/revanced/patches/shared/settings/preference/DefaultBasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Z)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final class app/revanced/patches/shared/settings/preference/impl/SwitchPreference : app/revanced/patches/shared/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getSummaryOff ()Lapp/revanced/patches/shared/settings/preference/impl/StringResource;
public final fun getSummaryOn ()Lapp/revanced/patches/shared/settings/preference/impl/StringResource;
public final fun getUserDialogMessage ()Lapp/revanced/patches/shared/settings/preference/impl/StringResource;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
public final class app/revanced/patches/shared/settings/preference/impl/TextPreference : app/revanced/patches/shared/settings/preference/DefaultBasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final class app/revanced/patches/shared/settings/preference/impl/TextPreference : app/revanced/patches/shared/settings/preference/BasePreference {
public fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/StringResource;Lapp/revanced/patches/shared/settings/preference/impl/InputType;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getInputType ()Lapp/revanced/patches/shared/settings/preference/impl/InputType;
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
}
@@ -818,8 +824,8 @@ public final class app/revanced/patches/tiktok/feedfilter/FeedFilterPatch : app/
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/tiktok/interaction/clearmode/RememberClearModePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/tiktok/interaction/clearmode/RememberClearModePatch;
public final class app/revanced/patches/tiktok/interaction/cleardisplay/RememberClearDisplayPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/tiktok/interaction/cleardisplay/RememberClearDisplayPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
@@ -1088,6 +1094,12 @@ public final class app/revanced/patches/youtube/interaction/copyvideourl/CopyVid
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch;
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/youtube/interaction/downloads/ExternalDownloadsBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1130,6 +1142,12 @@ public final class app/revanced/patches/youtube/layout/branding/CustomBrandingPa
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
}
public final class app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
}
public final class app/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/branding/header/PremiumHeadingPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V

View File

@@ -1,7 +1,7 @@
import org.gradle.kotlin.dsl.support.listFilesOrdered
plugins {
kotlin("jvm") version "1.9.21"
kotlin("jvm") version "1.9.22"
alias(libs.plugins.binary.compatibility.validator)
`maven-publish`
}

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 3.2.0-dev.3
version = 4.0.0-dev.6

View File

@@ -1,7 +1,7 @@
[versions]
revanced-patcher = "19.1.0"
smali = "3.0.3"
guava = "32.1.3-jre"
guava = "33.0.0-jre"
gson = "2.10.1"
binary-compatibility-validator = "0.13.2"

File diff suppressed because one or more lines are too long

View File

@@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
)
@Suppress("unused")
object SpoofWifiPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch"
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/integrations/all/connectivity/wifi/spoof/SpoofWifiPatch"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
override fun filterMap(

View File

@@ -10,7 +10,7 @@ import java.io.Closeable
@Patch(
name = "Change package name",
description = "Appends \".revanced\" to the package name by default.",
description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.",
use = false
)
@Suppress("unused")
@@ -59,4 +59,4 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
manifest.setAttribute("package", replacementPackageName)
}
}
}

View File

@@ -10,7 +10,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@Suppress("MemberVisibilityCanBePrivate")
abstract class AbstractTransformInstructionsPatch<T> : BytecodePatch() {
abstract fun filterMap(
classDef: ClassDef,
method: Method,

View File

@@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@Suppress("unused")
object RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
"Lapp/revanced/integrations/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
// Information about method calls we want to replace
enum class MethodCall(

View File

@@ -24,7 +24,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Suppress("unused")
object RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
private const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
"Lapp/revanced/integrations/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
override fun execute(context: BytecodeContext) {

View File

@@ -3,7 +3,6 @@ package app.revanced.patches.all.telephony.sim.spoof
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.AbstractTransformInstructionsPatch
@@ -25,26 +24,29 @@ import java.util.*
)
@Suppress("unused")
object SpoofSimCountryPatch : AbstractTransformInstructionsPatch<Pair<Int, String>>() {
private val isoValidator: PatchOption<String>.(String?) -> Boolean =
{ it: String? -> it?.uppercase() in Locale.getISOCountries() || it == null }
private val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }
private val networkCountryIso by stringPatchOption(
private val networkCountryIso by isoCountryPatchOption(
"networkCountryIso",
null,
null,
"Network ISO Country Code",
"ISO-3166-1 alpha-2 country code equivalent of the MCC (Mobile Country Code) " +
"of the current registered operator or the cell nearby.",
validator = isoValidator
)
private val simCountryIso by stringPatchOption(
private val simCountryIso by isoCountryPatchOption(
"simCountryIso",
null,
null,
"Sim ISO Country Code",
)
private fun isoCountryPatchOption(
key: String,
title: String,
) = stringPatchOption(
key,
null,
countries,
title,
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
validator = isoValidator
false,
validator = { it: String? -> it == null || it.uppercase() in countries.values }
)
override fun filterMap(

View File

@@ -12,7 +12,7 @@ import app.revanced.util.returnEarly
@Patch(
name = "Remove root detection",
description = "Removes the check for root permissions and unlocked bootloader.",
compatiblePackages = [CompatiblePackage("at.gv.oe.app", ["3.0.2"])]
compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
)
@Suppress("unused")
object RootDetectionPatch : BytecodePatch(

View File

@@ -10,7 +10,7 @@ import app.revanced.patches.idaustria.detection.signature.fingerprints.SpoofSign
@Patch(
name = "Spoof signature",
description = "Spoofs the signature of the app.",
compatiblePackages = [CompatiblePackage("at.gv.oe.app", ["3.0.2"])]
compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
)
@Suppress("unused")
object SpoofSignaturePatch : BytecodePatch(

View File

@@ -0,0 +1,38 @@
package app.revanced.patches.myfitnesspal.ads
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.myfitnesspal.ads.fingerprints.IsPremiumUseCaseImplFingerprint
import app.revanced.patches.myfitnesspal.ads.fingerprints.MainActivityNavigateToNativePremiumUpsellFingerprint
import app.revanced.util.exception
@Patch(
name = "Hide ads",
description = "Hides most of the ads across the app.",
compatiblePackages = [CompatiblePackage("com.myfitnesspal.android")]
)
@Suppress("unused")
object HideAdsPatch : BytecodePatch(
setOf(IsPremiumUseCaseImplFingerprint, MainActivityNavigateToNativePremiumUpsellFingerprint)
) {
override fun execute(context: BytecodeContext) {
// Overwrite the premium status specifically for ads.
IsPremiumUseCaseImplFingerprint.result?.mutableMethod?.replaceInstructions(
0,
"""
sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;
return-object v0
"""
) ?: throw IsPremiumUseCaseImplFingerprint.exception
// Prevent the premium upsell dialog from showing when the main activity is launched.
// In other places that are premium-only the dialog will still show.
MainActivityNavigateToNativePremiumUpsellFingerprint.result?.mutableMethod?.replaceInstructions(
0,
"return-void"
) ?: throw MainActivityNavigateToNativePremiumUpsellFingerprint.exception
}
}

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.myfitnesspal.ads.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object IsPremiumUseCaseImplFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC.value,
customFingerprint = { methodDef, classDef ->
classDef.type.endsWith("IsPremiumUseCaseImpl;") && methodDef.name == "doWork"
}
)

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.myfitnesspal.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object MainActivityNavigateToNativePremiumUpsellFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
customFingerprint = { methodDef, classDef ->
classDef.type.endsWith("MainActivity;") && methodDef.name == "navigateToNativePremiumUpsell"
}
)

View File

@@ -26,7 +26,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Suppress("unused")
object HideAdsPatch : BytecodePatch(setOf(AdPostFingerprint, NewAdPostFingerprint)) {
private const val FILTER_METHOD_DESCRIPTOR =
"Lapp/revanced/reddit/patches/FilterPromotedLinksPatch;" +
"Lapp/revanced/integrations/reddit/patches/FilterPromotedLinksPatch;" +
"->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;"
override fun execute(context: BytecodeContext) {

View File

@@ -11,9 +11,27 @@ import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
abstract class AbstractIntegrationsPatch(
private val integrationsDescriptor: String,
private val hooks: Set<IntegrationsFingerprint>
) : BytecodePatch(hooks) {
@Deprecated(
"Use the constructor without the integrationsDescriptor parameter",
ReplaceWith("AbstractIntegrationsPatch(hooks)")
)
@Suppress("UNUSED_PARAMETER")
constructor(
integrationsDescriptor: String,
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."
)
for (hook in hooks) hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR)
}
/**
* [MethodFingerprint] for integrations.
*
@@ -53,11 +71,7 @@ abstract class AbstractIntegrationsPatch(
}
}
override fun execute(context: BytecodeContext) {
if (context.findClass(integrationsDescriptor) == null) throw PatchException(
"Integrations have not been merged yet. This patch can not succeed without merging the integrations."
)
for (hook in hooks) hook.invoke(integrationsDescriptor)
private companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/shared/Utils;"
}
}

View File

@@ -24,7 +24,7 @@ import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringRefere
import com.android.tools.smali.dexlib2.util.MethodUtil
/**
* A patch that allows Google apps to run without root and under a different package name
* A patch that allows patched Google apps to run without root and under a different package name
* by using GmsCore instead of Google Play Services.
*
* @param fromPackageName The package name of the original app.
@@ -47,7 +47,7 @@ abstract class AbstractGmsCoreSupportPatch(
fingerprints: Set<MethodFingerprint> = emptySet(),
) : BytecodePatch(
name = "GmsCore support",
description = "Allows Google apps to run without root and under a different package name " +
description = "Allows patched Google apps to run without root and under a different package name " +
"by using GmsCore instead of Google Play Services.",
dependencies = setOf(ChangePackageNamePatch::class, abstractGmsCoreSupportResourcePatch::class) + dependencies,
compatiblePackages = compatiblePackages,

View File

@@ -11,6 +11,7 @@ import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
import app.revanced.util.mergeStrings
import org.w3c.dom.Node
import java.io.Closeable
@@ -37,6 +38,8 @@ abstract class AbstractSettingsResourcePatch(
stringsEditor = context.xmlEditor["res/values/strings.xml"]
arraysEditor = context.xmlEditor["res/values/arrays.xml"]
revancedPreferencesEditor = context.xmlEditor["res/xml/$preferenceFileName.xml"]
context.mergeStrings("settings/host/values/strings.xml")
}
internal companion object {

View File

@@ -1,32 +0,0 @@
package app.revanced.patches.shared.settings.preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import org.w3c.dom.Document
/**
* Base preference class that also has a default value.
*
* @param key The key of the preference.
* @param title The title of the preference.
* @param tag The tag of the preference.
* @param summary The summary of the preference.
* @param default The default value of the preference.
*/
abstract class DefaultBasePreference<T>(
key: String?,
title: StringResource,
summary: StringResource? = null,
tag: String,
val default: T? = null,
) : BasePreference(key, title, summary, tag) {
/**
* Serialize preference element to XML.
* Overriding methods should invoke super and operate on its return value.
* @param ownerDocument Target document to create elements from.
* @param resourceCallback Called when a resource has been processed.
* @return The serialized element.
*/
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply { addDefault(default) }
}

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BasePreference
import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
import app.revanced.patches.shared.settings.preference.addSummary
import org.w3c.dom.Document
@@ -13,16 +13,14 @@ import org.w3c.dom.Document
* @param entries The human-readable entries of the list preference.
* @param entryValues The entry values of the list preference.
* @param summary The summary of the list preference.
* @param default The default entry value of the list preference.
*/
class ListPreference(
key: String,
title: StringResource,
val entries: ArrayResource,
val entryValues: ArrayResource,
summary: StringResource? = null,
default: String? = null,
) : DefaultBasePreference<String>(key, title, summary, "ListPreference", default) {
private val entries: ArrayResource,
private val entryValues: ArrayResource,
summary: StringResource? = null
) : BasePreference(key, title, summary, "ListPreference") {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {
setAttribute("android:entries", "@array/${entries.also { resourceCallback.invoke(it) }.name}")

View File

@@ -1,10 +1,10 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch.Companion.include
import app.revanced.patches.shared.settings.preference.BasePreference
import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
import app.revanced.patches.shared.settings.preference.SummaryType
import app.revanced.patches.shared.settings.preference.addSummary
import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch.Companion.include
import org.w3c.dom.Document
import org.w3c.dom.Element
@@ -16,15 +16,13 @@ import org.w3c.dom.Element
* @param summaryOn The summary to show when the preference is enabled.
* @param summaryOff The summary to show when the preference is disabled.
* @param userDialogMessage The message to show in a dialog when the user toggles the preference.
* @param default The default value of the switch.
*/
class SwitchPreference(
key: String, title: StringResource,
val summaryOn: StringResource,
val summaryOff: StringResource,
val userDialogMessage: StringResource? = null,
default: Boolean = false,
) : DefaultBasePreference<Boolean>( key, title, null, "SwitchPreference", default) {
) : BasePreference(key, title, null, "SwitchPreference") {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit): Element {
userDialogMessage?.include()

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BasePreference
import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.DefaultBasePreference
import org.w3c.dom.Document
/**
@@ -11,16 +11,14 @@ import org.w3c.dom.Document
* @param title The title of the text preference.
* @param inputType The input type of the text preference.
* @param summary The summary of the text preference.
* @param default The default value of the text preference.
*/
class TextPreference(
key: String?,
title: StringResource,
summary: StringResource?,
val inputType: InputType = InputType.TEXT,
default: String? = null,
tag: String = "app.revanced.integrations.settingsmenu.ResettableEditTextPreference"
) : DefaultBasePreference<String>(key, title, summary, tag, default) {
tag: String = "app.revanced.integrations.shared.settings.preference.ResettableEditTextPreference"
) : BasePreference(key, title, summary, tag) {
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
super.serialize(ownerDocument, resourceCallback).apply {

View File

@@ -36,13 +36,13 @@ object FeedFilterPatch : BytecodePatch(
addInstruction(
returnFeedItemInstruction.location.index,
"invoke-static { v$feedItemsRegister }, " +
"Lapp/revanced/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V"
"Lapp/revanced/integrations/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V"
)
} ?: throw FeedApiServiceLIZFingerprint.exception
SettingsStatusLoadFingerprint.result?.mutableMethod?.addInstruction(
0,
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableFeedFilter()V"
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableFeedFilter()V"
) ?: throw SettingsStatusLoadFingerprint.exception
}
}

View File

@@ -0,0 +1,79 @@
package app.revanced.patches.tiktok.interaction.cleardisplay
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.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.tiktok.interaction.cleardisplay.fingerprints.OnClearDisplayEventFingerprint
import app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints.OnRenderFirstFrameFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
@Patch(
name = "Remember clear display",
description = "Remembers the clear display configurations in between videos.",
compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
]
)
@Suppress("unused")
object RememberClearDisplayPatch : BytecodePatch(
setOf(
OnClearDisplayEventFingerprint,
OnRenderFirstFrameFingerprint
)
) {
override fun execute(context: BytecodeContext) {
OnClearDisplayEventFingerprint.result?.mutableMethod?.let {
// region Hook the "Clear display" configuration save event to remember the state of clear display.
val isEnabledIndex = it.indexOfFirstInstruction { opcode == Opcode.IGET_BOOLEAN } + 1
val isEnabledRegister = it.getInstruction<Instruction22c>(isEnabledIndex - 1).registerA
it.addInstructions(
isEnabledIndex,
"invoke-static { v$isEnabledRegister }, " +
"Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V"
)
// endregion
// region Override the "Clear display" configuration load event to load the state of clear display.
val clearDisplayEventClass = it.parameters[0].type
OnRenderFirstFrameFingerprint.result?.mutableMethod?.apply {
addInstructionsWithLabels(
0,
"""
# Create a new clearDisplayEvent and post it to the EventBus (https://github.com/greenrobot/EventBus)
# The state of clear display.
invoke-static { }, Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->getClearDisplayState()Z
move-result v3
if-eqz v3, :clear_display_disabled
# Clear display type such as 0 = LONG_PRESS, 1 = SCREEN_RECORD etc.
const/4 v1, 0x0
# Name of the clear display type which is equivalent to the clear display type.
const-string v2, "long_press"
new-instance v0, $clearDisplayEventClass
invoke-direct { v0, v1, v2, v3 }, $clearDisplayEventClass-><init>(ILjava/lang/String;Z)V
invoke-virtual { v0 }, $clearDisplayEventClass->post()Lcom/ss/android/ugc/governance/eventbus/IEvent;
""",
ExternalLabel("clear_display_disabled", getInstruction(0))
)
} ?: throw OnRenderFirstFrameFingerprint.exception
// endregion
} ?: throw OnClearDisplayEventFingerprint.exception
}
}

View File

@@ -1,9 +1,10 @@
package app.revanced.patches.tiktok.interaction.clearmode.fingerprints
package app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object OnClearModeEventFingerprint : MethodFingerprint(
internal object OnClearDisplayEventFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
// Internally the feature is called "Clear mode".
methodDef.definingClass.endsWith("/ClearModePanelComponent;") && methodDef.name == "onClearModeEvent"
}
)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object OnRenderFirstFrameFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame"
}
)

View File

@@ -1,79 +0,0 @@
package app.revanced.patches.tiktok.interaction.clearmode
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.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.tiktok.interaction.clearmode.fingerprints.OnClearModeEventFingerprint
import app.revanced.patches.tiktok.interaction.clearmode.fingerprints.OnRenderFirstFrameFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
@Patch(
name = "Remember clear mode",
description = "Remembers the clear mode configurations in between videos.",
compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
]
)
@Suppress("unused")
object RememberClearModePatch : BytecodePatch(
setOf(
OnClearModeEventFingerprint,
OnRenderFirstFrameFingerprint
)
) {
override fun execute(context: BytecodeContext) {
OnClearModeEventFingerprint.result?.mutableMethod?.let {
// region Hook the "Clear mode" configuration save event to remember the state of clear mode.
val isEnabledIndex = it.indexOfFirstInstruction { opcode == Opcode.IGET_BOOLEAN } + 1
val isEnabledRegister = it.getInstruction<Instruction22c>(isEnabledIndex - 1).registerA
it.addInstructions(
isEnabledIndex,
"invoke-static { v$isEnabledRegister }, " +
"Lapp/revanced/tiktok/clearmode/RememberClearModePatch;->rememberClearModeState(Z)V"
)
// endregion
// region Override the "Clear mode" configuration load event to load the state of clear mode.
val clearModeEventClass = it.parameters[0].type
OnRenderFirstFrameFingerprint.result?.mutableMethod?.apply {
addInstructionsWithLabels(
0,
"""
# Create a new clearModeEvent and post it to the EventBus (https://github.com/greenrobot/EventBus)
# The state of clear mode.
invoke-static { }, Lapp/revanced/tiktok/clearmode/RememberClearModePatch;->getClearModeState()Z
move-result v3
if-eqz v3, :clear_mode_disabled
# Clear mode type such as 0 = LONG_PRESS, 1 = SCREEN_RECORD etc.
const/4 v1, 0x0
# Name of the clear mode type which is equivalent to the clear mode type.
const-string v2, "long_press"
new-instance v0, $clearModeEventClass
invoke-direct { v0, v1, v2, v3 }, $clearModeEventClass-><init>(ILjava/lang/String;Z)V
invoke-virtual { v0 }, $clearModeEventClass->post()Lcom/ss/android/ugc/governance/eventbus/IEvent;
""",
ExternalLabel("clear_mode_disabled", getInstruction(0))
)
} ?: throw OnRenderFirstFrameFingerprint.exception
// endregion
} ?: throw OnClearModeEventFingerprint.exception
}
}

View File

@@ -69,7 +69,7 @@ object DownloadsPatch : BytecodePatch(
addInstructionsWithLabels(
0,
"""
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z
move-result v0
if-eqz v0, :noremovewatermark
const/4 v0, 0x1
@@ -99,7 +99,7 @@ object DownloadsPatch : BytecodePatch(
downloadUriMethod.addInstructions(
secondIndex,
"""
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
move-result-object v0
"""
)
@@ -107,7 +107,7 @@ object DownloadsPatch : BytecodePatch(
downloadUriMethod.addInstructions(
firstIndex,
"""
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
move-result-object v0
"""
)
@@ -115,7 +115,7 @@ object DownloadsPatch : BytecodePatch(
SettingsStatusLoadFingerprint to {
addInstruction(
0,
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableDownload()V"
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableDownload()V"
)
}
).forEach { (fingerprint, patch) ->

View File

@@ -1,49 +1,82 @@
package app.revanced.patches.tiktok.interaction.speed
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.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint
import app.revanced.patches.tiktok.interaction.speed.fingerprints.GetSpeedFingerprint
import app.revanced.patches.tiktok.interaction.speed.fingerprints.OnRenderFirstFrameFingerprint
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SetSpeedFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11x
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Playback speed",
description = "Enables the playback speed option for all videos.",
description = "Enables the playback speed option for all videos and " +
"retains the speed configurations in between videos.",
compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
]
)
@Suppress("unused")
object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) {
object PlaybackSpeedPatch : BytecodePatch(
setOf(
GetSpeedFingerprint,
OnRenderFirstFrameFingerprint,
SetSpeedFingerprint
)
) {
override fun execute(context: BytecodeContext) {
SpeedControlParentFingerprint.result?.mutableMethod?.apply {
val targetMethodCallIndex = indexOfFirstInstruction {
if (opcode == Opcode.INVOKE_STATIC) {
val paramsTypes = ((this as Instruction35c).reference as MethodReference).parameterTypes
paramsTypes.size == 1 && paramsTypes[0].contains("/Aweme;")
} else false
}
SetSpeedFingerprint.result?.let { onVideoSwiped ->
// Remember the playback speed of the current video.
GetSpeedFingerprint.result?.mutableMethod?.apply {
val injectIndex = indexOfFirstInstruction { getReference<MethodReference>()?.returnType == "F" } + 2
val register = getInstruction<Instruction11x>(injectIndex - 1).registerA
val isSpeedEnableMethod = context
.toMethodWalker(this)
.nextMethod(targetMethodCallIndex, true)
.getMethod() as MutableMethod
addInstruction(
injectIndex,
"invoke-static { v$register }," +
" Lapp/revanced/tiktok/speed/SpeedPatch;->rememberPlaybackSpeed(F)V"
)
} ?: throw GetSpeedFingerprint.exception
isSpeedEnableMethod.addInstructions(
// By default, the playback speed will reset to 1.0 at the start of each video.
// Instead, override it with the desired playback speed.
OnRenderFirstFrameFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
# Video playback location (e.g. home page, following page or search result page) retrieved using getEnterFrom method.
const/4 v0, 0x1
invoke-virtual {p0, v0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getEnterFrom(Z)Ljava/lang/String;
move-result-object v0
# Model of current video retrieved using getCurrentAweme method.
invoke-virtual {p0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getCurrentAweme()Lcom/ss/android/ugc/aweme/feed/model/Aweme;
move-result-object v1
# Desired playback speed retrieved using getPlaybackSpeed method.
invoke-static {}, Lapp/revanced/tiktok/speed/SpeedPatch;->getPlaybackSpeed()F
move-result-object v2
invoke-static { v0, v1, v2 }, ${onVideoSwiped.method}
"""
) ?: throw OnRenderFirstFrameFingerprint.exception
// Force enable the playback speed option for all videos.
onVideoSwiped.mutableClass.methods.find { method -> method.returnType == "Z" }?.addInstructions(
0,
"""
)
} ?: throw SpeedControlParentFingerprint.exception
const/4 v0, 0x1
return v0
"""
) ?: throw PatchException("Failed to force enable the playback speed option.")
} ?: throw SetSpeedFingerprint.exception
}
}
}

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.tiktok.interaction.speed.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object GetSpeedFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onFeedSpeedSelectedEvent"
}
)

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.tiktok.interaction.clearmode.fingerprints
package app.revanced.patches.tiktok.interaction.speed.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
@@ -6,4 +6,4 @@ internal object OnRenderFirstFrameFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame"
}
)
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.tiktok.interaction.speed.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object SetSpeedFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf(
"Ljava/lang/String;",
"Lcom/ss/android/ugc/aweme/feed/model/Aweme;",
"F"
),
strings = listOf("enterFrom")
)

View File

@@ -1,13 +0,0 @@
package app.revanced.patches.tiktok.interaction.speed.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object SpeedControlParentFingerprint : MethodFingerprint(
strings = listOf(
"onStopTrackingTouch, hasTouchMove=",
", isCurVideoPaused: ",
"already_shown_edge_speed_guide"
)
)

View File

@@ -6,6 +6,5 @@ import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprin
@Patch(requiresIntegrations = true)
object IntegrationsPatch : AbstractIntegrationsPatch(
"Lapp/revanced/tiktok/utils/ReVancedUtils;",
setOf(InitFingerprint)
)

View File

@@ -37,10 +37,10 @@ object SettingsPatch : BytecodePatch(
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
"Lapp/revanced/integrations/tiktok/settings/AdPersonalizationActivityHook;"
private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
"$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
"$INTEGRATIONS_CLASS_DESCRIPTOR->initialize(" +
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
")Z"

View File

@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object SettingsStatusLoadFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("Lapp/revanced/tiktok/settingsmenu/SettingsStatus;") &&
methodDef.definingClass.endsWith("Lapp/revanced/integrations/tiktok/settings/SettingsStatus;") &&
methodDef.name == "load"
}
)

View File

@@ -85,7 +85,7 @@ object SpoofSimPatch : BytecodePatch() {
with(SettingsStatusLoadFingerprint.result!!.mutableMethod) {
addInstruction(
0,
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableSimSpoof()V"
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableSimSpoof()V"
)
}
}
@@ -97,7 +97,7 @@ object SpoofSimPatch : BytecodePatch() {
addInstructions(
index + 2,
"""
invoke-static {v$resultReg}, Lapp/revanced/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String;
invoke-static {v$resultReg}, Lapp/revanced/integrations/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$resultReg
"""
)

View File

@@ -25,7 +25,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
object ShowOnLockscreenPatch : BytecodePatch(
setOf(BrightnessFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch;"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/tudortmund/lockscreen/ShowOnLockscreenPatch;"
override fun execute(context: BytecodeContext) {
BrightnessFingerprint.result?.mutableMethod?.apply {

View File

@@ -60,7 +60,7 @@ object TimelineFilterPatch : BytecodePatch(
fingerprint.result?.mutableMethod?.addInstructions(
0,
"invoke-static {p$timelineObjectsRegister}, " +
"Lapp/revanced/tumblr/patches/TimelineFilterPatch;->" +
"Lapp/revanced/integrations/tumblr/patches/TimelineFilterPatch;->" +
"filterTimeline(Ljava/util/List;)V"
) ?: throw fingerprint.exception
}

View File

@@ -29,7 +29,7 @@ object AudioAdsPatch : BytecodePatch(
mutableMethod.addInstructionsWithLabels(
0,
"""
invoke-static { }, Lapp/revanced/twitch/patches/AudioAdsPatch;->shouldBlockAudioAds()Z
invoke-static { }, Lapp/revanced/integrations/twitch/patches/AudioAdsPatch;->shouldBlockAudioAds()Z
move-result v0
if-eqz v0, :show_audio_ads
return-void
@@ -52,8 +52,7 @@ object AudioAdsPatch : BytecodePatch(
StringResource(
"revanced_block_audio_ads_off",
"Audio ads are unblocked"
),
default = true,
)
)
)
}

View File

@@ -31,7 +31,7 @@ object EmbeddedAdsPatch : BytecodePatch(
result.mutableMethod.addInstructions(
3,
"""
invoke-static {}, Lapp/revanced/twitch/patches/EmbeddedAdsPatch;->createRequestInterceptor()Lapp/revanced/twitch/api/RequestInterceptor;
invoke-static {}, Lapp/revanced/integrations/twitch/patches/EmbeddedAdsPatch;->createRequestInterceptor()Lapp/revanced/integrations/twitch/api/RequestInterceptor;
move-result-object v2
invoke-virtual {v0, v2}, Lokhttp3/OkHttpClient${"$"}Builder;->addInterceptor(Lokhttp3/Interceptor;)Lokhttp3/OkHttpClient${"$"}Builder;
"""
@@ -59,8 +59,7 @@ object EmbeddedAdsPatch : BytecodePatch(
StringResource("key_revanced_proxy_luminous", "luminous"),
StringResource("key_revanced_proxy_purpleadblock", "purpleadblock")
)
),
default = "luminous"
)
)
)

View File

@@ -24,7 +24,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "16.9.1"])]
)
object VideoAdsPatch : AbstractAdPatch(
"Lapp/revanced/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z",
"Lapp/revanced/integrations/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z",
"show_video_ads",
setOf(
ContentConfigShowAdsFingerprint,
@@ -135,8 +135,7 @@ object VideoAdsPatch : AbstractAdPatch(
StringResource(
"revanced_block_video_ads_off",
"Video ads are unblocked"
),
default = true
)
)
)
}

View File

@@ -33,7 +33,7 @@ object ShowDeletedMessagesPatch : BytecodePatch(
)
) {
private fun createSpoilerConditionInstructions(register: String = "v0") = """
invoke-static {}, Lapp/revanced/twitch/patches/ShowDeletedMessagesPatch;->shouldUseSpoiler()Z
invoke-static {}, Lapp/revanced/integrations/twitch/patches/ShowDeletedMessagesPatch;->shouldUseSpoiler()Z
move-result $register
if-eqz $register, :no_spoiler
"""
@@ -61,7 +61,7 @@ object ShowDeletedMessagesPatch : BytecodePatch(
addInstructionsWithLabels(
0,
"""
invoke-static {p2}, Lapp/revanced/twitch/patches/ShowDeletedMessagesPatch;->reformatDeletedMessage(Landroid/text/Spanned;)Landroid/text/Spanned;
invoke-static {p2}, Lapp/revanced/integrations/twitch/patches/ShowDeletedMessagesPatch;->reformatDeletedMessage(Landroid/text/Spanned;)Landroid/text/Spanned;
move-result-object v0
if-eqz v0, :no_reformat
return-object v0
@@ -92,8 +92,7 @@ object ShowDeletedMessagesPatch : BytecodePatch(
StringResource("key_revanced_deleted_messages_spoiler", "spoiler"),
StringResource("key_revanced_deleted_messages_cross_out", "cross-out")
)
),
default = "cross-out"
)
)
)

View File

@@ -38,8 +38,7 @@ object AutoClaimChannelPointPatch : BytecodePatch(
StringResource(
"revanced_auto_claim_channel_points_off",
"Channel Points are not claimed automatically"
),
default = true
)
)
)
@@ -48,7 +47,7 @@ object AutoClaimChannelPointPatch : BytecodePatch(
addInstructionsWithLabels(
lastIndex, // place in front of return-void
"""
invoke-static {}, Lapp/revanced/twitch/patches/AutoClaimChannelPointsPatch;->shouldAutoClaim()Z
invoke-static {}, Lapp/revanced/integrations/twitch/patches/AutoClaimChannelPointsPatch;->shouldAutoClaim()Z
move-result v0
if-eqz v0, :auto_claim

View File

@@ -39,7 +39,7 @@ object DebugModePatch : BytecodePatch(
addInstructions(
0,
"""
invoke-static {}, Lapp/revanced/twitch/patches/DebugModePatch;->isDebugModeEnabled()Z
invoke-static {}, Lapp/revanced/integrations/twitch/patches/DebugModePatch;->isDebugModeEnabled()Z
move-result v0
return v0
"""
@@ -49,20 +49,19 @@ object DebugModePatch : BytecodePatch(
SettingsPatch.PreferenceScreen.MISC.OTHER.addPreferences(
SwitchPreference(
"revanced_debug_mode",
"revanced_twitch_debug_mode",
StringResource(
"revanced_debug_mode_enable",
"Enable debug mode"
"revanced_twitch_debug_mode_title",
"Enable Twitch debug mode"
),
StringResource(
"revanced_debug_mode_on",
"Debug mode is enabled (not recommended)"
"revanced_twitch_debug_mode_summary_on",
"Twitch debug mode is enabled (not recommended)"
),
StringResource(
"revanced_debug_mode_off",
"Debug mode is disabled"
),
default = false,
"revanced_twitch_debug_mode_summary_off",
"Twitch debug mode is disabled"
)
)
)
}

View File

@@ -6,6 +6,5 @@ import app.revanced.patches.twitch.misc.integrations.fingerprints.InitFingerprin
@Patch(requiresIntegrations = true)
object IntegrationsPatch : AbstractIntegrationsPatch(
"Lapp/revanced/twitch/utils/ReVancedUtils;",
setOf(InitFingerprint)
)
)

View File

@@ -1,6 +1,5 @@
package app.revanced.patches.twitch.misc.settings
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
@@ -14,12 +13,14 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMut
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.PreferenceCategory
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
import app.revanced.patches.twitch.misc.integrations.IntegrationsPatch
import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsOnClickFingerprint
import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsUpdatedFingerprint
import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsActivityOnCreateFingerprint
import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsMenuItemEnumFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.immutable.ImmutableField
import java.io.Closeable
@@ -46,12 +47,12 @@ object SettingsPatch : BytecodePatch(
private const val REVANCED_SETTINGS_MENU_ITEM_TITLE_RES = "revanced_settings"
private const val REVANCED_SETTINGS_MENU_ITEM_ICON_RES = "ic_settings"
private const val MENU_ITEM_ENUM_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuItem;"
private const val MENU_DISMISS_EVENT_CLASS = "Ltv/twitch/android/feature/settings/menu/SettingsMenuViewDelegate\$Event\$OnDismissClicked;"
private const val MENU_ITEM_ENUM_CLASS_DESCRIPTOR = "Ltv/twitch/android/feature/settings/menu/SettingsMenuItem;"
private const val MENU_DISMISS_EVENT_CLASS_DESCRIPTOR = "Ltv/twitch/android/feature/settings/menu/SettingsMenuViewDelegate\$Event\$OnDismissClicked;"
private const val INTEGRATIONS_PACKAGE = "app/revanced/twitch"
private const val SETTINGS_HOOKS_CLASS = "L$INTEGRATIONS_PACKAGE/settingsmenu/SettingsHooks;"
private const val REVANCED_UTILS_CLASS = "L$INTEGRATIONS_PACKAGE/utils/ReVancedUtils;"
private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations/twitch"
private const val ACTIVITY_HOOKS_CLASS_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settings/AppCompatActivityHook;"
private const val UTILS_CLASS_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/Utils;"
override fun execute(context: BytecodeContext) {
// Hook onCreate to handle fragment creation
@@ -60,7 +61,7 @@ object SettingsPatch : BytecodePatch(
mutableMethod.addInstructionsWithLabels(
insertIndex,
"""
invoke-static {p0}, $SETTINGS_HOOKS_CLASS->handleSettingsCreation(Landroidx/appcompat/app/AppCompatActivity;)Z
invoke-static {p0}, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingsCreation(Landroidx/appcompat/app/AppCompatActivity;)Z
move-result v0
if-eqz v0, :no_rv_settings_init
return-void
@@ -84,8 +85,8 @@ object SettingsPatch : BytecodePatch(
mutableMethod.addInstructions(
0,
"""
sget-object v0, $MENU_ITEM_ENUM_CLASS->$REVANCED_SETTINGS_MENU_ITEM_NAME:$MENU_ITEM_ENUM_CLASS
invoke-static {p1, v0}, $SETTINGS_HOOKS_CLASS->handleSettingMenuCreation(Ljava/util/List;Ljava/lang/Object;)Ljava/util/List;
sget-object v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR->$REVANCED_SETTINGS_MENU_ITEM_NAME:$MENU_ITEM_ENUM_CLASS_DESCRIPTOR
invoke-static {p1, v0}, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingMenuCreation(Ljava/util/List;Ljava/lang/Object;)Ljava/util/List;
move-result-object p1
"""
)
@@ -97,10 +98,10 @@ object SettingsPatch : BytecodePatch(
mutableMethod.addInstructionsWithLabels(
insertIndex,
"""
invoke-static {p1}, $SETTINGS_HOOKS_CLASS->handleSettingMenuOnClick(Ljava/lang/Enum;)Z
invoke-static {p1}, $ACTIVITY_HOOKS_CLASS_DESCRIPTOR->handleSettingMenuOnClick(Ljava/lang/Enum;)Z
move-result p2
if-eqz p2, :no_rv_settings_onclick
sget-object p1, $MENU_DISMISS_EVENT_CLASS->INSTANCE:$MENU_DISMISS_EVENT_CLASS
sget-object p1, $MENU_DISMISS_EVENT_CLASS_DESCRIPTOR->INSTANCE:$MENU_DISMISS_EVENT_CLASS_DESCRIPTOR
invoke-virtual {p0, p1}, Ltv/twitch/android/core/mvp/viewdelegate/RxViewDelegate;->pushEvent(Ltv/twitch/android/core/mvp/viewdelegate/ViewDelegateEvent;)V
return-void
""",
@@ -109,8 +110,15 @@ object SettingsPatch : BytecodePatch(
} ?: throw MenuGroupsOnClickFingerprint.exception
addString("revanced_settings", "ReVanced Settings", false)
addString("revanced_reboot_message", "Twitch needs to restart to apply your changes. Restart now?", false)
addString("revanced_reboot", "Restart", false)
PreferenceScreen.MISC.OTHER.addPreferences(
SwitchPreference(
"revanced_debug",
StringResource("revanced_debug_title", "Debug logging"),
StringResource("revanced_debug_summary_on", "Debug logs are enabled"),
StringResource("revanced_debug_summary_off", "Debug logs are disabled")
),
)
}
fun addString(identifier: String, value: String, formatted: Boolean = true) =
@@ -130,7 +138,7 @@ object SettingsPatch : BytecodePatch(
ImmutableField(
mutableMethod.definingClass,
name,
MENU_ITEM_ENUM_CLASS,
MENU_ITEM_ENUM_CLASS_DESCRIPTOR,
AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.ENUM or AccessFlags.STATIC,
null,
null,
@@ -142,17 +150,17 @@ object SettingsPatch : BytecodePatch(
mutableMethod.addInstructions(
mutableMethod.implementation!!.instructions.size - 4,
"""
new-instance v0, $MENU_ITEM_ENUM_CLASS
new-instance v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR
const-string v1, "$titleResourceName"
invoke-static {v1}, $REVANCED_UTILS_CLASS->getStringId(Ljava/lang/String;)I
invoke-static {v1}, $UTILS_CLASS_DESCRIPTOR->getStringId(Ljava/lang/String;)I
move-result v1
const-string v3, "$iconResourceName"
invoke-static {v3}, $REVANCED_UTILS_CLASS->getDrawableId(Ljava/lang/String;)I
invoke-static {v3}, $UTILS_CLASS_DESCRIPTOR->getDrawableId(Ljava/lang/String;)I
move-result v3
const-string v4, "$name"
const/4 v5, $value
invoke-direct {v0, v4, v5, v1, v3}, $MENU_ITEM_ENUM_CLASS-><init>(Ljava/lang/String;III)V
sput-object v0, $MENU_ITEM_ENUM_CLASS->$name:$MENU_ITEM_ENUM_CLASS
invoke-direct {v0, v4, v5, v1, v3}, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR-><init>(Ljava/lang/String;III)V
sput-object v0, $MENU_ITEM_ENUM_CLASS_DESCRIPTOR->$name:$MENU_ITEM_ENUM_CLASS_DESCRIPTOR
"""
)
}
@@ -179,7 +187,7 @@ object SettingsPatch : BytecodePatch(
key,
StringResource("${key}_title", title),
preferences.sortedBy { it.title.value },
"app.revanced.twitch.settingsmenu.preference.CustomPreferenceCategory"
"app.revanced.integrations.twitch.settings.preference.CustomPreferenceCategory"
)
}
}

View File

@@ -20,7 +20,7 @@ import java.io.InvalidClassException
object JsonHookPatch : BytecodePatch(
setOf(LoganSquareFingerprint)
), Closeable {
private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/integrations/twitter/patches/hook/json"
private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"

View File

@@ -12,4 +12,4 @@ import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
compatiblePackages = [CompatiblePackage("com.twitter.android")]
)
@Suppress("unused")
object HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
object HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/integrations/twitter/patches/hook/patch/ads/AdsHook;")

View File

@@ -12,5 +12,5 @@ import app.revanced.patches.twitter.misc.hook.patch.BaseHookPatchPatch
)
@Suppress("unused")
object HideRecommendedUsersPatch : BaseHookPatchPatch(
"Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
"Lapp/revanced/integrations/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
)

View File

@@ -15,7 +15,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
@Patch(
name = "Hide ads",
description = "Removes general ads.",
description = "Adds options to remove general ads.",
dependencies = [
HideGetPremiumPatch::class,
HideAdsResourcePatch::class,
@@ -65,7 +65,7 @@ object HideAdsPatch : BytecodePatch() {
.injectHideViewCall(
insertIndex,
viewRegister,
"Lapp/revanced/integrations/patches/components/AdsFilter;",
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;",
"hideAdAttributionView"
)
}

View File

@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
)
object HideAdsResourcePatch : ResourcePatch() {
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/AdsFilter;"
"Lapp/revanced/integrations/youtube/patches/components/AdsFilter;"
internal var adAttributionId: Long = -1
@@ -31,6 +31,12 @@ object HideAdsResourcePatch : ResourcePatch() {
StringResource("revanced_hide_general_ads_summary_on", "General ads are hidden"),
StringResource("revanced_hide_general_ads_summary_off", "General ads are shown")
),
SwitchPreference(
"revanced_hide_fullscreen_ads",
StringResource("revanced_hide_fullscreen_ads_title", "Hide fullscreen ads"),
StringResource("revanced_hide_fullscreen_ads_summary_on", "Fullscreen ads are hidden"),
StringResource("revanced_hide_fullscreen_ads_summary_off", "Fullscreen ads are shown")
),
SwitchPreference(
"revanced_hide_buttoned_ads",
StringResource("revanced_hide_buttoned_ads_title", "Hide buttoned ad"),

View File

@@ -33,7 +33,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
)
object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/HideGetPremiumPatch;"
"Lapp/revanced/integrations/youtube/patches/HideGetPremiumPatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.ADS.addPreferences(
@@ -45,11 +45,11 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
),
StringResource(
"revanced_hide_get_premium_summary_on",
"YouTube Premium promotions under video player is hidden"
"YouTube Premium promotions under video player are hidden"
),
StringResource(
"revanced_hide_get_premium_summary_off",
"YouTube Premium promotions under video player is shown"
"YouTube Premium promotions under video player are shown"
)
)
)

View File

@@ -15,7 +15,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Video ads",
description = "Removes ads in the video player.",
description = "Adds an option to remove ads in the video player.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class
@@ -53,7 +53,7 @@ object VideoAdsPatch : BytecodePatch(
loadVideoAdsFingerprintMethod.addInstructionsWithLabels(
0, """
invoke-static { }, Lapp/revanced/integrations/patches/VideoAdsPatch;->shouldShowAds()Z
invoke-static { }, Lapp/revanced/integrations/youtube/patches/VideoAdsPatch;->shouldShowAds()Z
move-result v0
if-nez v0, :show_video_ads
return-void

View File

@@ -8,8 +8,8 @@ import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePa
import app.revanced.patches.youtube.video.information.VideoInformationPatch
@Patch(
name = "Copy video url",
description = "Adds buttons in player to copy video links.",
name = "Copy video URL",
description = "Adds options to display buttons in the video player to copy video URLs.",
dependencies = [
CopyVideoUrlResourcePatch::class,
PlayerControlsBytecodePatch::class,
@@ -32,7 +32,7 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
)
@Suppress("unused")
object CopyVideoUrlBytecodePatch : BytecodePatch() {
private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
private const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/youtube/videoplayer"
private val BUTTONS_DESCRIPTORS = listOf(
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"

View File

@@ -0,0 +1,69 @@
package app.revanced.patches.youtube.interaction.dialog
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.interaction.dialog.fingerprints.CreateDialogFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Remove viewer discretion dialog",
description = "Adds an option to remove the dialog that appears when opening a video that has been age-restricted " +
"by accepting it automatically. This does not bypass the age restriction.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube"
)
]
)
@Suppress("unused")
object RemoveViewerDiscretionDialogPatch : BytecodePatch(
setOf(CreateDialogFingerprint)
) {
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/RemoveViewerDiscretionDialogPatch;->" +
"confirmDialog(Landroid/app/AlertDialog;)V"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
SwitchPreference(
"revanced_remove_viewer_discretion_dialog",
StringResource(
"revanced_remove_viewer_discretion_dialog_title",
"Remove viewer discretion dialog"
),
StringResource(
"revanced_remove_viewer_discretion_dialog_summary_on",
"Dialog will be removed"
),
StringResource(
"revanced_remove_viewer_discretion_dialog_summary_off",
"Dialog will be shown"
),
StringResource(
"revanced_remove_viewer_discretion_dialog_user_dialog_message",
"This does not bypass the age restriction. It just accepts it automatically."
)
)
)
CreateDialogFingerprint.result?.mutableMethod?.apply {
val showDialogIndex = implementation!!.instructions.lastIndex - 2
val dialogRegister = getInstruction<FiveRegisterInstruction>(showDialogIndex).registerC
replaceInstructions(
showDialogIndex,
"invoke-static { v$dialogRegister }, $INTEGRATIONS_METHOD_DESCRIPTOR",
)
} ?: throw CreateDialogFingerprint.exception
}
}

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.youtube.interaction.dialog.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object CreateDialogFingerprint : MethodFingerprint(
"V",
AccessFlags.PROTECTED.value,
listOf("L", "L", "Ljava/lang/String;"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL // dialog.show()
)
)

View File

@@ -9,7 +9,7 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
@Patch(
name = "External downloads",
description = "Adds support to download and save YouTube videos using an external app.",
description = "Adds support to download and save YouTube videos using an external downloader app.",
dependencies = [
ExternalDownloadsResourcePatch::class,
PlayerControlsBytecodePatch::class,
@@ -32,7 +32,7 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
)
@Suppress("unused")
object ExternalDownloadsBytecodePatch : BytecodePatch() {
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/ExternalDownloadButton;"
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
override fun execute(context: BytecodeContext) {
/*

View File

@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Disable precise seeking gesture",
description = "Disables the gesture that is used to seek precisely when swiping up on the seekbar.",
description = "Adds an option to disable precise seeking when swiping up on the seekbar.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -38,7 +38,7 @@ object DisablePreciseSeekingGesturePatch : BytecodePatch(
setOf(IsSwipingUpFingerprint)
) {
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/patches/DisablePreciseSeekingGesturePatch;->" +
"Lapp/revanced/integrations/youtube/patches/DisablePreciseSeekingGesturePatch;->" +
"disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V"
override fun execute(context: BytecodeContext) {

View File

@@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Seekbar tapping",
description = "Enables tap-to-seek on the seekbar of the video player.",
description = "Adds an option to enable tap-to-seek on the seekbar of the video player.",
dependencies = [
IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
@@ -85,7 +85,7 @@ object EnableSeekbarTappingPatch : BytecodePatch(
addInstructionsWithLabels(
insertIndex,
"""
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
invoke-static { }, Lapp/revanced/integrations/youtube/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
move-result v$freeRegister
if-eqz v$freeRegister, :disabled
${oMethod.toInvokeInstructionString()}

View File

@@ -17,7 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Enable slide to seek",
description = "Enable slide to seek instead of playing at 2x speed when pressing and holding in the video player.",
description = "Adds an option to enable slide to seek instead of playing at 2x speed when pressing and holding in the video player.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -38,7 +38,7 @@ object EnableSlideToSeekPatch : BytecodePatch(
DoubleSpeedSeekNoticeFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SlideToSeekPatch;"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/SlideToSeekPatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(

View File

@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
@Patch(
name = "Swipe controls",
description = "Adds volume and brightness swipe controls.",
description = "Adds options to enable and configure volume and brightness swipe controls.",
dependencies = [
IntegrationsPatch::class,
PlayerTypeHookPatch::class,

View File

@@ -8,6 +8,6 @@ internal object SwipeControlsHostActivityFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf(),
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;"
methodDef.definingClass == "Lapp/revanced/integrations/youtube/swipecontrols/SwipeControlsHostActivity;"
}
)

View File

@@ -18,7 +18,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Disable auto captions",
description = "Disable forced captions from being automatically enabled.",
description = "Adds an option to disable captions from being automatically enabled.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -57,7 +57,7 @@ object AutoCaptionsPatch : BytecodePatch(
0,
"""
const/4 v0, 0x$enabled
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
sput-boolean v0, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
"""
) ?: throw fingerprint.exception
}
@@ -65,10 +65,10 @@ object AutoCaptionsPatch : BytecodePatch(
SubtitleTrackFingerprint.result?.mutableMethod?.addInstructionsWithLabels(
0,
"""
invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
invoke-static {}, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
move-result v0
if-eqz v0, :auto_captions_enabled
sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
sget-boolean v0, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
if-nez v0, :auto_captions_enabled
const/4 v0, 0x1
return v0

View File

@@ -12,7 +12,7 @@ import java.nio.file.Files
@Patch(
name = "Custom branding",
description = "Changes the app name and icon to your choice (defaults to \"YouTube ReVanced\" and the ReVanced logo).",
description = "Applies a custom app name and icon. Defaults to \"YouTube ReVanced\" and the ReVanced logo.",
compatiblePackages = [
CompatiblePackage("com.google.android.youtube")
],
@@ -93,7 +93,7 @@ object CustomBrandingPatch : ResourcePatch() {
)
}
}
} else resourceGroups.forEach { context.copyResources("branding", it) }
} else resourceGroups.forEach { context.copyResources("custom-branding", it) }
}
}

View File

@@ -0,0 +1,137 @@
package app.revanced.patches.youtube.layout.branding.header
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
import java.io.File
@Patch(
name = "Change header",
description = "Applies a custom header in the top left corner within the app. Defaults to the ReVanced header.",
compatiblePackages = [
CompatiblePackage("com.google.android.youtube")
],
use = false
)
@Suppress("unused")
object ChangeHeaderPatch : ResourcePatch() {
private const val HEADER_NAME = "yt_wordmark_header"
private const val PREMIUM_HEADER_NAME = "yt_premium_wordmark_header"
private const val REVANCED_HEADER_NAME = "ReVanced"
private const val REVANCED_BORDERLESS_HEADER_NAME = "ReVanced (borderless logo)"
private val targetResourceDirectoryNames = arrayOf(
"xxxhdpi",
"xxhdpi",
"xhdpi",
"mdpi",
"hdpi",
).map { dpi ->
"drawable-$dpi"
}
private val variants = arrayOf("light", "dark")
private val header by stringPatchOption(
key = "header",
default = REVANCED_BORDERLESS_HEADER_NAME,
values = mapOf(
"YouTube" to HEADER_NAME,
"YouTube Premium" to PREMIUM_HEADER_NAME,
"ReVanced" to REVANCED_HEADER_NAME,
"ReVanced (borderless logo)" to REVANCED_BORDERLESS_HEADER_NAME,
),
title = "Header",
description = """
Either a header name or a path to a custom header folder to use in the top bar.
The path to a folder must contain one or more of the following folders matching the DPI of your device:
${targetResourceDirectoryNames.joinToString("\n") { "- $it" }}
These folders must contain the following files:
${variants.joinToString("\n") { variant -> "- ${HEADER_NAME}_$variant.png" }}
""".trimIndent(),
required = true,
)
override fun execute(context: ResourceContext) {
// The directories to copy the header to.
val targetResourceDirectories = targetResourceDirectoryNames.mapNotNull {
context["res"].resolve(it).takeIf(File::exists)
}
// The files to replace in the target directories.
val targetResourceFiles = targetResourceDirectoryNames.map { directoryName ->
ResourceGroup(
directoryName,
*variants.map { variant -> "${HEADER_NAME}_$variant.png" }.toTypedArray()
)
}
/**
* A function that overwrites both header variants from [from] to [to] in the target resource directories.
*/
val overwriteFromTo: (String, String) -> Unit = { from: String, to: String ->
targetResourceDirectories.forEach { directory ->
variants.forEach { variant ->
val fromPath = directory.resolve("${from}_$variant.png")
val toPath = directory.resolve("${to}_$variant.png")
fromPath.copyTo(toPath, true)
}
}
}
// Functions to overwrite the header to the different variants.
val toPremium = { overwriteFromTo(PREMIUM_HEADER_NAME, HEADER_NAME) }
val toHeader = { overwriteFromTo(HEADER_NAME, PREMIUM_HEADER_NAME) }
val toReVanced = {
// Copy the ReVanced header to the resource directories.
targetResourceFiles.forEach { context.copyResources("change-header/revanced", it) }
// Overwrite the premium with the custom header as well.
toHeader()
}
val toReVancedBorderless = {
// Copy the ReVanced borderless header to the resource directories.
targetResourceFiles.forEach { context.copyResources("change-header/revanced-borderless", it) }
// Overwrite the premium with the custom header as well.
toHeader()
}
val toCustom = {
var copiedReplacementImages = false
// For all the resource groups in the custom header folder, copy them to the resource directories.
File(header!!).listFiles { file -> file.isDirectory }?.forEach { folder ->
val targetDirectory = context["res"].resolve(folder.name)
// Skip if the target directory (DPI) doesn't exist.
if (!targetDirectory.exists()) return@forEach
folder.listFiles { file -> file.isFile }?.forEach {
val targetResourceFile = targetDirectory.resolve(it.name)
it.copyTo(targetResourceFile, true)
copiedReplacementImages = true
}
}
if (!copiedReplacementImages) throw PatchException("Could not find any custom images resources in directory: $header")
// Overwrite the premium with the custom header as well.
toHeader()
}
when (header) {
HEADER_NAME -> toHeader
PREMIUM_HEADER_NAME -> toPremium
REVANCED_HEADER_NAME -> toReVanced
REVANCED_BORDERLESS_HEADER_NAME -> toReVancedBorderless
else -> toCustom
}()
}
}

View File

@@ -1,62 +1,9 @@
package app.revanced.patches.youtube.layout.branding.header
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
import kotlin.io.path.copyTo
@Patch(
name = "Premium heading",
description = "Show or hide the premium heading.",
compatiblePackages = [
CompatiblePackage("com.google.android.youtube")
]
)
@Suppress("unused")
@Deprecated("Use PremiumHeadingPatch instead.")
object PremiumHeadingPatch : ResourcePatch() {
private const val DEFAULT_HEADING_RES = "yt_wordmark_header"
private const val PREMIUM_HEADING_RES = "yt_premium_wordmark_header"
private val usePremiumHeading by booleanPatchOption(
key = "usePremiumHeading",
default = true,
title = "Use premium heading",
description = "Whether to use the premium heading.",
required = true,
)
override fun execute(context: ResourceContext) {
val resDirectory = context["res"]
val (original, replacement) = if (usePremiumHeading!!)
PREMIUM_HEADING_RES to DEFAULT_HEADING_RES
else
DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
val variants = arrayOf("light", "dark")
arrayOf(
"xxxhdpi",
"xxhdpi",
"xhdpi",
"hdpi",
"mdpi"
).mapNotNull { dpi ->
resDirectory.resolve("drawable-$dpi").takeIf { it.exists() }?.toPath()
}.also {
if (it.isEmpty())
throw PatchException("The drawable folder can not be found. Therefore, the patch can not be applied.")
}.forEach { path ->
variants.forEach { mode ->
val fromPath = path.resolve("${original}_$mode.png")
val toPath = path.resolve("${replacement}_$mode.png")
fromPath.copyTo(toPath, true)
}
}
}
override fun execute(context: ResourceContext) = ChangeHeaderPatch.execute(context)
}

View File

@@ -13,7 +13,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Hide video action buttons",
description = "Adds options to hide action buttons under a video.",
description = "Adds options to hide action buttons (such as the Download button) under videos.",
dependencies = [
ResourceMappingPatch::class,
LithoFilterPatch::class
@@ -36,7 +36,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Suppress("unused")
object HideButtonsPatch : ResourcePatch() {
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/ButtonsFilter;"
"Lapp/revanced/integrations/youtube/patches/components/ButtonsFilter;"
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -22,7 +22,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Hide autoplay button",
description = "Hides the autoplay button in the video player.",
description = "Adds an option to hide the autoplay button in the video player.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
@@ -78,7 +78,7 @@ object HideAutoplayButtonPatch : BytecodePatch(
addInstructionsWithLabels(
insertIndex,
"""
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
invoke-static {}, Lapp/revanced/integrations/youtube/patches/HideAutoplayButtonPatch;->isButtonShown()Z
move-result v$clobberRegister
if-eqz v$clobberRegister, :hidden
""",

View File

@@ -14,7 +14,7 @@ import com.android.tools.smali.dexlib2.Opcode
@Patch(
name = "Hide captions button",
description = "Hides the captions button in the video player.",
description = "Adds an option to hide the captions button in the video player.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class
@@ -58,7 +58,7 @@ object HideCaptionsButtonPatch : BytecodePatch(
subtitleButtonControllerMethod.addInstruction(
insertIndex,
"""
invoke-static {v0}, Lapp/revanced/integrations/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V
invoke-static {v0}, Lapp/revanced/integrations/youtube/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V
"""
)
}

View File

@@ -13,7 +13,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Hide cast button",
description = "Hides the cast button in the video player.",
description = "Adds an option to hide the cast button in the video player.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class
@@ -40,7 +40,7 @@ object HideCastButtonPatch : BytecodePatch() {
addInstructions(
0,
"""
invoke-static {p1}, Lapp/revanced/integrations/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I
invoke-static {p1}, Lapp/revanced/integrations/youtube/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I
move-result p1
"""
)

View File

@@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Navigation buttons",
description = "Adds options to hide or change navigation buttons.",
description = "Adds options to hide and change navigation buttons (such as the Shorts button).",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
@@ -45,7 +45,7 @@ object NavigationButtonsPatch : BytecodePatch(
setOf(AddCreateButtonViewFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/NavigationButtonsPatch;"
"Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
@Patch(
name = "Hide player buttons",
description = "Hides previous and next buttons in the video player.",
description = "Adds an option to hide the previous and next buttons in the video player.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class
@@ -72,10 +72,10 @@ object HidePlayerButtonsPatch : BytecodePatch(
mutableMethod.addInstructions(
callIndex,
"""
invoke-static { v$hasNextParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
invoke-static { v$hasNextParameterRegister }, Lapp/revanced/integrations/youtube/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
move-result v$hasNextParameterRegister
invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/youtube/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
move-result v$hasPreviousParameterRegister
"""
)

View File

@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide album cards",
description = "Hides the album cards below the artist description.",
description = "Adds an option to hide album cards below artist descriptions.",
dependencies = [
IntegrationsPatch::class,
AlbumCardsResourcePatch::class
@@ -48,7 +48,7 @@ object AlbumCardsPatch : BytecodePatch(
addInstruction(
insertIndex,
"invoke-static {v$albumCardViewRegister}, " +
"Lapp/revanced/integrations/patches/HideAlbumCardsPatch;" +
"Lapp/revanced/integrations/youtube/patches/HideAlbumCardsPatch;" +
"->" +
"hideAlbumCard(Landroid/view/View;)V"
)

View File

@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide breaking news shelf",
description = "Hides the breaking news shelf on the homepage tab.",
description = "Adds an option to hide the breaking news shelf on the homepage tab.",
dependencies = [
IntegrationsPatch::class,
BreakingNewsResourcePatch::class
@@ -50,7 +50,7 @@ object BreakingNewsPatch : BytecodePatch(
insertIndex,
"""
invoke-static {v$breakingNewsViewRegister},
Lapp/revanced/integrations/patches/HideBreakingNewsPatch;
Lapp/revanced/integrations/youtube/patches/HideBreakingNewsPatch;
->
hideBreakingNews(Landroid/view/View;)V
"""

View File

@@ -12,7 +12,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Comments",
description = "Hides components related to comments.",
description = "Adds options to hide components related to comments.",
dependencies = [
SettingsPatch::class,
LithoFilterPatch::class
@@ -35,7 +35,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Suppress("unused")
object CommentsPatch : ResourcePatch() {
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/CommentsFilter;"
"Lapp/revanced/integrations/youtube/patches/components/CommentsFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)

View File

@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Hide crowdfunding box",
description = "Hides the crowdfunding box between the player and video description.",
description = "Adds an option to hide the crowdfunding box between the player and video description.",
dependencies = [
IntegrationsPatch::class,
CrowdfundingBoxResourcePatch::class
@@ -38,7 +38,7 @@ object CrowdfundingBoxPatch : BytecodePatch(
setOf(CrowdfundingBoxFingerprint)
) {
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"
"Lapp/revanced/integrations/youtube/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"
override fun execute(context: BytecodeContext) {
CrowdfundingBoxFingerprint.result?.let {

View File

@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
@Patch(
name = "Hide endscreen cards",
description = "Hides the suggested video cards at the end of videos.",
description = "Adds an option to hide suggested video cards at the end of videos.",
dependencies = [
IntegrationsPatch::class,
HideEndscreenCardsResourcePatch::class
@@ -53,7 +53,7 @@ object HideEndscreenCardsPatch : BytecodePatch(
addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/youtube/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
)
}
}

View File

@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Hide filter bar",
description = "Hides the filter bar in video feeds.",
description = "Adds options to hide the category bar at the top of video feeds.",
dependencies = [HideFilterBarResourcePatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -42,7 +42,7 @@ object HideFilterBarPatch : BytecodePatch(
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/HideFilterBarPatch;"
"Lapp/revanced/integrations/youtube/patches/HideFilterBarPatch;"
override fun execute(context: BytecodeContext) {
FilterBarHeightFingerprint.patch<TwoRegisterInstruction> { register ->

View File

@@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Hide floating microphone button",
description = "Hides the floating microphone button which appears in search.",
description = "Adds an option to hide the floating microphone button when searching.",
dependencies = [HideFloatingMicrophoneButtonResourcePatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -34,7 +34,7 @@ object HideFloatingMicrophoneButtonPatch : BytecodePatch(
setOf(ShowFloatingMicrophoneButtonFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/HideFloatingMicrophoneButtonPatch;"
"Lapp/revanced/integrations/youtube/patches/HideFloatingMicrophoneButtonPatch;"
override fun execute(context: BytecodeContext) {
ShowFloatingMicrophoneButtonFingerprint.result?.let { result ->

View File

@@ -14,7 +14,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Disable fullscreen ambient mode",
description = "Disables the ambient mode when in fullscreen.",
description = "Adds an option to disable the ambient mode when in fullscreen.",
dependencies = [SettingsPatch::class, IntegrationsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -34,7 +34,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch(
setOf(InitializeAmbientModeFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/DisableFullscreenAmbientModePatch;"
"Lapp/revanced/integrations/youtube/patches/DisableFullscreenAmbientModePatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -1,6 +1,5 @@
package app.revanced.patches.youtube.layout.hide.general
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
@@ -18,13 +17,14 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWaterma
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Hide layout components",
description = "Hides general layout components.",
description = "Adds options to hide general layout components.",
dependencies = [
LithoFilterPatch::class,
SettingsPatch::class
@@ -48,9 +48,9 @@ object HideLayoutComponentsPatch : BytecodePatch(
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint)
) {
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
"Lapp/revanced/integrations/youtube/patches/components/LayoutComponentsFilter;"
private const val DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME =
"Lapp/revanced/integrations/patches/components/DescriptionComponentsFilter;"
"Lapp/revanced/integrations/youtube/patches/components/DescriptionComponentsFilter;"
override fun execute(context: BytecodeContext) {
PreferenceScreen.LAYOUT.addPreferences(
@@ -93,6 +93,21 @@ object HideLayoutComponentsPatch : BytecodePatch(
StringResource("revanced_hide_timed_reactions_summary_on", "Timed reactions are hidden"),
StringResource("revanced_hide_timed_reactions_summary_off", "Timed reactions are shown")
),
SwitchPreference(
"revanced_hide_search_result_recommendations",
StringResource(
"revanced_hide_search_result_recommendations_title",
"Hide search result recommendations (e.g People also watched)"
),
StringResource(
"revanced_hide_search_result_recommendations_summary_on",
"Recommendations are hidden"
),
StringResource(
"revanced_hide_search_result_recommendations_summary_off",
"Recommendations are shown"
)
),
SwitchPreference(
"revanced_hide_search_result_shelf_header",
StringResource(
@@ -285,8 +300,8 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_artist_cards",
StringResource("revanced_hide_artist_cards_title", "Hide artist cards"),
StringResource("revanced_hide_artist_cards_on", "Artist cards is hidden"),
StringResource("revanced_hide_artist_cards_off", "Artist cards is shown")
StringResource("revanced_hide_artist_cards_on", "Artist cards are hidden"),
StringResource("revanced_hide_artist_cards_off", "Artist cards are shown")
),
SwitchPreference(
"revanced_hide_chips_shelf",

View File

@@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Patch(
name = "Hide info cards",
description = "Hides info cards in videos.",
description = "Adds an option to hide info cards that creators add in the video player.",
dependencies = [
IntegrationsPatch::class,
LithoFilterPatch::class,
@@ -48,7 +48,7 @@ object HideInfoCardsPatch : BytecodePatch(
)
) {
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/HideInfoCardsFilterPatch;"
"Lapp/revanced/integrations/youtube/patches/components/HideInfoCardsFilterPatch;"
override fun execute(context: BytecodeContext) {
InfocardsIncognitoFingerprint.also {
@@ -62,7 +62,7 @@ object HideInfoCardsPatch : BytecodePatch(
addInstruction(
invokeInstructionIndex,
"invoke-static {v${getInstruction<FiveRegisterInstruction>(invokeInstructionIndex).registerC}}," +
" Lapp/revanced/integrations/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V"
" Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V"
)
}
@@ -75,7 +75,7 @@ object HideInfoCardsPatch : BytecodePatch(
hideInfoCardsCallMethod.addInstructionsWithLabels(
invokeInterfaceIndex,
"""
invoke-static {}, Lapp/revanced/integrations/patches/HideInfoCardsPatch;->hideInfoCardsMethodCall()Z
invoke-static {}, Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsMethodCall()Z
move-result v$toggleRegister
if-nez v$toggleRegister, :hide_info_cards
""",

View File

@@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide \'Load more\' button",
description = "Hides the button under videos that loads similar videos.",
description = "Adds an option to hide the button under videos that loads similar videos.",
dependencies = [HideLoadMoreButtonResourcePatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -34,7 +34,7 @@ object HideLoadMoreButtonPatch : BytecodePatch(
setOf(HideLoadMoreButtonFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/HideLoadMoreButtonPatch;"
"Lapp/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch;"
override fun execute(context: BytecodeContext) {
HideLoadMoreButtonFingerprint.result?.let {

View File

@@ -44,7 +44,7 @@ object HideEmailAddressPatch : BytecodePatch(
addInstructions(
setVisibilityConstIndex,
"""
invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/patches/HideEmailAddressPatch;->hideEmailAddress(I)I
invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/youtube/patches/HideEmailAddressPatch;->hideEmailAddress(I)I
move-result v$setVisibilityConstRegister
"""
)

View File

@@ -13,7 +13,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Player flyout menu",
description = "Hides player flyout menu items.",
description = "Adds options to hide menu items that appear when pressing the gear icon in the video player.",
dependencies = [
LithoFilterPatch::class,
PlayerTypeHookPatch::class,
@@ -36,7 +36,7 @@ object HidePlayerFlyoutMenuPatch : ResourcePatch() {
private const val KEY = "revanced_hide_player_flyout"
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/PlayerFlyoutMenuItemsFilter;"
"Lapp/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter;"
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Disable rolling number animations",
description = "Disables rolling number animations of video view count, user likes, and upload time.",
description = "Adds an option to disable rolling number animations of video view count, user likes, and upload time.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -38,7 +38,7 @@ object DisableRollingNumberAnimationPatch : BytecodePatch(
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/DisableRollingNumberAnimationsPatch;"
"Lapp/revanced/integrations/youtube/patches/DisableRollingNumberAnimationsPatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -16,7 +16,7 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint
@Patch(
name = "Hide seekbar",
description = "Hides the seekbar.",
description = "Adds an option to hide the seekbar.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
@@ -63,7 +63,7 @@ object HideSeekbarPatch : BytecodePatch(
0,
"""
const/4 v0, 0x0
invoke-static { }, Lapp/revanced/integrations/patches/HideSeekbarPatch;->hideSeekbar()Z
invoke-static { }, Lapp/revanced/integrations/youtube/patches/HideSeekbarPatch;->hideSeekbar()Z
move-result v0
if-eqz v0, :hide_seekbar
return-void

View File

@@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Hide Shorts components",
description = "Hides components from YouTube Shorts.",
description = "Adds options to hide components related to YouTube Shorts.",
dependencies = [
IntegrationsPatch::class,
LithoFilterPatch::class,
@@ -51,7 +51,7 @@ object HideShortsComponentsPatch : BytecodePatch(
SetPivotBarVisibilityParentFingerprint
)
) {
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/ShortsFilter;"
override fun execute(context: BytecodeContext) {
// region Hide the Shorts shelf.

View File

@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Disable suggested video end screen",
description = "Disables the suggested video end screen at the end of a video.",
description = "Adds an option to disable the suggested video end screen at the end of videos.",
dependencies = [IntegrationsPatch::class, DisableSuggestedVideoEndScreenResourcePatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -33,7 +33,7 @@ object DisableSuggestedVideoEndScreenPatch : BytecodePatch(
setOf(CreateEndScreenViewFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch;"
"Lapp/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch;"
override fun execute(context: BytecodeContext) {
CreateEndScreenViewFingerprint.result?.let {

View File

@@ -14,7 +14,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Hide timestamp",
description = "Hides timestamp in video player.",
description = "Adds an option to hide the timestamp in the bottom left of the video player.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -48,7 +48,7 @@ object HideTimestampPatch : BytecodePatch(
mutableMethod.addInstructionsWithLabels(
0,
"""
invoke-static { }, Lapp/revanced/integrations/patches/HideTimestampPatch;->hideTimestamp()Z
invoke-static { }, Lapp/revanced/integrations/youtube/patches/HideTimestampPatch;->hideTimestamp()Z
move-result v0
if-eqz v0, :hide_time
return-void

View File

@@ -14,7 +14,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Disable player popup panels",
description = "Disables panels (such as live chat) from opening automatically.",
description = "Adds an option to disable panels (such as live chat) from opening automatically.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
@@ -50,7 +50,7 @@ object PlayerPopupPanelsPatch : BytecodePatch(
engagementPanelControllerMethod.addInstructionsWithLabels(
0,
"""
invoke-static { }, Lapp/revanced/integrations/patches/DisablePlayerPopupPanelsPatch;->disablePlayerPopupPanels()Z
invoke-static { }, Lapp/revanced/integrations/youtube/patches/DisablePlayerPopupPanelsPatch;->disablePlayerPopupPanels()Z
move-result v0
if-eqz v0, :player_popup_panels
if-eqz p4, :player_popup_panels

View File

@@ -9,7 +9,7 @@ import org.w3c.dom.Element
@Patch(
name = "Remove player controls background",
description = "Removes the background from the video player controls.",
description = "Removes the dark background surrounding the video player controls.",
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", [

View File

@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Custom player overlay opacity",
description = "Change the opacity of the player background when player controls are visible.",
description = "Adds an option to change the opacity of the video player background when player controls are visible.",
dependencies = [CustomPlayerOverlayOpacityResourcePatch::class],
compatiblePackages = [
CompatiblePackage("com.google.android.youtube")
@@ -21,7 +21,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
)
@Suppress("unused")
object CustomPlayerOverlayOpacityPatch : BytecodePatch(setOf(CreatePlayerOverviewFingerprint)) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/CustomPlayerOverlayOpacityPatch;"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/CustomPlayerOverlayOpacityPatch;"
override fun execute(context: BytecodeContext) {
CreatePlayerOverviewFingerprint.result?.let { result ->

View File

@@ -1,8 +1,5 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -11,23 +8,43 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.ConversionContextFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.DislikeFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.DislikesOldLayoutTextViewFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.LikeFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RemoveLikeFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberMeasureAnimatedTextFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberMeasureStaticLabelFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberMeasureTextParentFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberSetterFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RollingNumberTextViewFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.ShortsTextViewFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentConstructorFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentDataFingerprint
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentLookupFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.shared.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
@Patch(
name = "Return YouTube Dislike",
description = "Shows the dislike count of videos using the Return YouTube Dislike API.",
description = "Adds an option to show the dislike count of videos using the Return YouTube Dislike API.",
dependencies = [
IntegrationsPatch::class,
LithoFilterPatch::class,
@@ -38,6 +55,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", [
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.41",
@@ -49,7 +67,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Suppress("unused")
object ReturnYouTubeDislikePatch : BytecodePatch(
setOf(
ConversionContextFingerprint,
TextComponentConstructorFingerprint,
TextComponentDataFingerprint,
ShortsTextViewFingerprint,
DislikesOldLayoutTextViewFingerprint,
LikeFingerprint,
@@ -62,10 +82,12 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;"
"Lapp/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch;"
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch;"
"Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
private fun MethodFingerprint.resultOrThrow() = result ?: throw exception
override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
@@ -97,64 +119,132 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
// endregion
// region Hook creation of Spans and the cached lookup of them.
// region Hook code for creation and cached lookup of text Spans.
// Alternatively the hook can be made at the creation of Spans in TextComponentSpec,
// And it works in all situations except it fails to update the Span when the user dislikes,
// since the underlying (likes only) text did not change.
// This hook handles all situations, as it's where the created Spans are stored and later reused.
TextComponentContextFingerprint.also {
if (!it.resolve(context, TextComponentConstructorFingerprint.result!!.classDef))
throw it.exception
}.result?.also { result ->
if (!TextComponentAtomicReferenceFingerprint.resolve(context, result.method, result.classDef))
throw TextComponentAtomicReferenceFingerprint.exception
}?.let { textComponentContextFingerprintResult ->
val conversionContextIndex = textComponentContextFingerprintResult
.scanResult.patternScanResult!!.endIndex
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
.scanResult.patternScanResult!!.startIndex
TextComponentConstructorFingerprint.result?.let { textConstructorResult ->
// Find the field name of the conversion context.
val conversionContextClassType = ConversionContextFingerprint.resultOrThrow().classDef.type
val conversionContextField = textConstructorResult.classDef.fields.find {
it.type == conversionContextClassType
} ?: throw PatchException("Could not find conversion context field")
val insertIndex = atomicReferenceStartIndex + 9
TextComponentLookupFingerprint.resolve(context, textConstructorResult.classDef)
TextComponentLookupFingerprint.resultOrThrow().mutableMethod.apply {
// Find the instruction for creating the text data object.
val textDataClassType = TextComponentDataFingerprint.resultOrThrow().classDef.type
val insertIndex = indexOfFirstInstruction {
opcode == Opcode.NEW_INSTANCE &&
getReference<TypeReference>()?.type == textDataClassType
}
if (insertIndex < 0) throw PatchException("Could not find data creation instruction")
val tempRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
textComponentContextFingerprintResult.mutableMethod.apply {
// Get the conversion context obfuscated field name
val conversionContextFieldReference =
getInstruction<ReferenceInstruction>(conversionContextIndex).reference
// Find the instruction that sets the span to an instance field.
// The instruction is only a few lines after the creation of the instance.
// The method has multiple iput-object instructions using a CharSequence,
// so verify the found instruction is in the expected location.
val putFieldInstruction = implementation!!.instructions
.subList(insertIndex, insertIndex + 20)
.find {
it.opcode == Opcode.IPUT_OBJECT &&
it.getReference<FieldReference>()?.type == "Ljava/lang/CharSequence;"
} ?: throw PatchException("Could not find put object instruction")
val charSequenceRegister = (putFieldInstruction as TwoRegisterInstruction).registerA
// Free register to hold the conversion context
val freeRegister =
getInstruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB
val atomicReferenceRegister =
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 6).registerC
// Instruction that is replaced, and also has the CharacterSequence register.
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
val charSequenceSourceRegister = moveCharSequenceInstruction.registerB
val charSequenceTargetRegister = moveCharSequenceInstruction.registerA
// Move the current instance to the free register, and get the conversion context from it.
// Must replace the instruction to preserve the control flow label.
replaceInstruction(insertIndex, "move-object/from16 v$freeRegister, p0")
addInstructions(
insertIndex + 1,
"""
# Move context to free register
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
invoke-static {v$freeRegister, v$atomicReferenceRegister, v$charSequenceSourceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$freeRegister
# Replace the original instruction
move-object v${charSequenceTargetRegister}, v${freeRegister}
insertIndex,
"""
# Copy conversion context
move-object/from16 v$tempRegister, p0
iget-object v$tempRegister, v$tempRegister, $conversionContextField
invoke-static {v$tempRegister, v$charSequenceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$charSequenceRegister
"""
)
}
} ?: throw TextComponentContextFingerprint.exception
} ?: throw TextComponentConstructorFingerprint.exception
// endregion
// region Hook for non-litho Short videos.
ShortsTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val patternResult = it.scanResult.patternScanResult!!
// If the field is true, the TextView is for a dislike button.
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference
val textViewFieldReference = // Like/Dislike button TextView field
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
// Check if the hooked TextView object is that of the dislike button.
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
// Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
val insertIndex = patternResult.startIndex + 6
addInstructionsWithLabels(
insertIndex,
"""
# Check, if the TextView is for a dislike button
iget-boolean v0, p0, $isDisLikesBooleanReference
if-eqz v0, :is_like
# Hook the TextView, if it is for the dislike button
iget-object v0, p0, $textViewFieldReference
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
move-result v0
if-eqz v0, :ryd_disabled
return-void
:is_like
:ryd_disabled
nop
"""
)
}
} ?: throw ShortsTextViewFingerprint.exception
// endregion
// region Hook for litho Shorts
// Filter that parses the video id from the UI
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// Player response video id is needed to search for the video ids in Shorts litho components.
VideoIdPatch.hookPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
// endregion
// region Hook old UI layout dislikes, for the older app spoofs used with spoof-app-version.
DislikesOldLayoutTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
val resourceIdentifierRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
val textViewRegister = getInstruction<OneRegisterInstruction>(startIndex + 4).registerA
addInstruction(
startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
} ?: throw DislikesOldLayoutTextViewFingerprint.exception
// endregion
// region Hook rolling numbers.
// Do this last to allow patching old unsupported versions (if the user really wants),
// On older unsupported version this will fail to resolve and throw an exception,
// but everything will still work correctly anyways.
RollingNumberSetterFingerprint.result?.let {
val dislikesIndex = it.scanResult.patternScanResult!!.endIndex
@@ -164,7 +254,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
val charSequenceInstanceRegister =
getInstruction<OneRegisterInstruction>(0).registerA
val charSequenceFieldReference =
getInstruction<ReferenceInstruction>(dislikesIndex).reference.toString()
getInstruction<ReferenceInstruction>(dislikesIndex).reference
val registerCount = implementation!!.registerCount
@@ -268,73 +358,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
// endregion
// region Hook for non-litho Short videos.
ShortsTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val patternResult = it.scanResult.patternScanResult!!
// If the field is true, the TextView is for a dislike button.
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference
val textViewFieldReference = // Like/Dislike button TextView field
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
// Check if the hooked TextView object is that of the dislike button.
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
// Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
val insertIndex = patternResult.startIndex + 6
addInstructionsWithLabels(
insertIndex,
"""
# Check, if the TextView is for a dislike button
iget-boolean v0, p0, $isDisLikesBooleanReference
if-eqz v0, :is_like
# Hook the TextView, if it is for the dislike button
iget-object v0, p0, $textViewFieldReference
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
move-result v0
if-eqz v0, :ryd_disabled
return-void
:is_like
:ryd_disabled
nop
"""
)
}
} ?: throw ShortsTextViewFingerprint.exception
// endregion
// region Hook for litho Shorts
// Filter that parses the video id from the UI
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// Player response video id is needed to search for the video ids in Shorts litho components.
VideoIdPatch.hookPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
// endregion
// region Hook old UI layout dislikes, for the older app spoofs used with spoof-app-version.
DislikesOldLayoutTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
val resourceIdentifierRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
val textViewRegister = getInstruction<OneRegisterInstruction>(startIndex + 4).registerA
addInstruction(
startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
} ?: throw DislikesOldLayoutTextViewFingerprint.exception
// endregion
}
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)

View File

@@ -0,0 +1,18 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object ConversionContextFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;",
parameters = listOf(),
strings = listOf(
", widthConstraint=",
", heightConstraint=",
", templateLoggerFactory=",
", rootDisposableContainer=",
// 18.37.36 and after this String is: ConversionContext{containerInternal=
// and before it is: ConversionContext{container=
// Use a partial string to match both.
"ConversionContext{container"
)
)

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