mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-18 08:43:56 +00:00
Compare commits
80 Commits
v5.46.0-de
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3401467a6d | ||
|
|
87247590de | ||
|
|
41e2590584 | ||
|
|
778d13ce8b | ||
|
|
19f146c01d | ||
|
|
12b819d20e | ||
|
|
004b5908db | ||
|
|
f4af27dfec | ||
|
|
4cc315952d | ||
|
|
6312fe8d60 | ||
|
|
3d754575a4 | ||
|
|
a3f7609fe3 | ||
|
|
d25dcfe49a | ||
|
|
1cc2cb9cb2 | ||
|
|
f5cbb31724 | ||
|
|
b42ae27ce6 | ||
|
|
43ab29d03d | ||
|
|
789f0a5628 | ||
|
|
da836b667c | ||
|
|
44e7dbcf4d | ||
|
|
195c239000 | ||
|
|
c47beae213 | ||
|
|
cebcfab86a | ||
|
|
71c6cb569e | ||
|
|
6bb6281149 | ||
|
|
16bd96e2bb | ||
|
|
8f3f4c95bb | ||
|
|
da02d68587 | ||
|
|
a429824bb7 | ||
|
|
e0f33468e6 | ||
|
|
315931cbf8 | ||
|
|
dc69f2433e | ||
|
|
73e43b2a49 | ||
|
|
918f04793f | ||
|
|
f1a9537f01 | ||
|
|
1f4f252c81 | ||
|
|
2b560f5fe9 | ||
|
|
f8bd1239cc | ||
|
|
c825ebda37 | ||
|
|
255c00b183 | ||
|
|
0ea3491227 | ||
|
|
5d437b08dd | ||
|
|
018d176914 | ||
|
|
9a77beea8a | ||
|
|
ded8370207 | ||
|
|
4d1104fc32 | ||
|
|
34830ba63b | ||
|
|
7a6894d809 | ||
|
|
144e6e2694 | ||
|
|
847ee189a9 | ||
|
|
dc813fe617 | ||
|
|
02831a6069 | ||
|
|
5228fd4b58 | ||
|
|
6bd7dca75b | ||
|
|
22ed7bfbb3 | ||
|
|
a7c220a4ae | ||
|
|
d8ca4ee931 | ||
|
|
a5d197b977 | ||
|
|
a0ec4c07f7 | ||
|
|
0928dcd00d | ||
|
|
bbd8932b2e | ||
|
|
300b12f948 | ||
|
|
ac583d40d0 | ||
|
|
c400188c38 | ||
|
|
0af0ee92c4 | ||
|
|
fff29544b9 | ||
|
|
9495cf49ef | ||
|
|
15675b5164 | ||
|
|
654d091e65 | ||
|
|
98371be33c | ||
|
|
2f0de15e67 | ||
|
|
df160370e2 | ||
|
|
bb745b555b | ||
|
|
8df9a46721 | ||
|
|
94ae84ad0f | ||
|
|
4febb2e2e9 | ||
|
|
b9bc7e3e58 | ||
|
|
9f3bb26cb9 | ||
|
|
d64dfc2884 | ||
|
|
a39ef1e0a4 |
3
.github/workflows/build_pull_request.yml
vendored
3
.github/workflows/build_pull_request.yml
vendored
@@ -25,7 +25,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
ORG_GRADLE_PROJECT_githubPackagesUsername: ${{ env.GITHUB_ACTOR }}
|
||||||
|
ORG_GRADLE_PROJECT_githubPackagesPassword: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: ./gradlew :patches:buildAndroid --no-daemon
|
run: ./gradlew :patches:buildAndroid --no-daemon
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
|
|||||||
2
.github/workflows/pull_strings.yml
vendored
2
.github/workflows/pull_strings.yml
vendored
@@ -2,7 +2,7 @@ name: Pull strings
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 */12 * * *"
|
- cron: "0 0 * * 0"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -31,7 +31,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
ORG_GRADLE_PROJECT_githubPackagesUsername: ${{ env.GITHUB_ACTOR }}
|
||||||
|
ORG_GRADLE_PROJECT_githubPackagesPassword: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: ./gradlew :patches:buildAndroid clean
|
run: ./gradlew :patches:buildAndroid clean
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
262
CHANGELOG.md
262
CHANGELOG.md
@@ -1,3 +1,265 @@
|
|||||||
|
# [5.48.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.8...v5.48.0-dev.9) (2026-01-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Add `Disable Sentry telemetry` patch ([#6416](https://github.com/ReVanced/revanced-patches/issues/6416)) ([4cc3159](https://github.com/ReVanced/revanced-patches/commit/4cc315952db557c565872de9e8484805f2e42305))
|
||||||
|
* Disable Play Integrity patch ([#6412](https://github.com/ReVanced/revanced-patches/issues/6412)) ([6312fe8](https://github.com/ReVanced/revanced-patches/commit/6312fe8d60da24465c0c1b0fa4e94ceb79873d9c))
|
||||||
|
|
||||||
|
# [5.48.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.7...v5.48.0-dev.8) (2026-01-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Letterboxd:** Add `Unlock app icons` patch ([#6415](https://github.com/ReVanced/revanced-patches/issues/6415)) ([d25dcfe](https://github.com/ReVanced/revanced-patches/commit/d25dcfe49ac331c9b3dca739ba0be95dbab669cc))
|
||||||
|
|
||||||
|
# [5.48.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.6...v5.48.0-dev.7) (2026-01-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Strava:** Add `Disable Quick Edit` patch ([#6452](https://github.com/ReVanced/revanced-patches/issues/6452)) ([f5cbb31](https://github.com/ReVanced/revanced-patches/commit/f5cbb31724d15f7e939b96ee0186fd0a108f9fdc))
|
||||||
|
* **Strava:** Add `Overwrite media upload parameters` patch ([#6410](https://github.com/ReVanced/revanced-patches/issues/6410)) ([b42ae27](https://github.com/ReVanced/revanced-patches/commit/b42ae27ce66ebad9e9cfc5b70fc121df5bad7567))
|
||||||
|
|
||||||
|
# [5.48.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.5...v5.48.0-dev.6) (2026-01-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fix build error introduced in `4046bee` ([#6417](https://github.com/ReVanced/revanced-patches/issues/6417)) ([789f0a5](https://github.com/ReVanced/revanced-patches/commit/789f0a562861825065633d172445ebf35a1ba8d8))
|
||||||
|
|
||||||
|
# [5.48.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.4...v5.48.0-dev.5) (2025-12-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Disney+ - Skip ads:** Remove unsupported package names ([#6422](https://github.com/ReVanced/revanced-patches/issues/6422)) ([44e7dbc](https://github.com/ReVanced/revanced-patches/commit/44e7dbcf4d7eaf94dd0164baba847d3e19250154))
|
||||||
|
|
||||||
|
# [5.48.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.3...v5.48.0-dev.4) (2025-12-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Strava:** Add `Block Snowplow tracking` patch ([#6413](https://github.com/ReVanced/revanced-patches/issues/6413)) ([c47beae](https://github.com/ReVanced/revanced-patches/commit/c47beae21376dd17ab8bc09afe73e9094481bde9))
|
||||||
|
|
||||||
|
# [5.48.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.2...v5.48.0-dev.3) (2025-12-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fix compilation error introduced in `6bb6281` ([#6409](https://github.com/ReVanced/revanced-patches/issues/6409)) ([71c6cb5](https://github.com/ReVanced/revanced-patches/commit/71c6cb569ebf7b93cf73ee391839e5220557ce7c))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Instagram - Hides navigation buttons:** Add more buttons to hide ([#6390](https://github.com/ReVanced/revanced-patches/issues/6390)) ([6bb6281](https://github.com/ReVanced/revanced-patches/commit/6bb62811493da04812cc3e392e68d874f95cbef9))
|
||||||
|
|
||||||
|
# [5.48.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.48.0-dev.1...v5.48.0-dev.2) (2025-12-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Strava:** Add `Enable password login` patch ([#6396](https://github.com/ReVanced/revanced-patches/issues/6396)) ([8f3f4c9](https://github.com/ReVanced/revanced-patches/commit/8f3f4c95bb8f151fc9a2c272bf7d0e905c2f01fc))
|
||||||
|
|
||||||
|
# [5.48.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.47.0...v5.48.0-dev.1) (2025-12-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fix compilation error introduced in dc69f243 ([#6392](https://github.com/ReVanced/revanced-patches/issues/6392)) ([a429824](https://github.com/ReVanced/revanced-patches/commit/a429824bb77b49aea14b0b54f2204ae24d5209a1))
|
||||||
|
* **YouTube - Hide layout components:** Hide new type of crowdfunding box ([#6380](https://github.com/ReVanced/revanced-patches/issues/6380)) ([dc69f24](https://github.com/ReVanced/revanced-patches/commit/dc69f2433e2650654e2dffdd76b0b0c8a52bf515))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **ProtonVPN:** Add `Unlock split tunneling` patch ([#6353](https://github.com/ReVanced/revanced-patches/issues/6353)) ([e0f3346](https://github.com/ReVanced/revanced-patches/commit/e0f33468e6e96b9f10cf35ec67622d6488528c90))
|
||||||
|
* **SBS On Demand:** Add `Remove ads` patch ([#6378](https://github.com/ReVanced/revanced-patches/issues/6378)) ([315931c](https://github.com/ReVanced/revanced-patches/commit/315931cbf8f61cd4b3a54ace1ff03685d748614c))
|
||||||
|
|
||||||
|
# [5.47.0](https://github.com/ReVanced/revanced-patches/compare/v5.46.0...v5.47.0) (2025-12-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Instagram - Disable signature check:** Change patch to default excluded ([#6283](https://github.com/ReVanced/revanced-patches/issues/6283)) ([bb745b5](https://github.com/ReVanced/revanced-patches/commit/bb745b555b3808b7679c5995319aa365630fbd76))
|
||||||
|
* **Lightroom:** Add `Disable version check` patch to fix opening the app ([#6315](https://github.com/ReVanced/revanced-patches/issues/6315)) ([018d176](https://github.com/ReVanced/revanced-patches/commit/018d176914a06a30e9007a3eb2e6b0f459078413))
|
||||||
|
* **Reddit - Hide ads:** Update patch for new versions of Reddit ([#6342](https://github.com/ReVanced/revanced-patches/issues/6342)) ([f8bd123](https://github.com/ReVanced/revanced-patches/commit/f8bd1239cc0f0bd1c2dca39f846951bf512891e3))
|
||||||
|
* **Spotify:** Make patches work with latest versions again ([#6359](https://github.com/ReVanced/revanced-patches/issues/6359)) ([34830ba](https://github.com/ReVanced/revanced-patches/commit/34830ba63b436146064f0f89f948d51cd0cb9146))
|
||||||
|
* **YouTube - Hide layout components:** Fix "Hide Subscribe button" in channel page not working ([#6363](https://github.com/ReVanced/revanced-patches/issues/6363)) ([ded8370](https://github.com/ReVanced/revanced-patches/commit/ded83702077701aac8a8749d71bf7376427f37d6))
|
||||||
|
* **YouTube - Hide player flyout menu items:** Allow hiding audio menu with 'Android No SDK' client type ([9495cf4](https://github.com/ReVanced/revanced-patches/commit/9495cf49ef8a872be64de6c971c1919b4b9a8720))
|
||||||
|
* **YouTube - Sanitize sharing links:** Handle non hierarchical urls ([654d091](https://github.com/ReVanced/revanced-patches/commit/654d091e650cda37650b57cbf3ba6f1cdd6d47d3))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Disney+ - SkipAds:** Add other package names the patch is compatible with ([#6372](https://github.com/ReVanced/revanced-patches/issues/6372)) ([1f4f252](https://github.com/ReVanced/revanced-patches/commit/1f4f252c81e9a89267f6e37548e66027b1bc1a1a))
|
||||||
|
* **Disney+:** Add `Skip ads` patch ([#6343](https://github.com/ReVanced/revanced-patches/issues/6343)) ([6bd7dca](https://github.com/ReVanced/revanced-patches/commit/6bd7dca75bd2ea335a596aa93a8b767d39be5f83))
|
||||||
|
* **IdAustria - Remove device integrity check:** Update patch to work with latest version ([#6360](https://github.com/ReVanced/revanced-patches/issues/6360)) ([0ea3491](https://github.com/ReVanced/revanced-patches/commit/0ea3491227fc50c03555d43d3fec78eb82906b26))
|
||||||
|
* **Instagram:** Add `Anonymous story viewing` patch ([#6263](https://github.com/ReVanced/revanced-patches/issues/6263)) ([94ae84a](https://github.com/ReVanced/revanced-patches/commit/94ae84ad0fc3a9197c82d5356301d464730c3b17))
|
||||||
|
* **Instagram:** Add `Disable auto story flipping` patch ([#6262](https://github.com/ReVanced/revanced-patches/issues/6262)) ([2f0de15](https://github.com/ReVanced/revanced-patches/commit/2f0de15e67e4f99ed6ecdc136d04cceb23b0d069))
|
||||||
|
* **Instagram:** Add `Disable Reels scrolling` patch ([#6317](https://github.com/ReVanced/revanced-patches/issues/6317)) ([0928dcd](https://github.com/ReVanced/revanced-patches/commit/0928dcd00dc2a9c1eef9a23c1e26ff5dc9ee670a))
|
||||||
|
* **Letterboxd:** Add `Hide ads` patch ([#6309](https://github.com/ReVanced/revanced-patches/issues/6309)) ([0af0ee9](https://github.com/ReVanced/revanced-patches/commit/0af0ee92c48bb2ffc332197e05439e20c5c05d83))
|
||||||
|
* **Peacock TV:** Add `Hide ads` patch ([#6348](https://github.com/ReVanced/revanced-patches/issues/6348)) ([847ee18](https://github.com/ReVanced/revanced-patches/commit/847ee189a971e6d4a99823998569f8e561b8319c))
|
||||||
|
* **ProtonVPN:** Add `Remove delay` patch ([#6326](https://github.com/ReVanced/revanced-patches/issues/6326)) ([bbd8932](https://github.com/ReVanced/revanced-patches/commit/bbd8932b2e740aff96ba047332e541bff3e09436))
|
||||||
|
* **Spoof SIM provider:** Spoof additional TelephonyManager methods ([#6293](https://github.com/ReVanced/revanced-patches/issues/6293)) ([ac583d4](https://github.com/ReVanced/revanced-patches/commit/ac583d40d0f4c0e6544e3661ff3e82a25912f2b0))
|
||||||
|
* **YouTube - Hide layout components:** Add "Hide cell divider", "Hide featured links", and "Hide featured videos" options ([#6335](https://github.com/ReVanced/revanced-patches/issues/6335)) ([a5d197b](https://github.com/ReVanced/revanced-patches/commit/a5d197b9775b98d7a37bfdee9e5f726d5e04d8cf))
|
||||||
|
* **YouTube - Hide layout components:** Add "Hide Join button" and "Hide Subscribe button" options for channel page ([#6345](https://github.com/ReVanced/revanced-patches/issues/6345)) ([02831a6](https://github.com/ReVanced/revanced-patches/commit/02831a6069fc30ffa3a87f8e4de653d003a2187e))
|
||||||
|
* **YouTube - Hide Shorts components:** Add "Hide auto-dubbed label" and "Hide live preview" options ([#6334](https://github.com/ReVanced/revanced-patches/issues/6334)) ([a7c220a](https://github.com/ReVanced/revanced-patches/commit/a7c220a4aea93ea7ae7005b5760443d7571c4228))
|
||||||
|
|
||||||
|
# [5.47.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.17...v5.47.0-dev.18) (2025-12-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Disney+ - SkipAds:** Add other package names the patch is compatible with ([#6372](https://github.com/ReVanced/revanced-patches/issues/6372)) ([1f4f252](https://github.com/ReVanced/revanced-patches/commit/1f4f252c81e9a89267f6e37548e66027b1bc1a1a))
|
||||||
|
|
||||||
|
# [5.47.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.16...v5.47.0-dev.17) (2025-12-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Reddit - Hide ads:** Update patch for new versions of Reddit ([#6342](https://github.com/ReVanced/revanced-patches/issues/6342)) ([f8bd123](https://github.com/ReVanced/revanced-patches/commit/f8bd1239cc0f0bd1c2dca39f846951bf512891e3))
|
||||||
|
|
||||||
|
# [5.47.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.15...v5.47.0-dev.16) (2025-12-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Lightroom:** Add `Disable version check` patch to fix opening the app ([#6315](https://github.com/ReVanced/revanced-patches/issues/6315)) ([018d176](https://github.com/ReVanced/revanced-patches/commit/018d176914a06a30e9007a3eb2e6b0f459078413))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **IdAustria - Remove device integrity check:** Update patch to work with latest version ([#6360](https://github.com/ReVanced/revanced-patches/issues/6360)) ([0ea3491](https://github.com/ReVanced/revanced-patches/commit/0ea3491227fc50c03555d43d3fec78eb82906b26))
|
||||||
|
|
||||||
|
# [5.47.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.14...v5.47.0-dev.15) (2025-12-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Hide layout components:** Fix "Hide Subscribe button" in channel page not working ([#6363](https://github.com/ReVanced/revanced-patches/issues/6363)) ([ded8370](https://github.com/ReVanced/revanced-patches/commit/ded83702077701aac8a8749d71bf7376427f37d6))
|
||||||
|
|
||||||
|
# [5.47.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.13...v5.47.0-dev.14) (2025-12-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Spotify:** Make patches work with latest versions again ([#6359](https://github.com/ReVanced/revanced-patches/issues/6359)) ([34830ba](https://github.com/ReVanced/revanced-patches/commit/34830ba63b436146064f0f89f948d51cd0cb9146))
|
||||||
|
|
||||||
|
# [5.47.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.12...v5.47.0-dev.13) (2025-12-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Peacock TV:** Add `Hide ads` patch ([#6348](https://github.com/ReVanced/revanced-patches/issues/6348)) ([847ee18](https://github.com/ReVanced/revanced-patches/commit/847ee189a971e6d4a99823998569f8e561b8319c))
|
||||||
|
|
||||||
|
# [5.47.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.11...v5.47.0-dev.12) (2025-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Hide layout components:** Add "Hide Join button" and "Hide Subscribe button" options for channel page ([#6345](https://github.com/ReVanced/revanced-patches/issues/6345)) ([02831a6](https://github.com/ReVanced/revanced-patches/commit/02831a6069fc30ffa3a87f8e4de653d003a2187e))
|
||||||
|
|
||||||
|
# [5.47.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.10...v5.47.0-dev.11) (2025-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Disney+:** Add `Skip ads` patch ([#6343](https://github.com/ReVanced/revanced-patches/issues/6343)) ([6bd7dca](https://github.com/ReVanced/revanced-patches/commit/6bd7dca75bd2ea335a596aa93a8b767d39be5f83))
|
||||||
|
|
||||||
|
# [5.47.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.9...v5.47.0-dev.10) (2025-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Hide Shorts components:** Add "Hide auto-dubbed label" and "Hide live preview" options ([#6334](https://github.com/ReVanced/revanced-patches/issues/6334)) ([a7c220a](https://github.com/ReVanced/revanced-patches/commit/a7c220a4aea93ea7ae7005b5760443d7571c4228))
|
||||||
|
|
||||||
|
# [5.47.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.8...v5.47.0-dev.9) (2025-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Hide layout components:** Add "Hide cell divider", "Hide featured links", and "Hide featured videos" options ([#6335](https://github.com/ReVanced/revanced-patches/issues/6335)) ([a5d197b](https://github.com/ReVanced/revanced-patches/commit/a5d197b9775b98d7a37bfdee9e5f726d5e04d8cf))
|
||||||
|
|
||||||
|
# [5.47.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.7...v5.47.0-dev.8) (2025-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Instagram:** Add `Disable Reels scrolling` patch ([#6317](https://github.com/ReVanced/revanced-patches/issues/6317)) ([0928dcd](https://github.com/ReVanced/revanced-patches/commit/0928dcd00dc2a9c1eef9a23c1e26ff5dc9ee670a))
|
||||||
|
* **ProtonVPN:** Add `Remove delay` patch ([#6326](https://github.com/ReVanced/revanced-patches/issues/6326)) ([bbd8932](https://github.com/ReVanced/revanced-patches/commit/bbd8932b2e740aff96ba047332e541bff3e09436))
|
||||||
|
|
||||||
|
# [5.47.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.6...v5.47.0-dev.7) (2025-12-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Spoof SIM provider:** Spoof additional TelephonyManager methods ([#6293](https://github.com/ReVanced/revanced-patches/issues/6293)) ([ac583d4](https://github.com/ReVanced/revanced-patches/commit/ac583d40d0f4c0e6544e3661ff3e82a25912f2b0))
|
||||||
|
|
||||||
|
# [5.47.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.5...v5.47.0-dev.6) (2025-11-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Letterboxd:** Add `Hide ads` patch ([#6309](https://github.com/ReVanced/revanced-patches/issues/6309)) ([0af0ee9](https://github.com/ReVanced/revanced-patches/commit/0af0ee92c48bb2ffc332197e05439e20c5c05d83))
|
||||||
|
|
||||||
|
# [5.47.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.4...v5.47.0-dev.5) (2025-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Hide player flyout menu items:** Allow hiding audio menu with 'Android No SDK' client type ([9495cf4](https://github.com/ReVanced/revanced-patches/commit/9495cf49ef8a872be64de6c971c1919b4b9a8720))
|
||||||
|
|
||||||
|
# [5.47.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.3...v5.47.0-dev.4) (2025-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Sanitize sharing links:** Handle non hierarchical urls ([654d091](https://github.com/ReVanced/revanced-patches/commit/654d091e650cda37650b57cbf3ba6f1cdd6d47d3))
|
||||||
|
|
||||||
|
# [5.47.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.2...v5.47.0-dev.3) (2025-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Instagram:** Add `Disable auto story flipping` patch ([#6262](https://github.com/ReVanced/revanced-patches/issues/6262)) ([2f0de15](https://github.com/ReVanced/revanced-patches/commit/2f0de15e67e4f99ed6ecdc136d04cceb23b0d069))
|
||||||
|
|
||||||
|
# [5.47.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.47.0-dev.1...v5.47.0-dev.2) (2025-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Instagram - Disable signature check:** Change patch to default excluded ([#6283](https://github.com/ReVanced/revanced-patches/issues/6283)) ([bb745b5](https://github.com/ReVanced/revanced-patches/commit/bb745b555b3808b7679c5995319aa365630fbd76))
|
||||||
|
|
||||||
|
# [5.47.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.46.0...v5.47.0-dev.1) (2025-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Instagram:** Add `Anonymous story viewing` patch ([#6263](https://github.com/ReVanced/revanced-patches/issues/6263)) ([94ae84a](https://github.com/ReVanced/revanced-patches/commit/94ae84ad0fc3a9197c82d5356301d464730c3b17))
|
||||||
|
|
||||||
|
# [5.46.0](https://github.com/ReVanced/revanced-patches/compare/v5.45.0...v5.46.0) (2025-11-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Duolingo - Disable ads:** Constrain patch to last working app target ([f238ae9](https://github.com/ReVanced/revanced-patches/commit/f238ae9895000f01d1dccb800cc8efde0d5362bd))
|
||||||
|
* **Instagram - Hide navigation buttons:** Constrain patch to last working app target ([e030e9c](https://github.com/ReVanced/revanced-patches/commit/e030e9c07a7748e117ac44f6776a9f6317b20623))
|
||||||
|
* **Spotify - Hide Create button:** Remove obsolete patch that is no longer needed ([#6252](https://github.com/ReVanced/revanced-patches/issues/6252)) ([59d85b2](https://github.com/ReVanced/revanced-patches/commit/59d85b28a7fcb285ff5f2bb6ae654020d76b2019))
|
||||||
|
* **YouTube - Check watch history domain name resolution:** Fix false positive warning message if the internet connection fails halfway into the DNS check ([5726353](https://github.com/ReVanced/revanced-patches/commit/57263538c79f5a561c449229ac8e068c641285d3))
|
||||||
|
* **YouTube - Hide layout components:** Fix "Hide Hype points" ([#6247](https://github.com/ReVanced/revanced-patches/issues/6247)) ([5821440](https://github.com/ReVanced/revanced-patches/commit/582144026d28e57bb7adcbba39244f3c7cdbc0f3))
|
||||||
|
* **YouTube - Settings:** Add additional languages to ReVanced language preference ([d390b54](https://github.com/ReVanced/revanced-patches/commit/d390b54dab92d75b4e0d3e38344eae489dd69d98))
|
||||||
|
* **YouTube - Settings:** Resolve settings search crash when searching for specific words ([#6231](https://github.com/ReVanced/revanced-patches/issues/6231)) ([76dcfae](https://github.com/ReVanced/revanced-patches/commit/76dcfaefd8679e45a70f265b0239436e60c055cf))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Debugging:** Add setting to block experimental client flags ([#6196](https://github.com/ReVanced/revanced-patches/issues/6196)) ([2e9d695](https://github.com/ReVanced/revanced-patches/commit/2e9d6959c94df7588b9e34b18770e9f437e91926))
|
||||||
|
* **YouTube - Hide layout components:** Add "Hide Hype points" ([#6230](https://github.com/ReVanced/revanced-patches/issues/6230)) ([a52c015](https://github.com/ReVanced/revanced-patches/commit/a52c0153b12c3f6f0ad260e03d2e9850c0466392))
|
||||||
|
* **YouTube - Hide layout components:** Add video description "Hide Featured content" and "Hide Subscribe button" ([#6253](https://github.com/ReVanced/revanced-patches/issues/6253)) ([da4cf94](https://github.com/ReVanced/revanced-patches/commit/da4cf940911a4406e2c9dd558b60305385a80c61))
|
||||||
|
* **YouTube - Hide player flyout menu items:** Add "Hide Listen with YouTube Music" ([#6232](https://github.com/ReVanced/revanced-patches/issues/6232)) ([858edbf](https://github.com/ReVanced/revanced-patches/commit/858edbf3e7f394fcc766d767c8dc54cf5ba24370))
|
||||||
|
* **YouTube Music:** Add `Change miniplayer color` patch ([#6259](https://github.com/ReVanced/revanced-patches/issues/6259)) ([ab808ae](https://github.com/ReVanced/revanced-patches/commit/ab808aeb773592cb26c848d8456478a346ec3bad))
|
||||||
|
* **YouTube Music:** Add `Hide buttons` patch ([#6255](https://github.com/ReVanced/revanced-patches/issues/6255)) ([7a18ebc](https://github.com/ReVanced/revanced-patches/commit/7a18ebc7ab74ba30c5d5284a4856c55cdfc31097))
|
||||||
|
|
||||||
# [5.46.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.9...v5.46.0-dev.10) (2025-11-09)
|
# [5.46.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.9...v5.46.0-dev.10) (2025-11-09)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ Thank you for considering contributing to ReVanced Patches. You can find the con
|
|||||||
|
|
||||||
To build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
|
To build ReVanced Patches, you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
|
||||||
|
|
||||||
## 📜 Licence
|
## 📜 License
|
||||||
|
|
||||||
ReVanced Patches is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
|
ReVanced Patches is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
|
||||||
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Patches as long as you track changes/dates in source files.
|
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Patches as long as you track changes/dates in source files.
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
project_id_env: "CROWDIN_PROJECT_ID"
|
project_id_env: "CROWDIN_PROJECT_ID"
|
||||||
api_token_env: "CROWDIN_PERSONAL_TOKEN"
|
api_token_env: "CROWDIN_PERSONAL_TOKEN"
|
||||||
|
|
||||||
preserve_hierarchy: false
|
preserve_hierarchy: true
|
||||||
files:
|
files:
|
||||||
- source: patches/src/main/resources/addresources/values/strings.xml
|
- source: patches/src/main/resources/addresources/values/strings.xml
|
||||||
|
dest: patches.xml
|
||||||
translation: patches/src/main/resources/addresources/values-%android_code%/strings.xml
|
translation: patches/src/main/resources/addresources/values-%android_code%/strings.xml
|
||||||
skip_untranslated_strings: true
|
skip_untranslated_strings: true
|
||||||
|
|||||||
20
extensions/all/misc/disable-play-integrity/build.gradle.kts
Normal file
20
extensions/all/misc/disable-play-integrity/build.gradle.kts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
android {
|
||||||
|
namespace = "app.revanced.extension"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 21
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
aidl = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(libs.annotation)
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.google.android.play.core.integrity.protocol;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import com.google.android.play.core.integrity.protocol.IExpressIntegrityServiceCallback;
|
||||||
|
|
||||||
|
interface IExpressIntegrityService {
|
||||||
|
oneway void requestIntegrityToken(in Bundle request, IExpressIntegrityServiceCallback callback) = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.google.android.play.core.integrity.protocol;
|
||||||
|
|
||||||
|
interface IExpressIntegrityServiceCallback {
|
||||||
|
oneway void onRequestExpressIntegrityTokenResult(in Bundle result) = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.google.android.play.core.integrity.protocol;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import com.google.android.play.core.integrity.protocol.IIntegrityServiceCallback;
|
||||||
|
|
||||||
|
interface IIntegrityService {
|
||||||
|
oneway void requestIntegrityToken(in Bundle request, IIntegrityServiceCallback callback) = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.google.android.play.core.integrity.protocol;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
interface IIntegrityServiceCallback {
|
||||||
|
oneway void onResult(in Bundle result) = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package android.ext;
|
||||||
|
/** @hide */
|
||||||
|
// Int values that are assigned to packages in this interface can be retrieved at runtime from
|
||||||
|
// ApplicationInfo.ext().getPackageId() or from AndroidPackage.ext().getPackageId() (in system_server).
|
||||||
|
//
|
||||||
|
// PackageIds are assigned to parsed APKs only after they are verified, either by a certificate check
|
||||||
|
// or by a check that the APK is stored on an immutable OS partition.
|
||||||
|
public interface PackageId {
|
||||||
|
String PLAY_STORE_NAME = "com.android.vending";
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package android.os;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public class BinderWrapper implements IBinder {
|
||||||
|
protected final IBinder base;
|
||||||
|
|
||||||
|
public BinderWrapper(IBinder base) {
|
||||||
|
this.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
|
||||||
|
return base.transact(code, data, reply, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IInterface queryLocalInterface(@NonNull String descriptor) {
|
||||||
|
return base.queryLocalInterface(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getInterfaceDescriptor() throws RemoteException {
|
||||||
|
return base.getInterfaceDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean pingBinder() {
|
||||||
|
return base.pingBinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBinderAlive() {
|
||||||
|
return base.isBinderAlive();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException {
|
||||||
|
base.dump(fd, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dumpAsync(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException {
|
||||||
|
base.dumpAsync(fd, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToDeath(@NonNull DeathRecipient recipient, int flags) throws RemoteException {
|
||||||
|
base.linkToDeath(recipient, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags) {
|
||||||
|
return base.unlinkToDeath(recipient, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package app.grapheneos.gmscompat.lib.playintegrity;
|
||||||
|
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.internal.os.FakeBackgroundHandler;
|
||||||
|
import com.google.android.play.core.integrity.protocol.IIntegrityService;
|
||||||
|
import com.google.android.play.core.integrity.protocol.IIntegrityServiceCallback;
|
||||||
|
|
||||||
|
class ClassicPlayIntegrityServiceWrapper extends PlayIntegrityServiceWrapper {
|
||||||
|
|
||||||
|
ClassicPlayIntegrityServiceWrapper(IBinder base) {
|
||||||
|
super(base);
|
||||||
|
requestIntegrityTokenTxnCode = 2; // IIntegrityService.Stub.TRANSACTION_requestIntegrityToken
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TokenRequestStub extends IIntegrityService.Stub {
|
||||||
|
public void requestIntegrityToken(Bundle request, IIntegrityServiceCallback callback) {
|
||||||
|
Runnable r = () -> {
|
||||||
|
var result = new Bundle();
|
||||||
|
// https://developer.android.com/google/play/integrity/reference/com/google/android/play/core/integrity/model/IntegrityErrorCode.html#API_NOT_AVAILABLE
|
||||||
|
final int API_NOT_AVAILABLE = -1;
|
||||||
|
result.putInt("error", API_NOT_AVAILABLE);
|
||||||
|
try {
|
||||||
|
callback.onResult(result);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e("IIntegrityService.Stub", "", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FakeBackgroundHandler.getHandler().postDelayed(r, getTokenRequestResultDelay());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Binder createTokenRequestStub() {
|
||||||
|
return new TokenRequestStub();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package app.grapheneos.gmscompat.lib.playintegrity;
|
||||||
|
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.BinderWrapper;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
abstract class PlayIntegrityServiceWrapper extends BinderWrapper {
|
||||||
|
final String TAG;
|
||||||
|
protected int requestIntegrityTokenTxnCode;
|
||||||
|
|
||||||
|
public PlayIntegrityServiceWrapper(IBinder base) {
|
||||||
|
super(base);
|
||||||
|
TAG = getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Binder createTokenRequestStub();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transact(int code, Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
|
||||||
|
if (code == requestIntegrityTokenTxnCode) {
|
||||||
|
if (maybeStubOutIntegrityTokenRequest(code, data, reply, flags)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.transact(code, data, reply, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean maybeStubOutIntegrityTokenRequest(int code, Parcel data, @Nullable Parcel reply, int flags) {
|
||||||
|
Log.d(TAG, "integrity token request detected");
|
||||||
|
|
||||||
|
try {
|
||||||
|
createTokenRequestStub().transact(code, data, reply, flags);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// this is a local call
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static long getTokenRequestResultDelay() {
|
||||||
|
return 500L;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package app.grapheneos.gmscompat.lib.playintegrity;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.ext.PackageId;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import app.grapheneos.gmscompat.lib.util.ServiceConnectionWrapper;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class PlayIntegrityUtils {
|
||||||
|
|
||||||
|
public static @Nullable ServiceConnection maybeReplaceServiceConnection(Intent service, ServiceConnection orig) {
|
||||||
|
if (PackageId.PLAY_STORE_NAME.equals(service.getPackage())) {
|
||||||
|
UnaryOperator<IBinder> binderOverride = null;
|
||||||
|
|
||||||
|
final String CLASSIC_SERVICE =
|
||||||
|
"com.google.android.play.core.integrityservice.BIND_INTEGRITY_SERVICE";
|
||||||
|
final String STANDARD_SERVICE =
|
||||||
|
"com.google.android.play.core.expressintegrityservice.BIND_EXPRESS_INTEGRITY_SERVICE";
|
||||||
|
|
||||||
|
String action = service.getAction();
|
||||||
|
if (STANDARD_SERVICE.equals(action)) {
|
||||||
|
binderOverride = StandardPlayIntegrityServiceWrapper::new;
|
||||||
|
} else if (CLASSIC_SERVICE.equals(action)) {
|
||||||
|
binderOverride = ClassicPlayIntegrityServiceWrapper::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binderOverride != null) {
|
||||||
|
return new ServiceConnectionWrapper(orig, binderOverride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package app.grapheneos.gmscompat.lib.playintegrity;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
import com.android.internal.os.FakeBackgroundHandler;
|
||||||
|
import com.google.android.play.core.integrity.protocol.IExpressIntegrityService;
|
||||||
|
import com.google.android.play.core.integrity.protocol.IExpressIntegrityServiceCallback;
|
||||||
|
|
||||||
|
@SuppressLint("LongLogTag")
|
||||||
|
class StandardPlayIntegrityServiceWrapper extends PlayIntegrityServiceWrapper {
|
||||||
|
|
||||||
|
StandardPlayIntegrityServiceWrapper(IBinder base) {
|
||||||
|
super(base);
|
||||||
|
requestIntegrityTokenTxnCode = 3; // IExpressIntegrityService.Stub.TRANSACTION_requestIntegrityToken
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TokenRequestStub extends IExpressIntegrityService.Stub {
|
||||||
|
public void requestIntegrityToken(Bundle request, IExpressIntegrityServiceCallback callback) {
|
||||||
|
Runnable r = () -> {
|
||||||
|
var result = new Bundle();
|
||||||
|
// https://developer.android.com/google/play/integrity/reference/com/google/android/play/core/integrity/model/StandardIntegrityErrorCode.html#API_NOT_AVAILABLE
|
||||||
|
final int API_NOT_AVAILABLE = -1;
|
||||||
|
result.putInt("error", API_NOT_AVAILABLE);
|
||||||
|
try {
|
||||||
|
callback.onRequestExpressIntegrityTokenResult(result);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e("IExpressIntegrityService.Stub", "", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FakeBackgroundHandler.getHandler().postDelayed(r, getTokenRequestResultDelay());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Binder createTokenRequestStub() {
|
||||||
|
return new TokenRequestStub();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package app.grapheneos.gmscompat.lib.util;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class ServiceConnectionWrapper implements ServiceConnection {
|
||||||
|
private final ServiceConnection base;
|
||||||
|
private final UnaryOperator<IBinder> binderOverride;
|
||||||
|
|
||||||
|
public ServiceConnectionWrapper(ServiceConnection base, UnaryOperator<IBinder> binderOverride) {
|
||||||
|
this.base = base;
|
||||||
|
this.binderOverride = binderOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
IBinder override = binderOverride.apply(service);
|
||||||
|
if (override != null) {
|
||||||
|
service = override;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.onServiceConnected(name, service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
base.onServiceDisconnected(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindingDied(ComponentName name) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
base.onBindingDied(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNullBinding(ComponentName name) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
base.onNullBinding(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package app.revanced.extension.playintegrity;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import app.grapheneos.gmscompat.lib.playintegrity.PlayIntegrityUtils;
|
||||||
|
|
||||||
|
public class DisablePlayIntegrityPatch {
|
||||||
|
public static boolean bindService(Context context, Intent service, ServiceConnection conn, int flags) {
|
||||||
|
ServiceConnection override = PlayIntegrityUtils.maybeReplaceServiceConnection(service, conn);
|
||||||
|
if (override != null) {
|
||||||
|
conn = override;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.bindService(service, conn, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.android.internal.os;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
public class FakeBackgroundHandler {
|
||||||
|
|
||||||
|
public static Handler getHandler() {
|
||||||
|
return new Handler(Looper.getMainLooper());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -311,6 +311,10 @@ public class Utils {
|
|||||||
return resourceId;
|
return resourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getResourceString(int id) throws Resources.NotFoundException {
|
||||||
|
return getContext().getResources().getString(id);
|
||||||
|
}
|
||||||
|
|
||||||
public static int getResourceInteger(String resourceIdentifierName) throws Resources.NotFoundException {
|
public static int getResourceInteger(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||||
return getContext().getResources().getInteger(getResourceIdentifierOrThrow(resourceIdentifierName, "integer"));
|
return getContext().getResources().getInteger(getResourceIdentifierOrThrow(resourceIdentifierName, "integer"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -71,6 +72,17 @@ public class CustomBrandingPatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static View getLottieViewOrNull(View lottieStartupView) {
|
||||||
|
if (BaseSettings.CUSTOM_BRANDING_ICON.get() == BrandingTheme.ORIGINAL) {
|
||||||
|
return lottieStartupView;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,6 +35,15 @@ public class LinkSanitizer {
|
|||||||
|
|
||||||
public Uri sanitizeUri(Uri uri) {
|
public Uri sanitizeUri(Uri uri) {
|
||||||
try {
|
try {
|
||||||
|
String scheme = uri.getScheme();
|
||||||
|
if (scheme == null || !(scheme.equals("http") || scheme.equals("https"))) {
|
||||||
|
// Opening YouTube share sheet 'other' option passes the video title as a URI.
|
||||||
|
// Checking !uri.isHierarchical() works for all cases, except if the
|
||||||
|
// video title starts with / and then it's hierarchical but still an invalid URI.
|
||||||
|
Logger.printDebug(() -> "Ignoring uri: " + uri);
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
Uri.Builder builder = uri.buildUpon().clearQuery();
|
Uri.Builder builder = uri.buildUpon().clearQuery();
|
||||||
|
|
||||||
if (!parametersToRemove.isEmpty()) {
|
if (!parametersToRemove.isEmpty()) {
|
||||||
|
|||||||
@@ -58,6 +58,23 @@ public abstract class Setting<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Availability based on a single parent setting being disabled.
|
||||||
|
*/
|
||||||
|
public static Availability parentNot(BooleanSetting parent) {
|
||||||
|
return new Availability() {
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return !parent.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Setting<?>> getParentSettings() {
|
||||||
|
return Collections.singletonList(parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Availability based on all parents being enabled.
|
* Availability based on all parents being enabled.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class SpoofVideoStreamsPatch {
|
|||||||
public static boolean spoofingToClientWithNoMultiAudioStreams() {
|
public static boolean spoofingToClientWithNoMultiAudioStreams() {
|
||||||
return isPatchIncluded()
|
return isPatchIncluded()
|
||||||
&& SPOOF_STREAMING_DATA
|
&& SPOOF_STREAMING_DATA
|
||||||
&& preferredClient != ClientType.IPADOS;
|
&& !preferredClient.supportsMultiAudioTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
5
extensions/strava/build.gradle.kts
Normal file
5
extensions/strava/build.gradle.kts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
dependencies {
|
||||||
|
compileOnly(project(":extensions:shared:library"))
|
||||||
|
compileOnly(project(":extensions:strava:stub"))
|
||||||
|
compileOnly(libs.okhttp)
|
||||||
|
}
|
||||||
1
extensions/strava/src/main/AndroidManifest.xml
Normal file
1
extensions/strava/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
package app.revanced.extension.strava;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
|
import com.strava.core.data.MediaType;
|
||||||
|
import com.strava.photos.data.Media;
|
||||||
|
|
||||||
|
import okhttp3.*;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Utils;
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
public final class AddMediaDownloadPatch {
|
||||||
|
public static final int ACTION_DOWNLOAD = -1;
|
||||||
|
public static final int ACTION_OPEN_LINK = -2;
|
||||||
|
public static final int ACTION_COPY_LINK = -3;
|
||||||
|
|
||||||
|
private static final OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
|
public static boolean handleAction(int actionId, Media media) {
|
||||||
|
String url = getUrl(media);
|
||||||
|
switch (actionId) {
|
||||||
|
case ACTION_DOWNLOAD:
|
||||||
|
String name = media.getId();
|
||||||
|
if (media.getType() == MediaType.VIDEO) {
|
||||||
|
downloadVideo(url, name);
|
||||||
|
} else {
|
||||||
|
downloadPhoto(url, name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case ACTION_OPEN_LINK:
|
||||||
|
Utils.openLink(url);
|
||||||
|
return true;
|
||||||
|
case ACTION_COPY_LINK:
|
||||||
|
copyLink(url);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copyLink(CharSequence url) {
|
||||||
|
Utils.setClipboard(url);
|
||||||
|
showInfoToast("link_copied_to_clipboard", "🔗");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void downloadPhoto(String url, String name) {
|
||||||
|
showInfoToast("loading", "⏳");
|
||||||
|
Utils.runOnBackgroundThread(() -> {
|
||||||
|
try (Response response = fetch(url)) {
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
String mimeType = body.contentType().toString();
|
||||||
|
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
|
||||||
|
ContentResolver resolver = Utils.getContext().getContentResolver();
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(MediaStore.Images.Media.DISPLAY_NAME, name + '.' + extension);
|
||||||
|
values.put(MediaStore.Images.Media.IS_PENDING, 1);
|
||||||
|
values.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
|
||||||
|
values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/Strava");
|
||||||
|
Uri collection = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||||
|
? MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||||
|
: MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
Uri row = resolver.insert(collection, values);
|
||||||
|
try (OutputStream outputStream = resolver.openOutputStream(row)) {
|
||||||
|
transferTo(body.byteStream(), outputStream);
|
||||||
|
} finally {
|
||||||
|
values.clear();
|
||||||
|
values.put(MediaStore.Images.Media.IS_PENDING, 0);
|
||||||
|
resolver.update(row, values, null);
|
||||||
|
}
|
||||||
|
showInfoToast("yis_2024_local_save_image_success", "✔️");
|
||||||
|
} catch (IOException e) {
|
||||||
|
showErrorToast("download_failure", "❌", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads a video in the M3U8 / HLS (HTTP Live Streaming) format.
|
||||||
|
*/
|
||||||
|
public static void downloadVideo(String url, String name) {
|
||||||
|
// The first request yields multiple URLs with different stream options.
|
||||||
|
// In case of Strava, the first one is always of highest quality.
|
||||||
|
// Each stream can consist of multiple chunks.
|
||||||
|
// The second request yields the URLs of all of these chunks.
|
||||||
|
// Fetch all of them concurrently and pipe their streams into the file in order.
|
||||||
|
showInfoToast("loading", "⏳");
|
||||||
|
Utils.runOnBackgroundThread(() -> {
|
||||||
|
try {
|
||||||
|
String highestQualityStreamUrl;
|
||||||
|
try (Response response = fetch(url)) {
|
||||||
|
highestQualityStreamUrl = replaceFileName(url, lines(response).findFirst().get());
|
||||||
|
}
|
||||||
|
List<Future<Response>> futures;
|
||||||
|
try (Response response = fetch(highestQualityStreamUrl)) {
|
||||||
|
futures = lines(response)
|
||||||
|
.map(line -> replaceFileName(highestQualityStreamUrl, line))
|
||||||
|
.map(chunkUrl -> Utils.submitOnBackgroundThread(() -> fetch(chunkUrl)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
ContentResolver resolver = Utils.getContext().getContentResolver();
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(MediaStore.Video.Media.DISPLAY_NAME, name + '.' + "mp4");
|
||||||
|
values.put(MediaStore.Video.Media.IS_PENDING, 1);
|
||||||
|
values.put(MediaStore.Video.Media.MIME_TYPE, MimeTypeMap.getSingleton().getMimeTypeFromExtension("mp4"));
|
||||||
|
values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES + "/Strava");
|
||||||
|
Uri collection = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||||
|
? MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||||
|
: MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
Uri row = resolver.insert(collection, values);
|
||||||
|
try (OutputStream outputStream = resolver.openOutputStream(row)) {
|
||||||
|
Throwable error = null;
|
||||||
|
for (Future<Response> future : futures) {
|
||||||
|
if (error != null) {
|
||||||
|
if (future.cancel(true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try (Response response = future.get()) {
|
||||||
|
if (error == null) {
|
||||||
|
transferTo(response.body().byteStream(), outputStream);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
error = e;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
error = e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error != null) {
|
||||||
|
throw new IOException(error);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
values.clear();
|
||||||
|
values.put(MediaStore.Video.Media.IS_PENDING, 0);
|
||||||
|
resolver.update(row, values, null);
|
||||||
|
}
|
||||||
|
showInfoToast("yis_2024_local_save_video_success", "✔️");
|
||||||
|
} catch (IOException e) {
|
||||||
|
showErrorToast("download_failure", "❌", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getUrl(Media media) {
|
||||||
|
return media.getType() == MediaType.VIDEO
|
||||||
|
? ((Media.Video) media).getVideoUrl()
|
||||||
|
: media.getLargestUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getString(String name, String fallback) {
|
||||||
|
int id = Utils.getResourceIdentifier(name, "string");
|
||||||
|
return id != 0
|
||||||
|
? Utils.getResourceString(id)
|
||||||
|
: fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showInfoToast(String resourceName, String fallback) {
|
||||||
|
String text = getString(resourceName, fallback);
|
||||||
|
Utils.showToastShort(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showErrorToast(String resourceName, String fallback, IOException exception) {
|
||||||
|
String text = getString(resourceName, fallback);
|
||||||
|
Utils.showToastLong(text + ' ' + exception.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Response fetch(String url) throws IOException {
|
||||||
|
Request request = new Request.Builder().url(url).build();
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
throw new IOException("Got HTTP status code " + response.code());
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code inputStream.transferTo(outputStream)} is "too new".
|
||||||
|
*/
|
||||||
|
private static void transferTo(InputStream in, OutputStream out) throws IOException {
|
||||||
|
byte[] buffer = new byte[1024 * 8];
|
||||||
|
int length;
|
||||||
|
while ((length = in.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all file names.
|
||||||
|
*/
|
||||||
|
private static Stream<String> lines(Response response) {
|
||||||
|
BufferedReader reader = new BufferedReader(response.body().charStream());
|
||||||
|
return reader.lines().filter(line -> !line.startsWith("#"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String replaceFileName(String uri, String newName) {
|
||||||
|
return uri.substring(0, uri.lastIndexOf('/') + 1) + newName;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
extensions/strava/stub/build.gradle.kts
Normal file
12
extensions/strava/stub/build.gradle.kts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
plugins {
|
||||||
|
alias(libs.plugins.android.library)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "app.revanced.extension"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 21
|
||||||
|
}
|
||||||
|
}
|
||||||
1
extensions/strava/stub/src/main/AndroidManifest.xml
Normal file
1
extensions/strava/stub/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.strava.core.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public interface MediaContent extends Serializable {
|
||||||
|
String getCaption();
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
String getReferenceId();
|
||||||
|
|
||||||
|
MediaType getType();
|
||||||
|
|
||||||
|
void setCaption(String caption);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.strava.core.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public final class MediaDimension implements Comparable<MediaDimension>, Serializable {
|
||||||
|
private final int height;
|
||||||
|
private final int width;
|
||||||
|
|
||||||
|
public MediaDimension(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getHeightScale() {
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
return height / width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getWidthScale() {
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
return width / height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLandscape() {
|
||||||
|
return width > 0 && width >= height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(MediaDimension other) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.strava.core.data;
|
||||||
|
|
||||||
|
public enum MediaType {
|
||||||
|
PHOTO(1),
|
||||||
|
VIDEO(2);
|
||||||
|
|
||||||
|
private final int remoteValue;
|
||||||
|
|
||||||
|
private MediaType(int remoteValue) {
|
||||||
|
this.remoteValue = remoteValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRemoteValue() {
|
||||||
|
return remoteValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.strava.core.data;
|
||||||
|
|
||||||
|
import java.util.SortedMap;
|
||||||
|
|
||||||
|
public interface RemoteMediaContent extends MediaContent {
|
||||||
|
MediaDimension getLargestSize();
|
||||||
|
|
||||||
|
String getLargestUrl();
|
||||||
|
|
||||||
|
SortedMap<Integer, MediaDimension> getSizes();
|
||||||
|
|
||||||
|
String getSmallestUrl();
|
||||||
|
|
||||||
|
RemoteMediaStatus getStatus();
|
||||||
|
|
||||||
|
SortedMap<Integer, String> getUrls();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.strava.core.data;
|
||||||
|
|
||||||
|
public enum RemoteMediaStatus {
|
||||||
|
NEW,
|
||||||
|
PENDING,
|
||||||
|
PROCESSED,
|
||||||
|
REPORTED,
|
||||||
|
REINSTATED,
|
||||||
|
DELETED,
|
||||||
|
FAILED
|
||||||
|
}
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
package com.strava.photos.data;
|
||||||
|
|
||||||
|
import com.strava.core.data.MediaDimension;
|
||||||
|
import com.strava.core.data.MediaType;
|
||||||
|
import com.strava.core.data.RemoteMediaContent;
|
||||||
|
import com.strava.core.data.RemoteMediaStatus;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
|
||||||
|
public abstract class Media implements RemoteMediaContent {
|
||||||
|
public static final class Photo extends Media {
|
||||||
|
private final Long activityId;
|
||||||
|
private final String activityName;
|
||||||
|
private final long athleteId;
|
||||||
|
private String caption;
|
||||||
|
private final String createdAt;
|
||||||
|
private final String createdAtLocal;
|
||||||
|
private final String cursor;
|
||||||
|
private final String id;
|
||||||
|
private final SortedMap<Integer, MediaDimension> sizes;
|
||||||
|
private final RemoteMediaStatus status;
|
||||||
|
private final String tag;
|
||||||
|
private final MediaType type;
|
||||||
|
private final SortedMap<Integer, String> urls;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getActivityId() {
|
||||||
|
return activityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getActivityName() {
|
||||||
|
return activityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getAthleteId() {
|
||||||
|
return athleteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCaption() {
|
||||||
|
return caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCreatedAtLocal() {
|
||||||
|
return createdAtLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCursor() {
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortedMap<Integer, MediaDimension> getSizes() {
|
||||||
|
return sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RemoteMediaStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortedMap<Integer, String> getUrls() {
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCaption(String caption) {
|
||||||
|
this.caption = caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Photo(String id,
|
||||||
|
String caption,
|
||||||
|
SortedMap<Integer, String> urls,
|
||||||
|
SortedMap<Integer, MediaDimension> sizes,
|
||||||
|
long athleteId,
|
||||||
|
String createdAt,
|
||||||
|
String createdAtLocal,
|
||||||
|
Long activityId,
|
||||||
|
String activityName,
|
||||||
|
RemoteMediaStatus status,
|
||||||
|
String tag,
|
||||||
|
String cursor) {
|
||||||
|
this.id = id;
|
||||||
|
this.caption = caption;
|
||||||
|
this.urls = urls;
|
||||||
|
this.sizes = sizes;
|
||||||
|
this.athleteId = athleteId;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.createdAtLocal = createdAtLocal;
|
||||||
|
this.activityId = activityId;
|
||||||
|
this.activityName = activityName;
|
||||||
|
this.status = status;
|
||||||
|
this.tag = tag;
|
||||||
|
this.cursor = cursor;
|
||||||
|
this.type = MediaType.PHOTO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Video extends Media {
|
||||||
|
private final Long activityId;
|
||||||
|
private final String activityName;
|
||||||
|
private final long athleteId;
|
||||||
|
private String caption;
|
||||||
|
private final String createdAt;
|
||||||
|
private final String createdAtLocal;
|
||||||
|
private final String cursor;
|
||||||
|
private final Float durationSeconds;
|
||||||
|
private final String id;
|
||||||
|
private final SortedMap<Integer, MediaDimension> sizes;
|
||||||
|
private final RemoteMediaStatus status;
|
||||||
|
private final String tag;
|
||||||
|
private final MediaType type;
|
||||||
|
private final SortedMap<Integer, String> urls;
|
||||||
|
private final String videoUrl;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getActivityId() {
|
||||||
|
return activityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getActivityName() {
|
||||||
|
return activityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getAthleteId() {
|
||||||
|
return athleteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCaption() {
|
||||||
|
return caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCreatedAtLocal() {
|
||||||
|
return createdAtLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCursor() {
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Float getDurationSeconds() {
|
||||||
|
return durationSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortedMap<Integer, MediaDimension> getSizes() {
|
||||||
|
return sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RemoteMediaStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortedMap<Integer, String> getUrls() {
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getVideoUrl() {
|
||||||
|
return videoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCaption(String caption) {
|
||||||
|
this.caption = caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Video(String id,
|
||||||
|
String caption,
|
||||||
|
SortedMap<Integer, String> urls,
|
||||||
|
SortedMap<Integer, MediaDimension> sizes,
|
||||||
|
long athleteId,
|
||||||
|
String createdAt,
|
||||||
|
String createdAtLocal,
|
||||||
|
Long activityId,
|
||||||
|
String activityName,
|
||||||
|
RemoteMediaStatus status,
|
||||||
|
String videoUrl,
|
||||||
|
Float durationSeconds,
|
||||||
|
String tag,
|
||||||
|
String cursor) {
|
||||||
|
this.id = id;
|
||||||
|
this.caption = caption;
|
||||||
|
this.urls = urls;
|
||||||
|
this.sizes = sizes;
|
||||||
|
this.athleteId = athleteId;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.createdAtLocal = createdAtLocal;
|
||||||
|
this.activityId = activityId;
|
||||||
|
this.activityName = activityName;
|
||||||
|
this.status = status;
|
||||||
|
this.videoUrl = videoUrl;
|
||||||
|
this.durationSeconds = durationSeconds;
|
||||||
|
this.tag = tag;
|
||||||
|
this.cursor = cursor;
|
||||||
|
this.type = MediaType.VIDEO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Long getActivityId();
|
||||||
|
|
||||||
|
public abstract String getActivityName();
|
||||||
|
|
||||||
|
public abstract long getAthleteId();
|
||||||
|
|
||||||
|
public abstract String getCreatedAt();
|
||||||
|
|
||||||
|
public abstract String getCreatedAtLocal();
|
||||||
|
|
||||||
|
public abstract String getCursor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaDimension getLargestSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLargestUrl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReferenceId() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSmallestUrl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getTag();
|
||||||
|
|
||||||
|
private Media() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package app.revanced.extension.youtube.patches;
|
||||||
|
|
||||||
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class PauseOnAudioInterruptPatch {
|
||||||
|
|
||||||
|
private static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3;
|
||||||
|
private static final int AUDIOFOCUS_LOSS_TRANSIENT = -2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point for AudioFocusRequest builder.
|
||||||
|
* Returns true if audio ducking should be disabled (willPauseWhenDucked = true).
|
||||||
|
*/
|
||||||
|
public static boolean shouldPauseOnAudioInterrupt() {
|
||||||
|
return Settings.PAUSE_ON_AUDIO_INTERRUPT.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point for onAudioFocusChange callback.
|
||||||
|
* Converts AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK to AUDIOFOCUS_LOSS_TRANSIENT
|
||||||
|
* when the setting is enabled, causing YouTube to pause instead of ducking.
|
||||||
|
*/
|
||||||
|
public static int overrideAudioFocusChange(int focusChange) {
|
||||||
|
if (Settings.PAUSE_ON_AUDIO_INTERRUPT.get() && focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
|
||||||
|
return AUDIOFOCUS_LOSS_TRANSIENT;
|
||||||
|
}
|
||||||
|
return focusChange;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,10 +44,14 @@ final class DescriptionComponentsFilter extends Filter {
|
|||||||
"video_attributes_section"
|
"video_attributes_section"
|
||||||
);
|
);
|
||||||
|
|
||||||
final StringFilterGroup featuredSection = new StringFilterGroup(
|
final StringFilterGroup featuredLinksSection = new StringFilterGroup(
|
||||||
Settings.HIDE_FEATURED_SECTION,
|
Settings.HIDE_FEATURED_LINKS_SECTION,
|
||||||
// "media_lockup", "structured_description_video_lockup"
|
"media_lockup"
|
||||||
"compact_infocard"
|
);
|
||||||
|
|
||||||
|
final StringFilterGroup featuredVideosSection = new StringFilterGroup(
|
||||||
|
Settings.HIDE_FEATURED_VIDEOS_SECTION,
|
||||||
|
"structured_description_video_lockup"
|
||||||
);
|
);
|
||||||
|
|
||||||
final StringFilterGroup podcastSection = new StringFilterGroup(
|
final StringFilterGroup podcastSection = new StringFilterGroup(
|
||||||
@@ -76,7 +80,7 @@ final class DescriptionComponentsFilter extends Filter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
subscribeButton = new StringFilterGroup(
|
subscribeButton = new StringFilterGroup(
|
||||||
Settings.HIDE_DESCRIPTION_SUBSCRIBE_BUTTON,
|
Settings.HIDE_SUBSCRIBE_BUTTON,
|
||||||
"subscribe_button"
|
"subscribe_button"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -110,7 +114,8 @@ final class DescriptionComponentsFilter extends Filter {
|
|||||||
aiGeneratedVideoSummarySection,
|
aiGeneratedVideoSummarySection,
|
||||||
askSection,
|
askSection,
|
||||||
attributesSection,
|
attributesSection,
|
||||||
featuredSection,
|
featuredLinksSection,
|
||||||
|
featuredVideosSection,
|
||||||
horizontalShelf,
|
horizontalShelf,
|
||||||
howThisWasMadeSection,
|
howThisWasMadeSection,
|
||||||
hypePoints,
|
hypePoints,
|
||||||
|
|||||||
@@ -21,22 +21,26 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class LayoutComponentsFilter extends Filter {
|
public final class LayoutComponentsFilter extends Filter {
|
||||||
private static final StringTrieSearch mixPlaylistsExceptions = new StringTrieSearch(
|
private static final StringTrieSearch mixPlaylistsContextExceptions = new StringTrieSearch(
|
||||||
"V.ED", // Playlist browse id.
|
"V.ED", // Playlist browse id.
|
||||||
"java.lang.ref.WeakReference"
|
"java.lang.ref.WeakReference"
|
||||||
);
|
);
|
||||||
private static final ByteArrayFilterGroup mixPlaylistsExceptions2 = new ByteArrayFilterGroup(
|
private static final ByteArrayFilterGroup mixPlaylistsBufferExceptions = new ByteArrayFilterGroup(
|
||||||
null,
|
null,
|
||||||
"cell_description_body"
|
"cell_description_body",
|
||||||
|
"channel_profile"
|
||||||
);
|
);
|
||||||
private static final ByteArrayFilterGroup mixPlaylists = new ByteArrayFilterGroup(
|
private static final ByteArrayFilterGroup mixPlaylists = new ByteArrayFilterGroup(
|
||||||
null,
|
null,
|
||||||
"&list="
|
"&list="
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static final String PAGE_HEADER_PATH = "page_header.e";
|
||||||
|
|
||||||
private final StringTrieSearch exceptions = new StringTrieSearch();
|
private final StringTrieSearch exceptions = new StringTrieSearch();
|
||||||
private final StringFilterGroup communityPosts;
|
private final StringFilterGroup communityPosts;
|
||||||
private final StringFilterGroup surveys;
|
private final StringFilterGroup surveys;
|
||||||
|
private final StringFilterGroup subscribeButton;
|
||||||
private final StringFilterGroup notifyMe;
|
private final StringFilterGroup notifyMe;
|
||||||
private final StringFilterGroup singleItemInformationPanel;
|
private final StringFilterGroup singleItemInformationPanel;
|
||||||
private final StringFilterGroup expandableMetadata;
|
private final StringFilterGroup expandableMetadata;
|
||||||
@@ -67,8 +71,14 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
"chips_shelf"
|
"chips_shelf"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final var visualSpacer = new StringFilterGroup(
|
||||||
|
Settings.HIDE_VISUAL_SPACER,
|
||||||
|
"cell_divider"
|
||||||
|
);
|
||||||
|
|
||||||
addIdentifierCallbacks(
|
addIdentifierCallbacks(
|
||||||
chipsShelf
|
chipsShelf,
|
||||||
|
visualSpacer
|
||||||
);
|
);
|
||||||
|
|
||||||
// Paths.
|
// Paths.
|
||||||
@@ -237,8 +247,13 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
"sponsorships"
|
"sponsorships"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final var crowdfundingBox = new StringFilterGroup(
|
||||||
|
Settings.HIDE_CROWDFUNDING_BOX,
|
||||||
|
"donation_shelf"
|
||||||
|
);
|
||||||
|
|
||||||
final var channelWatermark = new StringFilterGroup(
|
final var channelWatermark = new StringFilterGroup(
|
||||||
Settings.HIDE_VIDEO_CHANNEL_WATERMARK,
|
Settings.HIDE_CHANNEL_WATERMARK,
|
||||||
"featured_channel_watermark_overlay"
|
"featured_channel_watermark_overlay"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -255,19 +270,28 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
channelProfile = new StringFilterGroup(
|
channelProfile = new StringFilterGroup(
|
||||||
null,
|
null,
|
||||||
"channel_profile.e",
|
"channel_profile.e",
|
||||||
"page_header.e"
|
PAGE_HEADER_PATH
|
||||||
);
|
);
|
||||||
channelProfileBuffer = new ByteArrayFilterGroupList();
|
channelProfileBuffer = new ByteArrayFilterGroupList();
|
||||||
channelProfileBuffer.addAll(new ByteArrayFilterGroup(
|
channelProfileBuffer.addAll(new ByteArrayFilterGroup(
|
||||||
Settings.HIDE_VISIT_STORE_BUTTON,
|
Settings.HIDE_STORE_BUTTON,
|
||||||
"header_store_button"
|
"store_button"
|
||||||
),
|
),
|
||||||
new ByteArrayFilterGroup(
|
new ByteArrayFilterGroup(
|
||||||
Settings.HIDE_VISIT_COMMUNITY_BUTTON,
|
Settings.HIDE_COMMUNITY_BUTTON,
|
||||||
"community_button"
|
"community_button"
|
||||||
|
),
|
||||||
|
new ByteArrayFilterGroup(
|
||||||
|
Settings.HIDE_JOIN_BUTTON,
|
||||||
|
"sponsor_button"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
subscribeButton = new StringFilterGroup(
|
||||||
|
Settings.HIDE_SUBSCRIBE_BUTTON_IN_CHANNEL_PAGE,
|
||||||
|
"subscribe_button"
|
||||||
|
);
|
||||||
|
|
||||||
horizontalShelves = new StringFilterGroup(
|
horizontalShelves = new StringFilterGroup(
|
||||||
Settings.HIDE_HORIZONTAL_SHELVES,
|
Settings.HIDE_HORIZONTAL_SHELVES,
|
||||||
"horizontal_video_shelf.e",
|
"horizontal_video_shelf.e",
|
||||||
@@ -293,6 +317,7 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
compactChannelBar,
|
compactChannelBar,
|
||||||
compactChannelBarInner,
|
compactChannelBarInner,
|
||||||
communityPosts,
|
communityPosts,
|
||||||
|
crowdfundingBox,
|
||||||
emergencyBox,
|
emergencyBox,
|
||||||
expandableMetadata,
|
expandableMetadata,
|
||||||
forYouShelf,
|
forYouShelf,
|
||||||
@@ -307,6 +332,7 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
quickActions,
|
quickActions,
|
||||||
relatedVideos,
|
relatedVideos,
|
||||||
singleItemInformationPanel,
|
singleItemInformationPanel,
|
||||||
|
subscribeButton,
|
||||||
subscribersCommunityGuidelines,
|
subscribersCommunityGuidelines,
|
||||||
subscriptionsChipBar,
|
subscriptionsChipBar,
|
||||||
surveys,
|
surveys,
|
||||||
@@ -337,6 +363,10 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
return channelProfileBuffer.check(buffer).isFiltered();
|
return channelProfileBuffer.check(buffer).isFiltered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (matchedGroup == subscribeButton) {
|
||||||
|
return path.startsWith(PAGE_HEADER_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
if (matchedGroup == communityPosts && NavigationBar.isBackButtonVisible()) {
|
if (matchedGroup == communityPosts && NavigationBar.isBackButtonVisible()) {
|
||||||
// Allow community posts on channel profile page,
|
// Allow community posts on channel profile page,
|
||||||
// or if viewing an individual channel in the feed.
|
// or if viewing an individual channel in the feed.
|
||||||
@@ -380,17 +410,15 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent playlist items being hidden, if a mix playlist is present in it.
|
if (mixPlaylists.check(bytes).isFiltered()
|
||||||
if (mixPlaylistsExceptions.matches(conversionContext.toString())) {
|
// Prevent hiding the description of some videos accidentally.
|
||||||
return false;
|
&& !mixPlaylistsBufferExceptions.check(bytes).isFiltered()
|
||||||
}
|
// Prevent playlist items being hidden, if a mix playlist is present in it.
|
||||||
|
// Check last since it requires creating a context string.
|
||||||
// Prevent hiding the description of some videos accidentally.
|
//
|
||||||
if (mixPlaylistsExceptions2.check(bytes).isFiltered()) {
|
// FIXME: The conversion context passed in does not always generate a valid toString.
|
||||||
return false;
|
// This string check may no longer be needed, or the patch may be broken.
|
||||||
}
|
&& !mixPlaylistsContextExceptions.matches(conversionContext.toString())) {
|
||||||
|
|
||||||
if (mixPlaylists.check(bytes).isFiltered()) {
|
|
||||||
Logger.printDebug(() -> "Filtered mix playlist");
|
Logger.printDebug(() -> "Filtered mix playlist");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -405,7 +433,7 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static boolean showWatermark() {
|
public static boolean showWatermark() {
|
||||||
return !Settings.HIDE_VIDEO_CHANNEL_WATERMARK.get();
|
return !Settings.HIDE_CHANNEL_WATERMARK.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,9 @@ import java.util.List;
|
|||||||
public class PlayerFlyoutMenuItemsFilter extends Filter {
|
public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||||
|
|
||||||
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
|
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
|
||||||
private static final boolean AVAILABLE_ON_LAUNCH = !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAvailable() {
|
public boolean isAvailable() {
|
||||||
// Check conditions of launch and now. Otherwise if spoofing is changed
|
return !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
||||||
// without a restart the setting will show as available when it's not.
|
|
||||||
return AVAILABLE_ON_LAUNCH && !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -44,9 +44,10 @@ public final class ShortsFilter extends Filter {
|
|||||||
private final StringFilterGroup useTemplateButton;
|
private final StringFilterGroup useTemplateButton;
|
||||||
private final ByteArrayFilterGroup useTemplateButtonBuffer;
|
private final ByteArrayFilterGroup useTemplateButtonBuffer;
|
||||||
|
|
||||||
|
private final StringFilterGroup autoDubbedLabel;
|
||||||
private final StringFilterGroup subscribeButton;
|
private final StringFilterGroup subscribeButton;
|
||||||
private final StringFilterGroup joinButton;
|
private final StringFilterGroup joinButton;
|
||||||
private final StringFilterGroup paidPromotionButton;
|
private final StringFilterGroup paidPromotionLabel;
|
||||||
private final StringFilterGroup shelfHeader;
|
private final StringFilterGroup shelfHeader;
|
||||||
|
|
||||||
private final StringFilterGroup suggestedAction;
|
private final StringFilterGroup suggestedAction;
|
||||||
@@ -161,6 +162,18 @@ public final class ShortsFilter extends Filter {
|
|||||||
"participation_bar.e"
|
"participation_bar.e"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
StringFilterGroup livePreview = new StringFilterGroup(
|
||||||
|
Settings.HIDE_SHORTS_LIVE_PREVIEW,
|
||||||
|
// Live Shorts preview that can popup while scrolling through Shorts player.
|
||||||
|
// Can be removed if a way to disable live Shorts is found.
|
||||||
|
"live_preview_page_vm.e"
|
||||||
|
);
|
||||||
|
|
||||||
|
autoDubbedLabel = new StringFilterGroup(
|
||||||
|
Settings.HIDE_SHORTS_AUTO_DUBBED_LABEL,
|
||||||
|
"badge."
|
||||||
|
);
|
||||||
|
|
||||||
joinButton = new StringFilterGroup(
|
joinButton = new StringFilterGroup(
|
||||||
Settings.HIDE_SHORTS_JOIN_BUTTON,
|
Settings.HIDE_SHORTS_JOIN_BUTTON,
|
||||||
"sponsor_button"
|
"sponsor_button"
|
||||||
@@ -171,9 +184,10 @@ public final class ShortsFilter extends Filter {
|
|||||||
"subscribe_button"
|
"subscribe_button"
|
||||||
);
|
);
|
||||||
|
|
||||||
paidPromotionButton = new StringFilterGroup(
|
paidPromotionLabel = new StringFilterGroup(
|
||||||
Settings.HIDE_PAID_PROMOTION_LABEL,
|
Settings.HIDE_PAID_PROMOTION_LABEL,
|
||||||
"reel_player_disclosure.e"
|
"reel_player_disclosure.e",
|
||||||
|
"shorts_disclosures.e"
|
||||||
);
|
);
|
||||||
|
|
||||||
shortsActionBar = new StringFilterGroup(
|
shortsActionBar = new StringFilterGroup(
|
||||||
@@ -219,10 +233,10 @@ public final class ShortsFilter extends Filter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
addPathCallbacks(
|
addPathCallbacks(
|
||||||
shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionButton,
|
shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionLabel, autoDubbedLabel,
|
||||||
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar, previewComment,
|
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar, previewComment,
|
||||||
fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
|
fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
|
||||||
stickers, likeFountain, likeButton, dislikeButton
|
stickers, likeFountain, likeButton, dislikeButton, livePreview
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -250,6 +264,12 @@ public final class ShortsFilter extends Filter {
|
|||||||
// Suggested actions.
|
// Suggested actions.
|
||||||
//
|
//
|
||||||
suggestedActionsBuffer.addAll(
|
suggestedActionsBuffer.addAll(
|
||||||
|
new ByteArrayFilterGroup(
|
||||||
|
Settings.HIDE_SHORTS_PREVIEW_COMMENT,
|
||||||
|
// Preview comment that can popup while a Short is playing.
|
||||||
|
// Uses no bundled icons, and instead the users profile photo is shown.
|
||||||
|
"shorts-comments-panel"
|
||||||
|
),
|
||||||
new ByteArrayFilterGroup(
|
new ByteArrayFilterGroup(
|
||||||
Settings.HIDE_SHORTS_SHOP_BUTTON,
|
Settings.HIDE_SHORTS_SHOP_BUTTON,
|
||||||
"yt_outline_bag_"
|
"yt_outline_bag_"
|
||||||
@@ -322,7 +342,8 @@ public final class ShortsFilter extends Filter {
|
|||||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||||
if (contentType == FilterContentType.PATH) {
|
if (contentType == FilterContentType.PATH) {
|
||||||
if (matchedGroup == subscribeButton || matchedGroup == joinButton || matchedGroup == paidPromotionButton) {
|
if (matchedGroup == subscribeButton || matchedGroup == joinButton
|
||||||
|
|| matchedGroup == paidPromotionLabel || matchedGroup == autoDubbedLabel) {
|
||||||
// Selectively filter to avoid false positive filtering of other subscribe/join buttons.
|
// Selectively filter to avoid false positive filtering of other subscribe/join buttons.
|
||||||
return path.startsWith(REEL_CHANNEL_BAR_PATH) || path.startsWith(REEL_METAPANEL_PATH);
|
return path.startsWith(REEL_CHANNEL_BAR_PATH) || path.startsWith(REEL_METAPANEL_PATH);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package app.revanced.extension.youtube.settings;
|
|||||||
import static java.lang.Boolean.FALSE;
|
import static java.lang.Boolean.FALSE;
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||||
|
import static app.revanced.extension.shared.settings.Setting.parentNot;
|
||||||
import static app.revanced.extension.shared.settings.Setting.parentsAll;
|
import static app.revanced.extension.shared.settings.Setting.parentsAll;
|
||||||
import static app.revanced.extension.shared.settings.Setting.parentsAny;
|
import static app.revanced.extension.shared.settings.Setting.parentsAny;
|
||||||
import static app.revanced.extension.youtube.patches.ChangeFormFactorPatch.FormFactor;
|
import static app.revanced.extension.youtube.patches.ChangeFormFactorPatch.FormFactor;
|
||||||
@@ -95,7 +96,6 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_CHIPS_SHELF = new BooleanSetting("revanced_hide_chips_shelf", TRUE);
|
public static final BooleanSetting HIDE_CHIPS_SHELF = new BooleanSetting("revanced_hide_chips_shelf", TRUE);
|
||||||
public static final BooleanSetting HIDE_COMMUNITY_POSTS = new BooleanSetting("revanced_hide_community_posts", FALSE);
|
public static final BooleanSetting HIDE_COMMUNITY_POSTS = new BooleanSetting("revanced_hide_community_posts", FALSE);
|
||||||
public static final BooleanSetting HIDE_COMPACT_BANNER = new BooleanSetting("revanced_hide_compact_banner", TRUE);
|
public static final BooleanSetting HIDE_COMPACT_BANNER = new BooleanSetting("revanced_hide_compact_banner", TRUE);
|
||||||
public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true);
|
|
||||||
public static final BooleanSetting HIDE_DOODLES = new BooleanSetting("revanced_hide_doodles", FALSE, true, "revanced_hide_doodles_user_dialog_message");
|
public static final BooleanSetting HIDE_DOODLES = new BooleanSetting("revanced_hide_doodles", FALSE, true, "revanced_hide_doodles_user_dialog_message");
|
||||||
public static final BooleanSetting HIDE_EXPANDABLE_CARD = new BooleanSetting("revanced_hide_expandable_card", TRUE);
|
public static final BooleanSetting HIDE_EXPANDABLE_CARD = new BooleanSetting("revanced_hide_expandable_card", TRUE);
|
||||||
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true);
|
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true);
|
||||||
@@ -115,6 +115,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_UPLOAD_TIME = new BooleanSetting("revanced_hide_upload_time", FALSE, "revanced_hide_upload_time_user_dialog_message");
|
public static final BooleanSetting HIDE_UPLOAD_TIME = new BooleanSetting("revanced_hide_upload_time", FALSE, "revanced_hide_upload_time_user_dialog_message");
|
||||||
public static final BooleanSetting HIDE_VIDEO_RECOMMENDATION_LABELS = new BooleanSetting("revanced_hide_video_recommendation_labels", TRUE);
|
public static final BooleanSetting HIDE_VIDEO_RECOMMENDATION_LABELS = new BooleanSetting("revanced_hide_video_recommendation_labels", TRUE);
|
||||||
public static final BooleanSetting HIDE_VIEW_COUNT = new BooleanSetting("revanced_hide_view_count", FALSE, "revanced_hide_view_count_user_dialog_message");
|
public static final BooleanSetting HIDE_VIEW_COUNT = new BooleanSetting("revanced_hide_view_count", FALSE, "revanced_hide_view_count_user_dialog_message");
|
||||||
|
public static final BooleanSetting HIDE_VISUAL_SPACER = new BooleanSetting("revanced_hide_visual_spacer", TRUE);
|
||||||
|
|
||||||
// Alternative thumbnails
|
// Alternative thumbnails
|
||||||
public static final EnumSetting<ThumbnailOption> ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL);
|
public static final EnumSetting<ThumbnailOption> ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL);
|
||||||
@@ -136,11 +137,13 @@ public class Settings extends BaseSettings {
|
|||||||
parentsAny(HIDE_KEYWORD_CONTENT_HOME, HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS, HIDE_KEYWORD_CONTENT_SEARCH));
|
parentsAny(HIDE_KEYWORD_CONTENT_HOME, HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS, HIDE_KEYWORD_CONTENT_SEARCH));
|
||||||
|
|
||||||
// Channel page
|
// Channel page
|
||||||
|
public static final BooleanSetting HIDE_COMMUNITY_BUTTON = new BooleanSetting("revanced_hide_community_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_FOR_YOU_SHELF = new BooleanSetting("revanced_hide_for_you_shelf", FALSE);
|
public static final BooleanSetting HIDE_FOR_YOU_SHELF = new BooleanSetting("revanced_hide_for_you_shelf", FALSE);
|
||||||
|
public static final BooleanSetting HIDE_JOIN_BUTTON = new BooleanSetting("revanced_hide_join_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_LINKS_PREVIEW = new BooleanSetting("revanced_hide_links_preview", TRUE);
|
public static final BooleanSetting HIDE_LINKS_PREVIEW = new BooleanSetting("revanced_hide_links_preview", TRUE);
|
||||||
public static final BooleanSetting HIDE_MEMBERS_SHELF = new BooleanSetting("revanced_hide_members_shelf", TRUE);
|
public static final BooleanSetting HIDE_MEMBERS_SHELF = new BooleanSetting("revanced_hide_members_shelf", TRUE);
|
||||||
public static final BooleanSetting HIDE_VISIT_COMMUNITY_BUTTON = new BooleanSetting("revanced_hide_visit_community_button", TRUE);
|
public static final BooleanSetting HIDE_STORE_BUTTON = new BooleanSetting("revanced_hide_store_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_VISIT_STORE_BUTTON = new BooleanSetting("revanced_hide_visit_store_button", TRUE);
|
public static final BooleanSetting HIDE_SUBSCRIBE_BUTTON_IN_CHANNEL_PAGE = new BooleanSetting("revanced_hide_subscribe_button_in_channel_page", FALSE);
|
||||||
|
|
||||||
// Player
|
// Player
|
||||||
public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE);
|
public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE);
|
||||||
@@ -154,6 +157,8 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_CAPTIONS_BUTTON = new BooleanSetting("revanced_hide_captions_button", FALSE);
|
public static final BooleanSetting HIDE_CAPTIONS_BUTTON = new BooleanSetting("revanced_hide_captions_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_hide_cast_button", TRUE, true);
|
public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_hide_cast_button", TRUE, true);
|
||||||
public static final BooleanSetting HIDE_CHANNEL_BAR = new BooleanSetting("revanced_hide_channel_bar", FALSE);
|
public static final BooleanSetting HIDE_CHANNEL_BAR = new BooleanSetting("revanced_hide_channel_bar", FALSE);
|
||||||
|
public static final BooleanSetting HIDE_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE);
|
||||||
|
public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true);
|
||||||
public static final BooleanSetting HIDE_EMERGENCY_BOX = new BooleanSetting("revanced_hide_emergency_box", TRUE);
|
public static final BooleanSetting HIDE_EMERGENCY_BOX = new BooleanSetting("revanced_hide_emergency_box", TRUE);
|
||||||
public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", FALSE);
|
public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", FALSE);
|
||||||
public static final BooleanSetting HIDE_END_SCREEN_SUGGESTED_VIDEO = new BooleanSetting("revanced_end_screen_suggested_video", FALSE, true);
|
public static final BooleanSetting HIDE_END_SCREEN_SUGGESTED_VIDEO = new BooleanSetting("revanced_end_screen_suggested_video", FALSE, true);
|
||||||
@@ -168,7 +173,6 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_RELATED_VIDEOS = new BooleanSetting("revanced_hide_related_videos", FALSE);
|
public static final BooleanSetting HIDE_RELATED_VIDEOS = new BooleanSetting("revanced_hide_related_videos", FALSE);
|
||||||
public static final BooleanSetting HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES = new BooleanSetting("revanced_hide_subscribers_community_guidelines", TRUE);
|
public static final BooleanSetting HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES = new BooleanSetting("revanced_hide_subscribers_community_guidelines", TRUE);
|
||||||
public static final BooleanSetting HIDE_TIMED_REACTIONS = new BooleanSetting("revanced_hide_timed_reactions", TRUE);
|
public static final BooleanSetting HIDE_TIMED_REACTIONS = new BooleanSetting("revanced_hide_timed_reactions", TRUE);
|
||||||
public static final BooleanSetting HIDE_VIDEO_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE);
|
|
||||||
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
|
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
|
||||||
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
||||||
public static final BooleanSetting VIDEO_QUALITY_DIALOG_BUTTON = new BooleanSetting("revanced_video_quality_dialog_button", FALSE);
|
public static final BooleanSetting VIDEO_QUALITY_DIALOG_BUTTON = new BooleanSetting("revanced_video_quality_dialog_button", FALSE);
|
||||||
@@ -210,13 +214,14 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_ASK_SECTION = new BooleanSetting("revanced_hide_ask_section", FALSE);
|
public static final BooleanSetting HIDE_ASK_SECTION = new BooleanSetting("revanced_hide_ask_section", FALSE);
|
||||||
public static final BooleanSetting HIDE_ATTRIBUTES_SECTION = new BooleanSetting("revanced_hide_attributes_section", FALSE);
|
public static final BooleanSetting HIDE_ATTRIBUTES_SECTION = new BooleanSetting("revanced_hide_attributes_section", FALSE);
|
||||||
public static final BooleanSetting HIDE_CHAPTERS_SECTION = new BooleanSetting("revanced_hide_chapters_section", TRUE);
|
public static final BooleanSetting HIDE_CHAPTERS_SECTION = new BooleanSetting("revanced_hide_chapters_section", TRUE);
|
||||||
public static final BooleanSetting HIDE_FEATURED_SECTION = new BooleanSetting("revanced_hide_featured_section", TRUE);
|
|
||||||
public static final BooleanSetting HIDE_HOW_THIS_WAS_MADE_SECTION = new BooleanSetting("revanced_hide_how_this_was_made_section", FALSE);
|
public static final BooleanSetting HIDE_HOW_THIS_WAS_MADE_SECTION = new BooleanSetting("revanced_hide_how_this_was_made_section", FALSE);
|
||||||
public static final BooleanSetting HIDE_HYPE_POINTS = new BooleanSetting("revanced_hide_hype_points", FALSE);
|
public static final BooleanSetting HIDE_HYPE_POINTS = new BooleanSetting("revanced_hide_hype_points", FALSE);
|
||||||
public static final BooleanSetting HIDE_INFO_CARDS_SECTION = new BooleanSetting("revanced_hide_info_cards_section", TRUE);
|
public static final BooleanSetting HIDE_INFO_CARDS_SECTION = new BooleanSetting("revanced_hide_info_cards_section", TRUE);
|
||||||
|
public static final BooleanSetting HIDE_FEATURED_LINKS_SECTION = new BooleanSetting("revanced_hide_featured_links_section", FALSE, parentNot(HIDE_INFO_CARDS_SECTION));
|
||||||
|
public static final BooleanSetting HIDE_FEATURED_VIDEOS_SECTION = new BooleanSetting("revanced_hide_featured_videos_section", FALSE, parentNot(HIDE_INFO_CARDS_SECTION));
|
||||||
|
public static final BooleanSetting HIDE_SUBSCRIBE_BUTTON = new BooleanSetting("revanced_hide_subscribe_button", FALSE, parentNot(HIDE_INFO_CARDS_SECTION));
|
||||||
public static final BooleanSetting HIDE_KEY_CONCEPTS_SECTION = new BooleanSetting("revanced_hide_key_concepts_section", FALSE);
|
public static final BooleanSetting HIDE_KEY_CONCEPTS_SECTION = new BooleanSetting("revanced_hide_key_concepts_section", FALSE);
|
||||||
public static final BooleanSetting HIDE_PODCAST_SECTION = new BooleanSetting("revanced_hide_podcast_section", TRUE);
|
public static final BooleanSetting HIDE_PODCAST_SECTION = new BooleanSetting("revanced_hide_podcast_section", TRUE);
|
||||||
public static final BooleanSetting HIDE_DESCRIPTION_SUBSCRIBE_BUTTON = new BooleanSetting("revanced_hide_description_subscribe_button", TRUE);
|
|
||||||
public static final BooleanSetting HIDE_TRANSCRIPT_SECTION = new BooleanSetting("revanced_hide_transcript_section", TRUE);
|
public static final BooleanSetting HIDE_TRANSCRIPT_SECTION = new BooleanSetting("revanced_hide_transcript_section", TRUE);
|
||||||
|
|
||||||
// Action buttons
|
// Action buttons
|
||||||
@@ -228,11 +233,11 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_HYPE_BUTTON = new BooleanSetting("revanced_hide_hype_button", FALSE);
|
public static final BooleanSetting HIDE_HYPE_BUTTON = new BooleanSetting("revanced_hide_hype_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_LIKE_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_like_dislike_button", FALSE);
|
public static final BooleanSetting HIDE_LIKE_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_like_dislike_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_PROMOTE_BUTTON = new BooleanSetting("revanced_hide_promote_button", FALSE);
|
public static final BooleanSetting HIDE_PROMOTE_BUTTON = new BooleanSetting("revanced_hide_promote_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_REMIX_BUTTON = new BooleanSetting("revanced_hide_remix_button", TRUE);
|
public static final BooleanSetting HIDE_REMIX_BUTTON = new BooleanSetting("revanced_hide_remix_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_REPORT_BUTTON = new BooleanSetting("revanced_hide_report_button", FALSE);
|
public static final BooleanSetting HIDE_REPORT_BUTTON = new BooleanSetting("revanced_hide_report_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SAVE_BUTTON = new BooleanSetting("revanced_hide_save_button", FALSE);
|
public static final BooleanSetting HIDE_SAVE_BUTTON = new BooleanSetting("revanced_hide_save_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHARE_BUTTON = new BooleanSetting("revanced_hide_share_button", FALSE);
|
public static final BooleanSetting HIDE_SHARE_BUTTON = new BooleanSetting("revanced_hide_share_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHOP_BUTTON = new BooleanSetting("revanced_hide_shop_button", FALSE);
|
public static final BooleanSetting HIDE_SHOP_BUTTON = new BooleanSetting("revanced_hide_shop_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_STOP_ADS_BUTTON = new BooleanSetting("revanced_hide_stop_ads_button", TRUE);
|
public static final BooleanSetting HIDE_STOP_ADS_BUTTON = new BooleanSetting("revanced_hide_stop_ads_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_THANKS_BUTTON = new BooleanSetting("revanced_hide_thanks_button", TRUE);
|
public static final BooleanSetting HIDE_THANKS_BUTTON = new BooleanSetting("revanced_hide_thanks_button", TRUE);
|
||||||
|
|
||||||
@@ -292,6 +297,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE);
|
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE);
|
||||||
public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_shorts_disable_background_playback", FALSE);
|
public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_shorts_disable_background_playback", FALSE);
|
||||||
public static final EnumSetting<ShortsPlayerType> SHORTS_PLAYER_TYPE = new EnumSetting<>("revanced_shorts_player_type", ShortsPlayerType.SHORTS_PLAYER);
|
public static final EnumSetting<ShortsPlayerType> SHORTS_PLAYER_TYPE = new EnumSetting<>("revanced_shorts_player_type", ShortsPlayerType.SHORTS_PLAYER);
|
||||||
|
public static final BooleanSetting HIDE_SHORTS_AUTO_DUBBED_LABEL = new BooleanSetting("revanced_hide_shorts_auto_dubbed_label", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_CHANNEL_BAR = new BooleanSetting("revanced_hide_shorts_channel_bar", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_CHANNEL_BAR = new BooleanSetting("revanced_hide_shorts_channel_bar", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_COMMENTS_BUTTON = new BooleanSetting("revanced_hide_shorts_comments_button", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_COMMENTS_BUTTON = new BooleanSetting("revanced_hide_shorts_comments_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE);
|
||||||
@@ -306,11 +312,12 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_SHORTS_JOIN_BUTTON = new BooleanSetting("revanced_hide_shorts_join_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_JOIN_BUTTON = new BooleanSetting("revanced_hide_shorts_join_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_LIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_like_button", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_LIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_like_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_LIKE_FOUNTAIN = new BooleanSetting("revanced_hide_shorts_like_fountain", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_LIKE_FOUNTAIN = new BooleanSetting("revanced_hide_shorts_like_fountain", TRUE);
|
||||||
|
public static final BooleanSetting HIDE_SHORTS_LIVE_PREVIEW = new BooleanSetting("revanced_hide_shorts_live_preview", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_NAVIGATION_BAR = new BooleanSetting("revanced_hide_shorts_navigation_bar", FALSE, true);
|
public static final BooleanSetting HIDE_SHORTS_NAVIGATION_BAR = new BooleanSetting("revanced_hide_shorts_navigation_bar", FALSE, true);
|
||||||
public static final BooleanSetting HIDE_SHORTS_PAUSED_OVERLAY_BUTTONS = new BooleanSetting("revanced_hide_shorts_paused_overlay_buttons", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_PAUSED_OVERLAY_BUTTONS = new BooleanSetting("revanced_hide_shorts_paused_overlay_buttons", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_PREVIEW_COMMENT = new BooleanSetting("revanced_hide_shorts_preview_comment", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_PREVIEW_COMMENT = new BooleanSetting("revanced_hide_shorts_preview_comment", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_REMIX_BUTTON = new BooleanSetting("revanced_hide_shorts_remix_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_REMIX_BUTTON = new BooleanSetting("revanced_hide_shorts_remix_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SEARCH = new BooleanSetting("revanced_hide_shorts_search", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_SEARCH = new BooleanSetting("revanced_hide_shorts_search", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", TRUE);
|
||||||
@@ -349,6 +356,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1, false, false);
|
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1, false, false);
|
||||||
public static final BooleanSetting LOOP_VIDEO = new BooleanSetting("revanced_loop_video", FALSE);
|
public static final BooleanSetting LOOP_VIDEO = new BooleanSetting("revanced_loop_video", FALSE);
|
||||||
public static final BooleanSetting LOOP_VIDEO_BUTTON = new BooleanSetting("revanced_loop_video_button", FALSE);
|
public static final BooleanSetting LOOP_VIDEO_BUTTON = new BooleanSetting("revanced_loop_video_button", FALSE);
|
||||||
|
public static final BooleanSetting PAUSE_ON_AUDIO_INTERRUPT = new BooleanSetting("revanced_pause_on_audio_interrupt", FALSE, true);
|
||||||
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE);
|
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE);
|
||||||
public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_CHAPTERS = new BooleanSetting("revanced_disable_haptic_feedback_chapters", FALSE);
|
public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_CHAPTERS = new BooleanSetting("revanced_disable_haptic_feedback_chapters", FALSE);
|
||||||
public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_PRECISE_SEEKING = new BooleanSetting("revanced_disable_haptic_feedback_precise_seeking", FALSE);
|
public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_PRECISE_SEEKING = new BooleanSetting("revanced_disable_haptic_feedback_precise_seeking", FALSE);
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 5.46.0-dev.10
|
version = 5.48.0-dev.9
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
public final class DisableReelsScrollingPatchKt {
|
||||||
|
public static final fun getDisableReelsScrollingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/all/misc/activity/exportall/ExportAllActivitiesPatchKt {
|
public final class app/revanced/patches/all/misc/activity/exportall/ExportAllActivitiesPatchKt {
|
||||||
public static final fun getExportAllActivitiesPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
public static final fun getExportAllActivitiesPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
}
|
}
|
||||||
@@ -56,6 +60,10 @@ public final class app/revanced/patches/all/misc/connectivity/telephony/sim/spoo
|
|||||||
public static final fun getSpoofSimCountryPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSpoofSimCountryPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimProviderPatchKt {
|
||||||
|
public static final fun getSpoofSimProviderPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatchKt {
|
public final class app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatchKt {
|
||||||
public static final fun getSpoofWifiPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSpoofWifiPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -96,6 +104,10 @@ public final class app/revanced/patches/all/misc/packagename/ChangePackageNamePa
|
|||||||
public static final fun setPackageNameOption (Lapp/revanced/patcher/patch/Option;)V
|
public static final fun setPackageNameOption (Lapp/revanced/patcher/patch/Option;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/all/misc/playintegrity/DisablePlayIntegrityKt {
|
||||||
|
public static final fun getDisablePlayIntegrityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/all/misc/resources/AddResourcesPatchKt {
|
public final class app/revanced/patches/all/misc/resources/AddResourcesPatchKt {
|
||||||
public static final fun addResource (Ljava/lang/String;Lapp/revanced/util/resource/BaseResource;)Z
|
public static final fun addResource (Ljava/lang/String;Lapp/revanced/util/resource/BaseResource;)Z
|
||||||
public static final fun addResources (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;)Z
|
public static final fun addResources (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;)Z
|
||||||
@@ -168,6 +180,10 @@ public final class app/revanced/patches/cieid/restrictions/root/BypassRootChecks
|
|||||||
public static final fun getBypassRootChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getBypassRootChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/com/sbs/ondemand/tv/RemoveAdsPatchKt {
|
||||||
|
public static final fun getRemoveAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/cricbuzz/ads/DisableAdsPatchKt {
|
public final class app/revanced/patches/cricbuzz/ads/DisableAdsPatchKt {
|
||||||
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -180,6 +196,10 @@ public final class app/revanced/patches/crunchyroll/ads/HideAdsPatchKt {
|
|||||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/disneyplus/ads/SkipAdsPatchKt {
|
||||||
|
public static final fun getSkipAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/duolingo/ad/DisableAdsPatchKt {
|
public final class app/revanced/patches/duolingo/ad/DisableAdsPatchKt {
|
||||||
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -256,6 +276,10 @@ public final class app/revanced/patches/iconpackstudio/misc/pro/UnlockProPatchKt
|
|||||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/idaustria/detection/deviceintegrity/RemoveDeviceIntegrityChecksPatchKt {
|
||||||
|
public static final fun getRemoveDeviceIntegrityChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/idaustria/detection/root/RootDetectionPatchKt {
|
public final class app/revanced/patches/idaustria/detection/root/RootDetectionPatchKt {
|
||||||
public static final fun getRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -276,6 +300,10 @@ public final class app/revanced/patches/instagram/feed/LimitFeedToFollowedProfil
|
|||||||
public static final fun getLimitFeedToFollowedProfiles ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getLimitFeedToFollowedProfiles ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/instagram/ghost/story/AnonymousStoryViewingPatchKt {
|
||||||
|
public static final fun getAnonymousStoryViewingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
|
public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
|
||||||
public static final fun getHideExploreFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHideExploreFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -316,10 +344,22 @@ public final class app/revanced/patches/instagram/misc/signature/SignatureCheckP
|
|||||||
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/instagram/story/flipping/DisableStoryAutoFlippingPatchKt {
|
||||||
|
public static final fun getDisableStoryAutoFlippingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/irplus/ad/RemoveAdsPatchKt {
|
public final class app/revanced/patches/irplus/ad/RemoveAdsPatchKt {
|
||||||
public static final fun getRemoveAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getRemoveAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/letterboxd/ads/HideAdsPatchKt {
|
||||||
|
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/letterboxd/unlock/unlockAppIcons/UnlockAppIconsPatchKt {
|
||||||
|
public static final fun getUnlockAppIconsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/lightroom/misc/login/DisableMandatoryLoginPatchKt {
|
public final class app/revanced/patches/lightroom/misc/login/DisableMandatoryLoginPatchKt {
|
||||||
public static final fun getDisableMandatoryLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getDisableMandatoryLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -328,6 +368,10 @@ public final class app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatc
|
|||||||
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/lightroom/misc/version/DisableVersionCheckPatchKt {
|
||||||
|
public static final fun getDisableVersionCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/memegenerator/detection/license/LicenseValidationPatchKt {
|
public final class app/revanced/patches/memegenerator/detection/license/LicenseValidationPatchKt {
|
||||||
public static final fun getLicenseValidationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getLicenseValidationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -549,6 +593,10 @@ public final class app/revanced/patches/pandora/misc/EnableUnlimitedSkipsPatchKt
|
|||||||
public static final fun getEnableUnlimitedSkipsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getEnableUnlimitedSkipsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/peacocktv/ads/HideAdsPatchKt {
|
||||||
|
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatchKt {
|
public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatchKt {
|
||||||
public static final fun getGetDeviceIdPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getGetDeviceIdPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -605,6 +653,14 @@ public final class app/revanced/patches/protonmail/signature/RemoveSentFromSigna
|
|||||||
public static final fun getRemoveSentFromSignaturePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
public static final fun getRemoveSentFromSignaturePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/protonvpn/delay/RemoveDelayPatchKt {
|
||||||
|
public static final fun getRemoveDelayPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunnelingKt {
|
||||||
|
public static final fun getUnlockSplitTunnelingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/rar/misc/annoyances/purchasereminder/HidePurchaseReminderPatchKt {
|
public final class app/revanced/patches/rar/misc/annoyances/purchasereminder/HidePurchaseReminderPatchKt {
|
||||||
public static final fun getHidePurchaseReminderPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHidePurchaseReminderPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -888,6 +944,10 @@ public final class app/revanced/patches/shared/misc/pairip/license/DisableLicens
|
|||||||
public static final fun getDisableLicenseCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getDisableLicenseCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/shared/misc/privacy/DisableSentryTelemetryKt {
|
||||||
|
public static final fun getDisableSentryTelemetryPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt {
|
public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt {
|
||||||
public static final fun overrideThemeColors (Ljava/lang/String;Ljava/lang/String;)V
|
public static final fun overrideThemeColors (Ljava/lang/String;Ljava/lang/String;)V
|
||||||
public static final fun settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
public static final fun settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
@@ -1140,6 +1200,30 @@ public final class app/revanced/patches/stocard/layout/HideStoryBubblesPatchKt {
|
|||||||
public static final fun getHideStoryBubblesPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
public static final fun getHideStoryBubblesPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/strava/media/download/AddMediaDownloadPatchKt {
|
||||||
|
public static final fun getAddMediaDownloadPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/strava/media/upload/OverwriteMediaUploadParametersPatchKt {
|
||||||
|
public static final fun getOverwriteMediaUploadParametersPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/strava/misc/extension/SharedExtensionPatchKt {
|
||||||
|
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/strava/password/EnablePasswordLoginPatchKt {
|
||||||
|
public static final fun getEnablePasswordLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/strava/privacy/BlockSnowplowTrackingPatchKt {
|
||||||
|
public static final fun getBlockSnowplowTrackingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/strava/quickedit/DisableQuickEditPatchKt {
|
||||||
|
public static final fun getDisableQuickEditPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/strava/subscription/UnlockSubscriptionPatchKt {
|
public final class app/revanced/patches/strava/subscription/UnlockSubscriptionPatchKt {
|
||||||
public static final fun getUnlockSubscriptionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getUnlockSubscriptionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -1620,6 +1704,10 @@ public final class app/revanced/patches/youtube/misc/announcements/Announcements
|
|||||||
public static final fun getAnnouncementsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getAnnouncementsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/youtube/misc/audiofocus/PauseOnAudioInterruptPatchKt {
|
||||||
|
public static final fun getPauseOnAudioInterruptPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatchKt {
|
public final class app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatchKt {
|
||||||
public static final fun getAutoRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getAutoRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -1915,6 +2003,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
|||||||
public static final fun indexOfFirstResourceIdOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
|
public static final fun indexOfFirstResourceIdOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
|
||||||
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
|
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
|
||||||
public static final fun literal (Lapp/revanced/patcher/FingerprintBuilder;Lkotlin/jvm/functions/Function0;)V
|
public static final fun literal (Lapp/revanced/patcher/FingerprintBuilder;Lkotlin/jvm/functions/Function0;)V
|
||||||
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)V
|
||||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V
|
||||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;C)V
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;C)V
|
||||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V
|
||||||
@@ -1924,7 +2013,6 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
|||||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
|
||||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V
|
||||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V
|
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V
|
||||||
public static synthetic fun returnEarly$default (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ZILjava/lang/Object;)V
|
|
||||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V
|
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V
|
||||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;C)V
|
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;C)V
|
||||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V
|
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V
|
||||||
|
|||||||
@@ -50,12 +50,9 @@ kotlin {
|
|||||||
publishing {
|
publishing {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = "GitHubPackages"
|
name = "githubPackages"
|
||||||
url = uri("https://maven.pkg.github.com/revanced/revanced-patches")
|
url = uri("https://maven.pkg.github.com/revanced/revanced-patches")
|
||||||
credentials {
|
credentials(PasswordCredentials::class)
|
||||||
username = System.getenv("GITHUB_ACTOR")
|
|
||||||
password = System.getenv("GITHUB_TOKEN")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,105 +1,9 @@
|
|||||||
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
|
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.patch.stringOption
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|
||||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
|
||||||
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.reference.MethodReference
|
|
||||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
|
||||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
@Deprecated("Patch was renamed", ReplaceWith("spoofSimProviderPatch"))
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val spoofSimCountryPatch = bytecodePatch(
|
val spoofSimCountryPatch = bytecodePatch {
|
||||||
name = "Spoof SIM country",
|
dependsOn(spoofSimProviderPatch)
|
||||||
description = "Spoofs country information returned by the SIM card provider.",
|
|
||||||
use = false,
|
|
||||||
) {
|
|
||||||
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }
|
|
||||||
|
|
||||||
fun isoCountryPatchOption(
|
|
||||||
key: String,
|
|
||||||
title: String,
|
|
||||||
) = stringOption(
|
|
||||||
key,
|
|
||||||
null,
|
|
||||||
countries,
|
|
||||||
title,
|
|
||||||
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
|
|
||||||
false,
|
|
||||||
validator = { it: String? -> it == null || it.uppercase() in countries.values },
|
|
||||||
)
|
|
||||||
|
|
||||||
val networkCountryIso by isoCountryPatchOption(
|
|
||||||
"networkCountryIso",
|
|
||||||
"Network ISO country code",
|
|
||||||
)
|
|
||||||
|
|
||||||
val simCountryIso by isoCountryPatchOption(
|
|
||||||
"simCountryIso",
|
|
||||||
"SIM ISO country code",
|
|
||||||
)
|
|
||||||
|
|
||||||
dependsOn(
|
|
||||||
transformInstructionsPatch(
|
|
||||||
filterMap = { _, _, instruction, instructionIndex ->
|
|
||||||
if (instruction !is ReferenceInstruction) return@transformInstructionsPatch null
|
|
||||||
|
|
||||||
val reference = instruction.reference as? MethodReference ?: return@transformInstructionsPatch null
|
|
||||||
|
|
||||||
val match = MethodCall.entries.firstOrNull { search ->
|
|
||||||
MethodUtil.methodSignaturesMatch(reference, search.reference)
|
|
||||||
} ?: return@transformInstructionsPatch null
|
|
||||||
|
|
||||||
val iso = when (match) {
|
|
||||||
MethodCall.NetworkCountryIso -> networkCountryIso
|
|
||||||
MethodCall.SimCountryIso -> simCountryIso
|
|
||||||
}?.lowercase()
|
|
||||||
|
|
||||||
iso?.let { instructionIndex to it }
|
|
||||||
},
|
|
||||||
transform = { mutableMethod, entry: Pair<Int, String> ->
|
|
||||||
transformMethodCall(entry, mutableMethod)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun transformMethodCall(
|
|
||||||
entry: Pair<Int, String>,
|
|
||||||
mutableMethod: MutableMethod,
|
|
||||||
) {
|
|
||||||
val (instructionIndex, methodCallValue) = entry
|
|
||||||
|
|
||||||
val register = mutableMethod.getInstruction<OneRegisterInstruction>(instructionIndex + 1).registerA
|
|
||||||
|
|
||||||
mutableMethod.replaceInstruction(
|
|
||||||
instructionIndex + 1,
|
|
||||||
"const-string v$register, \"$methodCallValue\"",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum class MethodCall(
|
|
||||||
val reference: MethodReference,
|
|
||||||
) {
|
|
||||||
NetworkCountryIso(
|
|
||||||
ImmutableMethodReference(
|
|
||||||
"Landroid/telephony/TelephonyManager;",
|
|
||||||
"getNetworkCountryIso",
|
|
||||||
emptyList(),
|
|
||||||
"Ljava/lang/String;",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SimCountryIso(
|
|
||||||
ImmutableMethodReference(
|
|
||||||
"Landroid/telephony/TelephonyManager;",
|
|
||||||
"getSimCountryIso",
|
|
||||||
emptyList(),
|
|
||||||
"Ljava/lang/String;",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.patch.intOption
|
||||||
|
import app.revanced.patcher.patch.stringOption
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||||
|
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.reference.MethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val spoofSimProviderPatch = bytecodePatch(
|
||||||
|
name = "Spoof SIM provider",
|
||||||
|
description = "Spoofs information about the SIM card provider.",
|
||||||
|
use = false,
|
||||||
|
) {
|
||||||
|
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }
|
||||||
|
|
||||||
|
fun isoCountryPatchOption(
|
||||||
|
key: String,
|
||||||
|
title: String,
|
||||||
|
) = stringOption(
|
||||||
|
key,
|
||||||
|
null,
|
||||||
|
countries,
|
||||||
|
title,
|
||||||
|
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
|
||||||
|
false,
|
||||||
|
validator = { it: String? -> it == null || it.uppercase() in countries.values },
|
||||||
|
)
|
||||||
|
|
||||||
|
fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999)
|
||||||
|
|
||||||
|
val networkCountryIso by isoCountryPatchOption(
|
||||||
|
"networkCountryIso",
|
||||||
|
"Network ISO country code",
|
||||||
|
)
|
||||||
|
|
||||||
|
val networkOperator by intOption(
|
||||||
|
key = "networkOperator",
|
||||||
|
title = "MCC+MNC network operator code",
|
||||||
|
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the network operator.",
|
||||||
|
validator = { isMccMncValid(it) }
|
||||||
|
)
|
||||||
|
|
||||||
|
val networkOperatorName by stringOption(
|
||||||
|
key = "networkOperatorName",
|
||||||
|
title = "Network operator name",
|
||||||
|
description = "The full name of the network operator.",
|
||||||
|
)
|
||||||
|
|
||||||
|
val simCountryIso by isoCountryPatchOption(
|
||||||
|
"simCountryIso",
|
||||||
|
"SIM ISO country code",
|
||||||
|
)
|
||||||
|
|
||||||
|
val simOperator by intOption(
|
||||||
|
key = "simOperator",
|
||||||
|
title = "MCC+MNC SIM operator code",
|
||||||
|
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the SIM operator.",
|
||||||
|
validator = { isMccMncValid(it) }
|
||||||
|
)
|
||||||
|
|
||||||
|
val simOperatorName by stringOption(
|
||||||
|
key = "simOperatorName",
|
||||||
|
title = "SIM operator name",
|
||||||
|
description = "The full name of the SIM operator.",
|
||||||
|
)
|
||||||
|
|
||||||
|
dependsOn(
|
||||||
|
transformInstructionsPatch(
|
||||||
|
filterMap = { _, _, instruction, instructionIndex ->
|
||||||
|
if (instruction !is ReferenceInstruction) return@transformInstructionsPatch null
|
||||||
|
|
||||||
|
val reference = instruction.reference as? MethodReference ?: return@transformInstructionsPatch null
|
||||||
|
|
||||||
|
val match = MethodCall.entries.firstOrNull { search ->
|
||||||
|
MethodUtil.methodSignaturesMatch(reference, search.reference)
|
||||||
|
} ?: return@transformInstructionsPatch null
|
||||||
|
|
||||||
|
val replacement = when (match) {
|
||||||
|
MethodCall.NetworkCountryIso -> networkCountryIso?.lowercase()
|
||||||
|
MethodCall.NetworkOperator -> networkOperator?.toString()
|
||||||
|
MethodCall.NetworkOperatorName -> networkOperatorName
|
||||||
|
MethodCall.SimCountryIso -> simCountryIso?.lowercase()
|
||||||
|
MethodCall.SimOperator -> simOperator?.toString()
|
||||||
|
MethodCall.SimOperatorName -> simOperatorName
|
||||||
|
}
|
||||||
|
replacement?.let { instructionIndex to it }
|
||||||
|
},
|
||||||
|
transform = ::transformMethodCall,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformMethodCall(
|
||||||
|
mutableMethod: MutableMethod,
|
||||||
|
entry: Pair<Int, String>,
|
||||||
|
) {
|
||||||
|
val (instructionIndex, methodCallValue) = entry
|
||||||
|
|
||||||
|
// Get the register which would have contained the return value
|
||||||
|
val register = mutableMethod.getInstruction<OneRegisterInstruction>(instructionIndex + 1).registerA
|
||||||
|
|
||||||
|
// Replace the move-result instruction with our fake value
|
||||||
|
mutableMethod.replaceInstruction(
|
||||||
|
instructionIndex + 1,
|
||||||
|
"const-string v$register, \"$methodCallValue\"",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class MethodCall(
|
||||||
|
val reference: MethodReference,
|
||||||
|
) {
|
||||||
|
NetworkCountryIso(
|
||||||
|
ImmutableMethodReference(
|
||||||
|
"Landroid/telephony/TelephonyManager;",
|
||||||
|
"getNetworkCountryIso",
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
NetworkOperator(
|
||||||
|
ImmutableMethodReference(
|
||||||
|
"Landroid/telephony/TelephonyManager;",
|
||||||
|
"getNetworkOperator",
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
NetworkOperatorName(
|
||||||
|
ImmutableMethodReference(
|
||||||
|
"Landroid/telephony/TelephonyManager;",
|
||||||
|
"getNetworkOperatorName",
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SimCountryIso(
|
||||||
|
ImmutableMethodReference(
|
||||||
|
"Landroid/telephony/TelephonyManager;",
|
||||||
|
"getSimCountryIso",
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SimOperator(
|
||||||
|
ImmutableMethodReference(
|
||||||
|
"Landroid/telephony/TelephonyManager;",
|
||||||
|
"getSimOperator",
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SimOperatorName(
|
||||||
|
ImmutableMethodReference(
|
||||||
|
"Landroid/telephony/TelephonyManager;",
|
||||||
|
"getSimOperatorName",
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package app.revanced.patches.all.misc.playintegrity
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
|
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/playintegrity/DisablePlayIntegrityPatch;"
|
||||||
|
|
||||||
|
private val CONTEXT_BIND_SERVICE_METHOD_REFERENCE = ImmutableMethodReference(
|
||||||
|
"Landroid/content/Context;",
|
||||||
|
"bindService",
|
||||||
|
listOf("Landroid/content/Intent;", "Landroid/content/ServiceConnection;", "I"),
|
||||||
|
"Z"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val disablePlayIntegrityPatch = bytecodePatch(
|
||||||
|
name = "Disable Play Integrity",
|
||||||
|
description = "Prevents apps from using Play Integrity by pretending it is not available.",
|
||||||
|
use = false,
|
||||||
|
) {
|
||||||
|
extendWith("extensions/all/misc/disable-play-integrity.rve")
|
||||||
|
|
||||||
|
dependsOn(
|
||||||
|
transformInstructionsPatch(
|
||||||
|
filterMap = filterMap@{ classDef, method, instruction, instructionIndex ->
|
||||||
|
val reference = instruction
|
||||||
|
.getReference<MethodReference>()
|
||||||
|
?.takeIf {
|
||||||
|
MethodUtil.methodSignaturesMatch(CONTEXT_BIND_SERVICE_METHOD_REFERENCE, it)
|
||||||
|
}
|
||||||
|
?: return@filterMap null
|
||||||
|
|
||||||
|
Triple(instruction as Instruction35c, instructionIndex, reference.parameterTypes)
|
||||||
|
},
|
||||||
|
transform = { method, entry ->
|
||||||
|
val (instruction, index, parameterTypes) = entry
|
||||||
|
val parameterString = parameterTypes.joinToString(separator = "")
|
||||||
|
val registerString = "v${instruction.registerC}, v${instruction.registerD}, v${instruction.registerE}, v${instruction.registerF}"
|
||||||
|
|
||||||
|
method.replaceInstruction(
|
||||||
|
index,
|
||||||
|
"invoke-static { $registerString }, $EXTENSION_CLASS_DESCRIPTOR->bindService(Landroid/content/Context;$parameterString)Z"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package app.revanced.patches.com.sbs.ondemand.tv
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val shouldShowAdvertisingTVFingerprint = fingerprint {
|
||||||
|
returns("Z")
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "getShouldShowAdvertisingTV" &&
|
||||||
|
classDef.type == "Lcom/sbs/ondemand/common/InMemoryStorage;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val shouldShowPauseAdFingerprint = fingerprint {
|
||||||
|
returns("Z")
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "shouldShowPauseAd" &&
|
||||||
|
classDef.type == "Lcom/sbs/ondemand/player/viewmodels/PauseAdController;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val requestAdStreamFingerprint = fingerprint {
|
||||||
|
returns("V")
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "requestAdStream\$player_googleStoreTvRelease" &&
|
||||||
|
classDef.type == "Lcom/sbs/ondemand/player/viewmodels/AdsController;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package app.revanced.patches.com.sbs.ondemand.tv
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val removeAdsPatch = bytecodePatch(
|
||||||
|
name = "Remove ads",
|
||||||
|
description = "Removes pre-roll, pause and on-demand advertisements from SBS On Demand TV.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.sbs.ondemand.tv")
|
||||||
|
|
||||||
|
dependsOn(disableLicenseCheckPatch)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
shouldShowAdvertisingTVFingerprint.method.returnEarly(true)
|
||||||
|
shouldShowPauseAdFingerprint.method.returnEarly(false)
|
||||||
|
|
||||||
|
// Remove on-demand pre-roll advertisements using exception handling.
|
||||||
|
// Exception handling is used instead of returnEarly() because:
|
||||||
|
// 1. returnEarly() causes black screen when the app waits for ad content that never comes.
|
||||||
|
// 2. SBS app has built-in exception handling in handleProviderFailure().
|
||||||
|
// 3. Exception triggers fallbackToAkamaiProvider() which loads actual content.
|
||||||
|
// 4. This preserves the intended app flow: first try ads, then fail gracefully, then load content.
|
||||||
|
requestAdStreamFingerprint.method.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
new-instance v0, Ljava/lang/RuntimeException;
|
||||||
|
const-string v1, "Ad stream disabled"
|
||||||
|
invoke-direct {v0, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/String;)V
|
||||||
|
throw v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package app.revanced.patches.disneyplus.ads
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val insertionGetPointsFingerprint = fingerprint {
|
||||||
|
returns("Ljava/util/List")
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getPoints" &&
|
||||||
|
method.definingClass == "Lcom/dss/sdk/internal/media/Insertion;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val insertionGetRangesFingerprint = fingerprint {
|
||||||
|
returns("Ljava/util/List")
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getRanges" &&
|
||||||
|
method.definingClass == "Lcom/dss/sdk/internal/media/Insertion;"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package app.revanced.patches.disneyplus.ads
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val skipAdsPatch = bytecodePatch(
|
||||||
|
name = "Skip ads",
|
||||||
|
description = "Automatically skips ads.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.disney.disneyplus")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
arrayOf(insertionGetPointsFingerprint, insertionGetRangesFingerprint).forEach {
|
||||||
|
it.method.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
new-instance v0, Ljava/util/ArrayList;
|
||||||
|
invoke-direct {v0}, Ljava/util/ArrayList;-><init>()V
|
||||||
|
return-object v0
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.deviceintegrity
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal val isDeviceBootloaderOpenFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC)
|
||||||
|
returns("Ljava/lang/Object;")
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "isDeviceBootloaderOpen" &&
|
||||||
|
classDef.endsWith("/DeviceIntegrityCheckProviderImpl;")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val isDeviceRootedFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC)
|
||||||
|
returns("Z")
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "isDeviceRooted" &&
|
||||||
|
classDef.endsWith("/DeviceIntegrityCheckProviderImpl;")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.deviceintegrity
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val removeDeviceIntegrityChecksPatch = bytecodePatch(
|
||||||
|
name = "Remove device integrity checks",
|
||||||
|
description = "Removes the check for root permissions and unlocked bootloader.",
|
||||||
|
) {
|
||||||
|
compatibleWith("at.gv.oe.app")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
isDeviceRootedFingerprint.method.returnEarly(false)
|
||||||
|
|
||||||
|
isDeviceBootloaderOpenFingerprint.method.apply {
|
||||||
|
addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x0
|
||||||
|
invoke-static { v0 }, Lkotlin/coroutines/jvm/internal/Boxing;->boxBoolean(Z)Ljava/lang/Boolean;
|
||||||
|
move-result-object v0
|
||||||
|
return-object v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package app.revanced.patches.idaustria.detection.root
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
|
|
||||||
internal val attestationSupportedCheckFingerprint = fingerprint {
|
|
||||||
accessFlags(AccessFlags.PUBLIC)
|
|
||||||
returns("V")
|
|
||||||
custom { method, classDef ->
|
|
||||||
method.name == "attestationSupportCheck" &&
|
|
||||||
classDef.endsWith("/DeviceIntegrityCheck;")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val bootloaderCheckFingerprint = fingerprint {
|
|
||||||
accessFlags(AccessFlags.PUBLIC)
|
|
||||||
returns("Z")
|
|
||||||
custom { method, classDef ->
|
|
||||||
method.name == "bootloaderCheck" &&
|
|
||||||
classDef.endsWith("/DeviceIntegrityCheck;")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val rootCheckFingerprint = fingerprint {
|
|
||||||
accessFlags(AccessFlags.PUBLIC)
|
|
||||||
returns("V")
|
|
||||||
custom { method, classDef ->
|
|
||||||
method.name == "rootCheck" &&
|
|
||||||
classDef.endsWith("/DeviceIntegrityCheck;")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,10 @@
|
|||||||
package app.revanced.patches.idaustria.detection.root
|
package app.revanced.patches.idaustria.detection.root
|
||||||
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.shared.PATCH_DESCRIPTION_REMOVE_ROOT_DETECTION
|
import app.revanced.patches.idaustria.detection.deviceintegrity.removeDeviceIntegrityChecksPatch
|
||||||
import app.revanced.patches.shared.PATCH_NAME_REMOVE_ROOT_DETECTION
|
|
||||||
import app.revanced.util.returnEarly
|
|
||||||
|
|
||||||
|
@Deprecated("Patch was superseded", ReplaceWith("removeDeviceIntegrityChecksPatch"))
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val rootDetectionPatch = bytecodePatch(
|
val rootDetectionPatch = bytecodePatch {
|
||||||
name = PATCH_NAME_REMOVE_ROOT_DETECTION,
|
dependsOn(removeDeviceIntegrityChecksPatch)
|
||||||
description = PATCH_DESCRIPTION_REMOVE_ROOT_DETECTION
|
|
||||||
) {
|
|
||||||
compatibleWith("at.gv.oe.app")
|
|
||||||
|
|
||||||
execute {
|
|
||||||
setOf(
|
|
||||||
attestationSupportedCheckFingerprint,
|
|
||||||
bootloaderCheckFingerprint,
|
|
||||||
rootCheckFingerprint,
|
|
||||||
).forEach { it.method.returnEarly(true) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package app.revanced.patches.instagram.ghost.story
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.Utils.trimIndentMultiline
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val anonymousStoryViewingPatch = bytecodePatch(
|
||||||
|
name = "Anonymous story viewing",
|
||||||
|
description = """
|
||||||
|
View stories without sending any information to the server.
|
||||||
|
Your view will not appear in the story viewers list.
|
||||||
|
Note: Since no data is sent, a story you have already viewed may appear as new on another device.
|
||||||
|
""".trimIndentMultiline(),
|
||||||
|
use = false
|
||||||
|
) {
|
||||||
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
// Prevent the hashmap of the seen media to be filled
|
||||||
|
setMediaSeenHashmapFingerprint.method.returnEarly()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.instagram.ghost.story
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val setMediaSeenHashmapFingerprint = fingerprint {
|
||||||
|
parameters()
|
||||||
|
returns("V")
|
||||||
|
strings("media/seen/")
|
||||||
|
}
|
||||||
@@ -28,6 +28,13 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
|||||||
|
|
||||||
dependsOn(sharedExtensionPatch)
|
dependsOn(sharedExtensionPatch)
|
||||||
|
|
||||||
|
val hideHome by booleanOption(
|
||||||
|
key = "hideHome",
|
||||||
|
default = false,
|
||||||
|
title = "Hide Home",
|
||||||
|
description = "Permanently hides the Home button. App starts at next available tab." // On the "homecoming" / current instagram layout.
|
||||||
|
)
|
||||||
|
|
||||||
val hideReels by booleanOption(
|
val hideReels by booleanOption(
|
||||||
key = "hideReels",
|
key = "hideReels",
|
||||||
default = true,
|
default = true,
|
||||||
@@ -35,6 +42,27 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
|||||||
description = "Permanently hides the Reels button."
|
description = "Permanently hides the Reels button."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val hideDirect by booleanOption(
|
||||||
|
key = "hideDirect",
|
||||||
|
default = false,
|
||||||
|
title = "Hide Direct",
|
||||||
|
description = "Permanently hides the Direct button."
|
||||||
|
)
|
||||||
|
|
||||||
|
val hideSearch by booleanOption(
|
||||||
|
key = "hideSearch",
|
||||||
|
default = false,
|
||||||
|
title = "Hide Search",
|
||||||
|
description = "Permanently hides the Search button."
|
||||||
|
)
|
||||||
|
|
||||||
|
val hideProfile by booleanOption(
|
||||||
|
key = "hideProfile",
|
||||||
|
default = false,
|
||||||
|
title = "Hide Profile",
|
||||||
|
description = "Permanently hides the Profile button."
|
||||||
|
)
|
||||||
|
|
||||||
val hideCreate by booleanOption(
|
val hideCreate by booleanOption(
|
||||||
key = "hideCreate",
|
key = "hideCreate",
|
||||||
default = true,
|
default = true,
|
||||||
@@ -43,7 +71,7 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
if (!hideReels!! && !hideCreate!!) {
|
if (!hideHome!! &&!hideReels!! && !hideDirect!! && !hideSearch!! && !hideProfile!! && !hideCreate!!) {
|
||||||
return@execute Logger.getLogger(this::class.java.name).warning(
|
return@execute Logger.getLogger(this::class.java.name).warning(
|
||||||
"No hide navigation buttons options are enabled. No changes made."
|
"No hide navigation buttons options are enabled. No changes made."
|
||||||
)
|
)
|
||||||
@@ -76,6 +104,13 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
|||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hideHome!!) {
|
||||||
|
addInstructionsAtControlFlowLabel(
|
||||||
|
returnIndex,
|
||||||
|
instructionsRemoveButtonByName("fragment_feed")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (hideReels!!) {
|
if (hideReels!!) {
|
||||||
addInstructionsAtControlFlowLabel(
|
addInstructionsAtControlFlowLabel(
|
||||||
returnIndex,
|
returnIndex,
|
||||||
@@ -83,12 +118,33 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hideDirect!!) {
|
||||||
|
addInstructionsAtControlFlowLabel(
|
||||||
|
returnIndex,
|
||||||
|
instructionsRemoveButtonByName("fragment_direct_tab")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (hideSearch!!) {
|
||||||
|
addInstructionsAtControlFlowLabel(
|
||||||
|
returnIndex,
|
||||||
|
instructionsRemoveButtonByName("fragment_search")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (hideCreate!!) {
|
if (hideCreate!!) {
|
||||||
addInstructionsAtControlFlowLabel(
|
addInstructionsAtControlFlowLabel(
|
||||||
returnIndex,
|
returnIndex,
|
||||||
instructionsRemoveButtonByName("fragment_share")
|
instructionsRemoveButtonByName("fragment_share")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hideProfile!!) {
|
||||||
|
addInstructionsAtControlFlowLabel(
|
||||||
|
returnIndex,
|
||||||
|
instructionsRemoveButtonByName("fragment_profile")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ internal val storyUrlResponseJsonParserFingerprint = fingerprint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal val profileUrlResponseJsonParserFingerprint = fingerprint {
|
internal val profileUrlResponseJsonParserFingerprint = fingerprint {
|
||||||
strings("profile_to_share_url", "ProfileUrlResponse")
|
strings("profile_to_share_url")
|
||||||
custom { method, _ -> method.name == "parseFromJson" }
|
custom { method, _ -> method.name == "parseFromJson" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import app.revanced.util.returnEarly
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val signatureCheckPatch = bytecodePatch(
|
val signatureCheckPatch = bytecodePatch(
|
||||||
name = "Disable signature check",
|
name = "Disable signature check",
|
||||||
description = "Disables the signature check that causes the app to crash on startup."
|
description = "Disables the signature check that can cause the app to crash on startup. " +
|
||||||
|
"Including this patch may cause issues with sharing or opening external Instagram links.",
|
||||||
|
use = false
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.instagram.android")
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.instagram.reels.clipsSwipeRefreshLayoutOnInterceptTouchEventFingerprint
|
||||||
|
import app.revanced.patches.instagram.reels.clipsViewPagerImplGetViewAtIndexFingerprint
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val disableReelsScrollingPatch = bytecodePatch(
|
||||||
|
name = "Disable Reels scrolling",
|
||||||
|
description = "Disables the endless scrolling behavior in Instagram Reels, preventing swiping to the next Reel. " +
|
||||||
|
"Note: On a clean install, the 'Tip' animation may appear but will stop on its own after a few seconds.",
|
||||||
|
use = false
|
||||||
|
) {
|
||||||
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
val viewPagerField = clipsViewPagerImplGetViewAtIndexFingerprint.classDef.fields.first {
|
||||||
|
it.type == "Landroidx/viewpager2/widget/ViewPager2;"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable user input on the ViewPager2 to prevent scrolling.
|
||||||
|
clipsViewPagerImplGetViewAtIndexFingerprint.method.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
iget-object v0, p0, $viewPagerField
|
||||||
|
const/4 v1, 0x0
|
||||||
|
invoke-virtual { v0, v1 }, Landroidx/viewpager2/widget/ViewPager2;->setUserInputEnabled(Z)V
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
// Return false in onInterceptTouchEvent to disable pull-to-refresh.
|
||||||
|
clipsSwipeRefreshLayoutOnInterceptTouchEventFingerprint.method.returnEarly(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.instagram.reels
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val clipsViewPagerImplGetViewAtIndexFingerprint = fingerprint {
|
||||||
|
strings("ClipsViewPagerImpl_getViewAtIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val clipsSwipeRefreshLayoutOnInterceptTouchEventFingerprint = fingerprint {
|
||||||
|
parameters("Landroid/view/MotionEvent;")
|
||||||
|
custom { _, classDef -> classDef.type == "Linstagram/features/clips/viewer/ui/ClipsSwipeRefreshLayout;" }
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package app.revanced.patches.instagram.story.flipping
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val disableStoryAutoFlippingPatch = bytecodePatch(
|
||||||
|
name = "Disable story auto flipping",
|
||||||
|
description = "Disable stories automatically flipping/skipping after some seconds.",
|
||||||
|
use = false
|
||||||
|
) {
|
||||||
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
onStoryTimeoutActionFingerprint.method.returnEarly()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.instagram.story.flipping
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val onStoryTimeoutActionFingerprint = fingerprint {
|
||||||
|
parameters("Ljava/lang/Object;")
|
||||||
|
returns("V")
|
||||||
|
strings("userSession")
|
||||||
|
custom { _, classDef ->
|
||||||
|
classDef.type == "Linstagram/features/stories/fragment/ReelViewerFragment;"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package app.revanced.patches.letterboxd.ads
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal const val admobHelperClassName = "Lcom/letterboxd/letterboxd/helpers/AdmobHelper;"
|
||||||
|
|
||||||
|
internal val admobHelperSetShowAdsFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "setShowAds" && classDef.type == admobHelperClassName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val admobHelperShouldShowAdsFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "shouldShowAds" && classDef.type == admobHelperClassName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val filmFragmentShowAdsFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "showAds" && classDef.type.endsWith("/FilmFragment;")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val memberExtensionShowAdsFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "showAds" && classDef.type.endsWith("/AMemberExtensionKt;")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
package app.revanced.patches.letterboxd.ads
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val hideAdsPatch = bytecodePatch(
|
||||||
|
name = "Hide ads",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.letterboxd.letterboxd")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
admobHelperSetShowAdsFingerprint.method.addInstruction(0, "const p1, 0x0")
|
||||||
|
listOf(admobHelperShouldShowAdsFingerprint, filmFragmentShowAdsFingerprint, memberExtensionShowAdsFingerprint).forEach {
|
||||||
|
it.method.returnEarly(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.letterboxd.unlock.unlockAppIcons
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val getCanChangeAppIconFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "getCanChangeAppIcon" && classDef.type.endsWith("SettingsAppIconFragment;")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
package app.revanced.patches.letterboxd.unlock.unlockAppIcons
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val unlockAppIconsPatch = bytecodePatch(
|
||||||
|
name = "Unlock app icons",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.letterboxd.letterboxd")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
getCanChangeAppIconFingerprint.method.returnEarly(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package app.revanced.patches.lightroom.misc.version
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val disableVersionCheckPatch = bytecodePatch(
|
||||||
|
name = "Disable version check",
|
||||||
|
description = "Disables the server-side version check that prevents the app from starting.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.adobe.lrmobile"("9.3.0"))
|
||||||
|
|
||||||
|
execute {
|
||||||
|
refreshRemoteConfigurationFingerprint.method.apply {
|
||||||
|
val igetIndex = refreshRemoteConfigurationFingerprint.patternMatch!!.endIndex
|
||||||
|
|
||||||
|
// This value represents the server command to clear all version restrictions.
|
||||||
|
val statusForceReset = "-0x2";
|
||||||
|
replaceInstruction(igetIndex, "const/4 v1, $statusForceReset")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package app.revanced.patches.lightroom.misc.version
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal val refreshRemoteConfigurationFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||||
|
strings(
|
||||||
|
"com.adobe.lrmobile.denylisted_version_set_key",
|
||||||
|
"com.adobe.lrmobile.app_min_version_key"
|
||||||
|
)
|
||||||
|
opcodes(
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IGET, // Overwrite this instruction to disable the check.
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
package app.revanced.patches.music.layout.branding
|
package app.revanced.patches.music.layout.branding
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
|
||||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_MAIN_ACTIVITY_NAME
|
import app.revanced.patches.music.misc.gms.Constants.MUSIC_MAIN_ACTIVITY_NAME
|
||||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
||||||
import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint
|
import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint
|
||||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||||
|
import app.revanced.patches.shared.layout.branding.EXTENSION_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch
|
import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch
|
||||||
import app.revanced.patches.shared.misc.mapping.get
|
import app.revanced.patches.shared.misc.mapping.get
|
||||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionReversed
|
|
||||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||||
|
|
||||||
private val disableSplashAnimationPatch = bytecodePatch {
|
private val disableSplashAnimationPatch = bytecodePatch {
|
||||||
|
|
||||||
@@ -33,23 +33,22 @@ private val disableSplashAnimationPatch = bytecodePatch {
|
|||||||
// but the animation is not always the same size as the launch screen and it's still
|
// but the animation is not always the same size as the launch screen and it's still
|
||||||
// barely shown. Instead turn off the animation entirely (app will also launch a little faster).
|
// barely shown. Instead turn off the animation entirely (app will also launch a little faster).
|
||||||
cairoSplashAnimationConfigFingerprint.method.apply {
|
cairoSplashAnimationConfigFingerprint.method.apply {
|
||||||
val mainActivityLaunchAnimation = resourceMappings["layout", "main_activity_launch_animation"]
|
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
|
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
|
||||||
mainActivityLaunchAnimation
|
resourceMappings["layout", "main_activity_launch_animation"]
|
||||||
)
|
)
|
||||||
val insertIndex = indexOfFirstInstructionReversed(literalIndex) {
|
val checkCastIndex = indexOfFirstInstructionOrThrow(literalIndex) {
|
||||||
this.opcode == Opcode.INVOKE_VIRTUAL &&
|
opcode == Opcode.CHECK_CAST &&
|
||||||
getReference<MethodReference>()?.name == "setContentView"
|
getReference<TypeReference>()?.type == "Lcom/airbnb/lottie/LottieAnimationView;"
|
||||||
} + 1
|
}
|
||||||
val jumpIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
val register = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
|
||||||
getReference<MethodReference>()?.parameterTypes?.firstOrNull() == "Ljava/lang/Runnable;"
|
|
||||||
} + 1
|
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
// If using a custom icon then set the lottie animation view to null to bypasses the startup animation.
|
||||||
insertIndex,
|
addInstructions(
|
||||||
"goto :skip_animation",
|
checkCastIndex,
|
||||||
ExternalLabel("skip_animation", getInstruction(jumpIndex))
|
"""
|
||||||
|
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getLottieViewOrNull(Landroid/view/View;)Landroid/view/View;
|
||||||
|
move-result-object v$register
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package app.revanced.patches.peacocktv.ads
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal val mediaTailerAdServiceFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC)
|
||||||
|
returns("Ljava/lang/Object")
|
||||||
|
strings("Could not build MT Advertising service")
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package app.revanced.patches.peacocktv.ads
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val hideAdsPatch = bytecodePatch(
|
||||||
|
name = "Hide ads",
|
||||||
|
description = "Hides all video ads.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.peacocktv.peacockandroid")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
mediaTailerAdServiceFingerprint.method.returnEarly(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package app.revanced.patches.protonvpn.delay
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
|
||||||
|
internal val longDelayFingerprint = fingerprint {
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getChangeServerLongDelayInSeconds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val shortDelayFingerprint = fingerprint {
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getChangeServerShortDelayInSeconds"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package app.revanced.patches.protonvpn.delay
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val removeDelayPatch = bytecodePatch(
|
||||||
|
name = "Remove delay",
|
||||||
|
description = "Removes the delay when changing servers.",
|
||||||
|
) {
|
||||||
|
compatibleWith("ch.protonvpn.android")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
longDelayFingerprint.method.returnEarly(0)
|
||||||
|
shortDelayFingerprint.method.returnEarly(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package app.revanced.patches.protonvpn.splittunneling
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal val enableSplitTunnelingUiFingerprint = fingerprint {
|
||||||
|
strings("currentModeAppNames")
|
||||||
|
opcodes(
|
||||||
|
Opcode.MOVE_OBJECT,
|
||||||
|
Opcode.MOVE_FROM16,
|
||||||
|
Opcode.INVOKE_DIRECT_RANGE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val initializeSplitTunnelingSettingsUIFingerprint = fingerprint {
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "applyRestrictions"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.patches.protonvpn.splittunneling
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val unlockSplitTunnelingPatch =
|
||||||
|
bytecodePatch(
|
||||||
|
name = "Unlock split tunneling",
|
||||||
|
) {
|
||||||
|
compatibleWith("ch.protonvpn.android")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
val registerIndex = enableSplitTunnelingUiFingerprint.patternMatch!!.endIndex - 1
|
||||||
|
|
||||||
|
enableSplitTunnelingUiFingerprint.method.apply {
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(registerIndex).registerA
|
||||||
|
replaceInstruction(registerIndex, "const/4 v$register, 0x0")
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeSplitTunnelingSettingsUIFingerprint.method.apply {
|
||||||
|
val initSettingsIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
getReference<MethodReference>()?.name == "getSplitTunneling"
|
||||||
|
}
|
||||||
|
removeInstruction(initSettingsIndex - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,8 @@ package app.revanced.patches.reddit.ad.comments
|
|||||||
import app.revanced.patcher.fingerprint
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
internal val hideCommentAdsFingerprint = fingerprint {
|
internal val hideCommentAdsFingerprint = fingerprint {
|
||||||
strings(
|
custom { method, classDef ->
|
||||||
"link",
|
method.name == "invokeSuspend" &&
|
||||||
// CommentPageRepository is not returning a link object
|
classDef.contains("LoadAdsCombinedCall")
|
||||||
"is not returning a link object"
|
|
||||||
)
|
|
||||||
custom { _, classDef ->
|
|
||||||
classDef.sourceFile == "PostDetailPresenter.kt"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package app.revanced.patches.reddit.ad.comments
|
package app.revanced.patches.reddit.ad.comments
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
||||||
val hideCommentAdsPatch = bytecodePatch(
|
val hideCommentAdsPatch = bytecodePatch(
|
||||||
@@ -8,13 +8,6 @@ val hideCommentAdsPatch = bytecodePatch(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
hideCommentAdsFingerprint.method.addInstructions(
|
hideCommentAdsFingerprint.method.replaceInstructions(0, "return-object p1")
|
||||||
0,
|
|
||||||
"""
|
|
||||||
new-instance v0, Ljava/lang/Object;
|
|
||||||
invoke-direct {v0}, Ljava/lang/Object;-><init>()V
|
|
||||||
return-object v0
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,5 @@ internal val adPostFingerprint = fingerprint {
|
|||||||
|
|
||||||
internal val newAdPostFingerprint = fingerprint {
|
internal val newAdPostFingerprint = fingerprint {
|
||||||
opcodes(Opcode.INVOKE_VIRTUAL)
|
opcodes(Opcode.INVOKE_VIRTUAL)
|
||||||
strings("chain", "feedElement")
|
strings("feedElement", "com.reddit.cookie")
|
||||||
custom { _, classDef -> classDef.sourceFile == "AdElementConverter.kt" }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package app.revanced.patches.reddit.ad.general
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.reddit.ad.banner.hideBannerPatch
|
|
||||||
import app.revanced.patches.reddit.ad.comments.hideCommentAdsPatch
|
import app.revanced.patches.reddit.ad.comments.hideCommentAdsPatch
|
||||||
import app.revanced.patches.reddit.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.reddit.misc.extension.sharedExtensionPatch
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@@ -16,14 +15,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|||||||
val hideAdsPatch = bytecodePatch(
|
val hideAdsPatch = bytecodePatch(
|
||||||
name = "Hide ads",
|
name = "Hide ads",
|
||||||
) {
|
) {
|
||||||
dependsOn(hideBannerPatch, hideCommentAdsPatch, sharedExtensionPatch)
|
dependsOn(hideCommentAdsPatch, sharedExtensionPatch)
|
||||||
|
|
||||||
// Note that for now, this patch and anything using it will only work on
|
compatibleWith("com.reddit.frontpage")
|
||||||
// Reddit 2024.17.0 or older. Newer versions will crash during patching.
|
|
||||||
// See https://github.com/ReVanced/revanced-patches/issues/3099
|
|
||||||
// and https://github.com/iBotPeaches/Apktool/issues/3534.
|
|
||||||
// This constraint is necessary due to dependency on hideBannerPatch.
|
|
||||||
compatibleWith("com.reddit.frontpage"("2024.17.0"))
|
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
// region Filter promoted ads (does not work in popular or latest feed)
|
// region Filter promoted ads (does not work in popular or latest feed)
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package app.revanced.patches.shared.misc.privacy
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
|
import app.revanced.util.asSequence
|
||||||
|
import app.revanced.util.getNode
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val disableSentryTelemetryPatch = resourcePatch(
|
||||||
|
name = "Disable Sentry telemetry",
|
||||||
|
description = "Disables Sentry telemetry. See https://sentry.io/for/android/ for more information.",
|
||||||
|
use = false,
|
||||||
|
) {
|
||||||
|
execute {
|
||||||
|
fun Element.replaceOrCreate(tagName: String, attributeName: String, attributeValue: String) {
|
||||||
|
val childElements = getElementsByTagName(tagName).asSequence().filterIsInstance<Element>()
|
||||||
|
val targetChild = childElements.find { childElement ->
|
||||||
|
childElement.getAttribute("android:name") == attributeName
|
||||||
|
}
|
||||||
|
if (targetChild != null) {
|
||||||
|
targetChild.setAttribute("android:value", attributeValue)
|
||||||
|
} else {
|
||||||
|
appendChild(ownerDocument.createElement(tagName).apply {
|
||||||
|
setAttribute("android:name", attributeName)
|
||||||
|
setAttribute("android:value", attributeValue)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document("AndroidManifest.xml").use { document ->
|
||||||
|
val application = document.getNode("application") as Element
|
||||||
|
application.replaceOrCreate("meta-data", "io.sentry.enabled", "false")
|
||||||
|
application.replaceOrCreate("meta-data", "io.sentry.dsn", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,5 +3,5 @@ package app.revanced.patches.spotify.misc.extension
|
|||||||
import app.revanced.patcher.fingerprint
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
internal val loadOrbitLibraryFingerprint = fingerprint {
|
internal val loadOrbitLibraryFingerprint = fingerprint {
|
||||||
strings("OrbitLibraryLoader", "cst")
|
strings("orbit_library_load", "orbit-jni-spotify")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package app.revanced.patches.strava.media.download
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
|
import app.revanced.patches.shared.misc.mapping.get
|
||||||
|
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||||
|
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||||
|
import app.revanced.patches.strava.misc.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.writeRegister
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22c
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||||
|
|
||||||
|
private const val ACTION_CLASS_DESCRIPTOR = "Lcom/strava/bottomsheet/Action;"
|
||||||
|
private const val MEDIA_CLASS_DESCRIPTOR = "Lcom/strava/photos/data/Media;"
|
||||||
|
private const val MEDIA_DOWNLOAD_CLASS_DESCRIPTOR = "Lapp/revanced/extension/strava/AddMediaDownloadPatch;"
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val addMediaDownloadPatch = bytecodePatch(
|
||||||
|
name = "Add media download",
|
||||||
|
description = "Extends the full-screen media viewer menu with items to copy or open their URLs or download them directly."
|
||||||
|
) {
|
||||||
|
compatibleWith("com.strava")
|
||||||
|
|
||||||
|
dependsOn(
|
||||||
|
resourceMappingPatch,
|
||||||
|
sharedExtensionPatch
|
||||||
|
)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
val fragmentClass = classBy { it.endsWith("/FullscreenMediaFragment;") }!!.mutableClass
|
||||||
|
|
||||||
|
// region Extend menu of `FullscreenMediaFragment` with actions.
|
||||||
|
|
||||||
|
createAndShowFragmentFingerprint.match(fragmentClass).method.apply {
|
||||||
|
val setTrueIndex = instructions.indexOfFirst { instruction ->
|
||||||
|
instruction.opcode == Opcode.IPUT_BOOLEAN
|
||||||
|
}
|
||||||
|
val actionRegistrarRegister = getInstruction<BuilderInstruction22c>(setTrueIndex).registerB
|
||||||
|
val actionRegister = instructions.first { instruction ->
|
||||||
|
instruction.getReference<TypeReference>()?.type == ACTION_CLASS_DESCRIPTOR
|
||||||
|
}.writeRegister!!
|
||||||
|
|
||||||
|
fun addMenuItem(actionId: String, string: String, color: String, drawable: String) = addInstructions(
|
||||||
|
setTrueIndex + 1,
|
||||||
|
"""
|
||||||
|
new-instance v$actionRegister, $ACTION_CLASS_DESCRIPTOR
|
||||||
|
sget v${actionRegister + 1}, $MEDIA_DOWNLOAD_CLASS_DESCRIPTOR->$actionId:I
|
||||||
|
const v${actionRegister + 2}, 0x0
|
||||||
|
const v${actionRegister + 3}, ${resourceMappings["string", string]}
|
||||||
|
const v${actionRegister + 4}, ${resourceMappings["color", color]}
|
||||||
|
const v${actionRegister + 5}, ${resourceMappings["drawable", drawable]}
|
||||||
|
move/from16 v${actionRegister + 6}, v${actionRegister + 4}
|
||||||
|
invoke-direct/range { v$actionRegister .. v${actionRegister + 7} }, $ACTION_CLASS_DESCRIPTOR-><init>(ILjava/lang/String;IIIILjava/io/Serializable;)V
|
||||||
|
invoke-virtual { v$actionRegistrarRegister, v$actionRegister }, Lcom/strava/bottomsheet/a;->a(Lcom/strava/bottomsheet/BottomSheetItem;)V
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
addMenuItem("ACTION_COPY_LINK", "copy_link", "core_o3", "actions_link_normal_xsmall")
|
||||||
|
addMenuItem("ACTION_OPEN_LINK", "fallback_menu_item_open_in_browser", "core_o3", "actions_link_external_normal_xsmall")
|
||||||
|
addMenuItem("ACTION_DOWNLOAD", "download", "core_o3", "actions_download_normal_xsmall")
|
||||||
|
|
||||||
|
// Move media to last parameter of `Action` constructor.
|
||||||
|
val getMediaInstruction = instructions.first { instruction ->
|
||||||
|
instruction.getReference<FieldReference>()?.type == MEDIA_CLASS_DESCRIPTOR
|
||||||
|
}
|
||||||
|
addInstruction(
|
||||||
|
getMediaInstruction.location.index + 1,
|
||||||
|
"move-object/from16 v${actionRegister + 7}, v${getMediaInstruction.writeRegister}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Handle new actions.
|
||||||
|
|
||||||
|
val actionClass = classes.first { clazz ->
|
||||||
|
clazz.type == ACTION_CLASS_DESCRIPTOR
|
||||||
|
}
|
||||||
|
val actionSerializableField = actionClass.instanceFields.first { field ->
|
||||||
|
field.type == "Ljava/io/Serializable;"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "copy link" & "open link" & "download" actions.
|
||||||
|
handleMediaActionFingerprint.match(fragmentClass).method.apply {
|
||||||
|
// Call handler if action ID < 0 (= custom).
|
||||||
|
val moveInstruction = instructions.first { instruction ->
|
||||||
|
instruction.opcode == Opcode.MOVE_RESULT
|
||||||
|
}
|
||||||
|
val indexAfterMoveInstruction = moveInstruction.location.index + 1
|
||||||
|
val actionIdRegister = moveInstruction.writeRegister
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
indexAfterMoveInstruction,
|
||||||
|
"""
|
||||||
|
if-gez v$actionIdRegister, :move
|
||||||
|
check-cast p2, $ACTION_CLASS_DESCRIPTOR
|
||||||
|
iget-object v0, p2, $actionSerializableField
|
||||||
|
check-cast v0, $MEDIA_CLASS_DESCRIPTOR
|
||||||
|
invoke-static { v$actionIdRegister, v0 }, $MEDIA_DOWNLOAD_CLASS_DESCRIPTOR->handleAction(I$MEDIA_CLASS_DESCRIPTOR)Z
|
||||||
|
move-result v0
|
||||||
|
return v0
|
||||||
|
""",
|
||||||
|
ExternalLabel("move", instructions[indexAfterMoveInstruction])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.patches.strava.media.download
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal val createAndShowFragmentFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
|
returns("V")
|
||||||
|
parameters("L")
|
||||||
|
strings("mediaType")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val handleMediaActionFingerprint = fingerprint {
|
||||||
|
parameters("Landroid/view/View;", "Lcom/strava/bottomsheet/BottomSheetItem;")
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package app.revanced.patches.strava.media.upload
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val getCompressionQualityFingerprint = fingerprint {
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getCompressionQuality"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val getMaxDurationFingerprint = fingerprint {
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getMaxDuration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val getMaxSizeFingerprint = fingerprint {
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getMaxSize"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package app.revanced.patches.strava.media.upload
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.patch.intOption
|
||||||
|
import app.revanced.patcher.patch.longOption
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val overwriteMediaUploadParametersPatch = bytecodePatch(
|
||||||
|
name = "Overwrite media upload parameters",
|
||||||
|
description = "Overwrites the compression, resize and trim media (images and videos) parameters returned by Strava's server before upload.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.strava")
|
||||||
|
|
||||||
|
val compressionQuality by intOption(
|
||||||
|
key = "compressionQuality",
|
||||||
|
title = "Compression quality (percent)",
|
||||||
|
description = "This is used as the JPEG quality setting (≤ 100).",
|
||||||
|
) { it == null || it in 1..100 }
|
||||||
|
|
||||||
|
val maxDuration by longOption(
|
||||||
|
key = "maxDuration",
|
||||||
|
title = "Max duration (seconds)",
|
||||||
|
description = "The maximum length (≤ ${60 * 60}) of a video before it gets trimmed.",
|
||||||
|
) { it == null || it in 1..60 * 60 }
|
||||||
|
|
||||||
|
val maxSize by intOption(
|
||||||
|
key = "maxSize",
|
||||||
|
title = "Max size (pixels)",
|
||||||
|
description = "The image gets resized so that the smaller dimension (width/height) does not exceed this value (≤ 10000).",
|
||||||
|
) { it == null || it in 1..10000 }
|
||||||
|
|
||||||
|
execute {
|
||||||
|
val mediaUploadParametersClass = classes.single { it.endsWith("/MediaUploadParameters;") }
|
||||||
|
|
||||||
|
compressionQuality?.let { compressionQuality ->
|
||||||
|
getCompressionQualityFingerprint.match(mediaUploadParametersClass).method.returnEarly(compressionQuality / 100f)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxDuration?.let { maxDuration ->
|
||||||
|
getMaxDurationFingerprint.match(mediaUploadParametersClass).method.returnEarly(maxDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxSize?.let {
|
||||||
|
getMaxSizeFingerprint.match(mediaUploadParametersClass).method.returnEarly(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.strava.misc.extension
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||||
|
|
||||||
|
internal val applicationOnCreateHook = extensionHook {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "onCreate" && classDef.endsWith("/StravaApplication;")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package app.revanced.patches.strava.misc.extension
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||||
|
|
||||||
|
val sharedExtensionPatch = sharedExtensionPatch("strava", applicationOnCreateHook)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package app.revanced.patches.strava.password
|
||||||
|
|
||||||
|
import app.revanced.patcher.Fingerprint
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val enablePasswordLoginPatch = bytecodePatch(
|
||||||
|
name = "Enable password login",
|
||||||
|
description = "Re-enables password login after having used an OTP code.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.strava")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
fun Fingerprint.returnTrue() = method.returnEarly(true)
|
||||||
|
|
||||||
|
logInGetUsePasswordFingerprint.returnTrue()
|
||||||
|
emailChangeGetUsePasswordFingerprint.returnTrue()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.patches.strava.password
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val logInGetUsePasswordFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "getUsePassword" && classDef.endsWith("/RequestOtpLogInNetworkResponse;")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val emailChangeGetUsePasswordFingerprint = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "getUsePassword" && classDef.endsWith("/RequestEmailChangeWithOtpOrPasswordResponse;")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package app.revanced.patches.strava.privacy
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val blockSnowplowTrackingPatch = bytecodePatch(
|
||||||
|
name = "Block Snowplow tracking",
|
||||||
|
description = "Blocks Snowplow analytics. See https://snowplow.io for more information.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.strava")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
// Keep events list empty, otherwise sent to https://c.strava.com/com.snowplowanalytics.snowplow/tp2.
|
||||||
|
insertEventFingerprint.method.returnEarly()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.strava.privacy
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
// https://github.com/snowplow/snowplow-android-tracker/blob/2.2.0/snowplow-tracker/src/main/java/com/snowplowanalytics/snowplow/internal/emitter/storage/SQLiteEventStore.java#L130
|
||||||
|
// Not the exact same code (e.g. returns void instead of long), even though the version number matches.
|
||||||
|
internal val insertEventFingerprint = fingerprint {
|
||||||
|
strings("Added event to database: %s")
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package app.revanced.patches.strava.quickedit
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val disableQuickEditPatch = bytecodePatch(
|
||||||
|
name = "Disable Quick Edit",
|
||||||
|
description = "Prevents the Quick Edit prompt from popping up.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.strava")
|
||||||
|
|
||||||
|
execute {
|
||||||
|
getHasAccessToQuickEditFingerprint.method.returnEarly()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package app.revanced.patches.strava.quickedit
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val getHasAccessToQuickEditFingerprint = fingerprint {
|
||||||
|
returns("Z")
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "getHasAccessToQuickEdit"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package app.revanced.patches.strava.subscription
|
package app.revanced.patches.strava.subscription
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint
|
import app.revanced.patcher.fingerprint
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal val getSubscribedFingerprint = fingerprint {
|
internal val getSubscribedFingerprint = fingerprint {
|
||||||
opcodes(Opcode.IGET_BOOLEAN)
|
|
||||||
custom { method, classDef ->
|
custom { method, classDef ->
|
||||||
classDef.endsWith("/SubscriptionDetailResponse;") && method.name == "getSubscribed"
|
method.name == "getSubscribed" && classDef.endsWith("/SubscriptionDetailResponse;")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package app.revanced.patches.strava.subscription
|
package app.revanced.patches.strava.subscription
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val unlockSubscriptionPatch = bytecodePatch(
|
val unlockSubscriptionPatch = bytecodePatch(
|
||||||
@@ -11,9 +11,6 @@ val unlockSubscriptionPatch = bytecodePatch(
|
|||||||
compatibleWith("com.strava")
|
compatibleWith("com.strava")
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
getSubscribedFingerprint.method.replaceInstruction(
|
getSubscribedFingerprint.method.returnEarly(true)
|
||||||
getSubscribedFingerprint.patternMatch!!.startIndex,
|
|
||||||
"const/4 v0, 0x1",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,13 +145,14 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
|||||||
SwitchPreference("revanced_hide_ask_section"),
|
SwitchPreference("revanced_hide_ask_section"),
|
||||||
SwitchPreference("revanced_hide_attributes_section"),
|
SwitchPreference("revanced_hide_attributes_section"),
|
||||||
SwitchPreference("revanced_hide_chapters_section"),
|
SwitchPreference("revanced_hide_chapters_section"),
|
||||||
SwitchPreference("revanced_hide_featured_section"),
|
SwitchPreference("revanced_hide_featured_links_section"),
|
||||||
|
SwitchPreference("revanced_hide_featured_videos_section"),
|
||||||
SwitchPreference("revanced_hide_info_cards_section"),
|
SwitchPreference("revanced_hide_info_cards_section"),
|
||||||
SwitchPreference("revanced_hide_how_this_was_made_section"),
|
SwitchPreference("revanced_hide_how_this_was_made_section"),
|
||||||
SwitchPreference("revanced_hide_hype_points"),
|
SwitchPreference("revanced_hide_hype_points"),
|
||||||
SwitchPreference("revanced_hide_key_concepts_section"),
|
SwitchPreference("revanced_hide_key_concepts_section"),
|
||||||
SwitchPreference("revanced_hide_podcast_section"),
|
SwitchPreference("revanced_hide_podcast_section"),
|
||||||
SwitchPreference("revanced_hide_description_subscribe_button"),
|
SwitchPreference("revanced_hide_subscribe_button"),
|
||||||
SwitchPreference("revanced_hide_transcript_section"),
|
SwitchPreference("revanced_hide_transcript_section"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -173,6 +174,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
|||||||
),
|
),
|
||||||
SwitchPreference("revanced_hide_channel_bar"),
|
SwitchPreference("revanced_hide_channel_bar"),
|
||||||
SwitchPreference("revanced_hide_channel_watermark"),
|
SwitchPreference("revanced_hide_channel_watermark"),
|
||||||
|
SwitchPreference("revanced_hide_crowdfunding_box"),
|
||||||
SwitchPreference("revanced_hide_emergency_box"),
|
SwitchPreference("revanced_hide_emergency_box"),
|
||||||
SwitchPreference("revanced_hide_info_panels"),
|
SwitchPreference("revanced_hide_info_panels"),
|
||||||
SwitchPreference("revanced_hide_join_membership_button"),
|
SwitchPreference("revanced_hide_join_membership_button"),
|
||||||
@@ -214,19 +216,20 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
|||||||
PreferenceScreenPreference(
|
PreferenceScreenPreference(
|
||||||
key = "revanced_channel_screen",
|
key = "revanced_channel_screen",
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
|
SwitchPreference("revanced_hide_community_button"),
|
||||||
SwitchPreference("revanced_hide_for_you_shelf"),
|
SwitchPreference("revanced_hide_for_you_shelf"),
|
||||||
|
SwitchPreference("revanced_hide_join_button"),
|
||||||
SwitchPreference("revanced_hide_links_preview"),
|
SwitchPreference("revanced_hide_links_preview"),
|
||||||
SwitchPreference("revanced_hide_members_shelf"),
|
SwitchPreference("revanced_hide_members_shelf"),
|
||||||
SwitchPreference("revanced_hide_visit_community_button"),
|
SwitchPreference("revanced_hide_store_button"),
|
||||||
SwitchPreference("revanced_hide_visit_store_button"),
|
SwitchPreference("revanced_hide_subscribe_button_in_channel_page"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SwitchPreference("revanced_hide_album_cards"),
|
SwitchPreference("revanced_hide_album_cards"),
|
||||||
SwitchPreference("revanced_hide_artist_cards"),
|
SwitchPreference("revanced_hide_artist_cards"),
|
||||||
|
SwitchPreference("revanced_hide_chips_shelf"),
|
||||||
SwitchPreference("revanced_hide_community_posts"),
|
SwitchPreference("revanced_hide_community_posts"),
|
||||||
SwitchPreference("revanced_hide_compact_banner"),
|
SwitchPreference("revanced_hide_compact_banner"),
|
||||||
SwitchPreference("revanced_hide_crowdfunding_box"),
|
|
||||||
SwitchPreference("revanced_hide_chips_shelf"),
|
|
||||||
SwitchPreference("revanced_hide_expandable_card"),
|
SwitchPreference("revanced_hide_expandable_card"),
|
||||||
SwitchPreference("revanced_hide_floating_microphone_button"),
|
SwitchPreference("revanced_hide_floating_microphone_button"),
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
@@ -242,9 +245,10 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
|||||||
SwitchPreference("revanced_hide_show_more_button"),
|
SwitchPreference("revanced_hide_show_more_button"),
|
||||||
SwitchPreference("revanced_hide_surveys"),
|
SwitchPreference("revanced_hide_surveys"),
|
||||||
SwitchPreference("revanced_hide_ticket_shelf"),
|
SwitchPreference("revanced_hide_ticket_shelf"),
|
||||||
|
SwitchPreference("revanced_hide_upload_time"),
|
||||||
SwitchPreference("revanced_hide_video_recommendation_labels"),
|
SwitchPreference("revanced_hide_video_recommendation_labels"),
|
||||||
SwitchPreference("revanced_hide_view_count"),
|
SwitchPreference("revanced_hide_view_count"),
|
||||||
SwitchPreference("revanced_hide_upload_time"),
|
SwitchPreference("revanced_hide_visual_spacer"),
|
||||||
SwitchPreference("revanced_hide_doodles"),
|
SwitchPreference("revanced_hide_doodles"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user