mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-15 21:52:27 +01:00
Compare commits
174 Commits
v5.45.0-de
...
feat/moder
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1e03e1b69 | ||
|
|
8c603802f7 | ||
|
|
95c72ad300 | ||
|
|
2f3ecab0e1 | ||
|
|
a5d39c3bbe | ||
|
|
07c4dd3a55 | ||
|
|
67c6c345ea | ||
|
|
ed514d9755 | ||
|
|
0e994f5bfe | ||
|
|
8cc69fe38b | ||
|
|
41b31dd56c | ||
|
|
9671c7499d | ||
|
|
d62d17fdeb | ||
|
|
c6eaba9af6 | ||
|
|
fff29544b9 | ||
|
|
9495cf49ef | ||
|
|
15675b5164 | ||
|
|
654d091e65 | ||
|
|
98371be33c | ||
|
|
2f0de15e67 | ||
|
|
df160370e2 | ||
|
|
bb745b555b | ||
|
|
8df9a46721 | ||
|
|
94ae84ad0f | ||
|
|
4febb2e2e9 | ||
|
|
b9bc7e3e58 | ||
|
|
9f3bb26cb9 | ||
|
|
d64dfc2884 | ||
|
|
db5b79ddbb | ||
|
|
a39ef1e0a4 | ||
|
|
a1a80ebc57 | ||
|
|
5ccfb3cb9f | ||
|
|
1d8e977a43 | ||
|
|
da4cf94091 | ||
|
|
d23fa5e3b7 | ||
|
|
2687b3006b | ||
|
|
29a86fb8ec | ||
|
|
34d29abdfa | ||
|
|
ab808aeb77 | ||
|
|
a6b07cceb1 | ||
|
|
81a429af74 | ||
|
|
3406033732 | ||
|
|
d291881215 | ||
|
|
7a18ebc7ab | ||
|
|
afbcf3d90f | ||
|
|
b7c995930a | ||
|
|
675a2c4209 | ||
|
|
475197af45 | ||
|
|
0855290097 | ||
|
|
d390b54dab | ||
|
|
4d1eaa6b14 | ||
|
|
49c925e95f | ||
|
|
7499f3d19b | ||
|
|
3d55083dbc | ||
|
|
c6364f5b49 | ||
|
|
f177eae385 | ||
|
|
829bfa76d1 | ||
|
|
2e9d6959c9 | ||
|
|
81f83690d6 | ||
|
|
f1bd6848c9 | ||
|
|
59d85b28a7 | ||
|
|
f238ae9895 | ||
|
|
e030e9c07a | ||
|
|
5029e979be | ||
|
|
55e1a6784b | ||
|
|
0cad5e73f0 | ||
|
|
ce503d5b58 | ||
|
|
57263538c7 | ||
|
|
88352d8774 | ||
|
|
03ce5711de | ||
|
|
70f4955e89 | ||
|
|
582144026d | ||
|
|
d80892cc0e | ||
|
|
6c4b931b8a | ||
|
|
76dcfaefd8 | ||
|
|
e4f52343c0 | ||
|
|
1196b1a147 | ||
|
|
858edbf3e7 | ||
|
|
a52c0153b1 | ||
|
|
fc70f852f9 | ||
|
|
cd9ef81354 | ||
|
|
1b2cd64a86 | ||
|
|
0c03599f07 | ||
|
|
5f23bfe833 | ||
|
|
2cf8f0e636 | ||
|
|
955f7c9341 | ||
|
|
93160722c0 | ||
|
|
78689fde83 | ||
|
|
260afefaab | ||
|
|
b7be52dec6 | ||
|
|
594317e573 | ||
|
|
c95170ecbd | ||
|
|
ecda492866 | ||
|
|
4a73671262 | ||
|
|
6d72b4a3fb | ||
|
|
f00c0e0d89 | ||
|
|
772620c8ce | ||
|
|
9984e586b4 | ||
|
|
9a2f23291d | ||
|
|
7ef70f7823 | ||
|
|
a1fd6b13d5 | ||
|
|
f30ece9287 | ||
|
|
f2356a8be2 | ||
|
|
47f1a5f9c9 | ||
|
|
fc988fa078 | ||
|
|
c37527f182 | ||
|
|
64334b4f79 | ||
|
|
0389073600 | ||
|
|
5449357f7f | ||
|
|
39da47e6ee | ||
|
|
1356a7e5b2 | ||
|
|
b5cda51048 | ||
|
|
a1ad5fea20 | ||
|
|
c98c73b0bc | ||
|
|
ed87bc7b7a | ||
|
|
1901e965e8 | ||
|
|
aae71e6a19 | ||
|
|
a1c9170cc9 | ||
|
|
88b077a9b7 | ||
|
|
563f586eed | ||
|
|
c6becb4044 | ||
|
|
2d207fccbc | ||
|
|
967ef47c2d | ||
|
|
240e953160 | ||
|
|
0f03a071e9 | ||
|
|
e52b33981c | ||
|
|
4d9de1a81a | ||
|
|
636bded69c | ||
|
|
2d49d76e82 | ||
|
|
934947a257 | ||
|
|
8e05bb3a80 | ||
|
|
f88ad4e4a7 | ||
|
|
f252fb24b6 | ||
|
|
2f9081eb6c | ||
|
|
a82f49aa08 | ||
|
|
823530f707 | ||
|
|
7eb78d4f2b | ||
|
|
4dec67385e | ||
|
|
edaad1a7b7 | ||
|
|
d3df24977a | ||
|
|
7b02a31e3f | ||
|
|
41c8fbc10d | ||
|
|
59e1321e62 | ||
|
|
252f57f430 | ||
|
|
d6593e2acd | ||
|
|
c4e6e62e71 | ||
|
|
ca736094e4 | ||
|
|
7e010d38cc | ||
|
|
a4d24ad192 | ||
|
|
45d42a1405 | ||
|
|
ecf5752100 | ||
|
|
4096b34003 | ||
|
|
23b200ce68 | ||
|
|
56876f336b | ||
|
|
c7a71f44df | ||
|
|
a25d769f69 | ||
|
|
c2a099d1f4 | ||
|
|
d906046a52 | ||
|
|
765957f2c9 | ||
|
|
8e64416f14 | ||
|
|
6a5b204f8e | ||
|
|
b99789b1cd | ||
|
|
bb671766f6 | ||
|
|
97ce498368 | ||
|
|
dcaa6feda0 | ||
|
|
e8d56c85cc | ||
|
|
04401899f4 | ||
|
|
e52a9509e2 | ||
|
|
c6d84744ca | ||
|
|
d3fae2a3e7 | ||
|
|
6ddf0583a4 | ||
|
|
77864f41f4 | ||
|
|
a352a05db6 | ||
|
|
724e6d61b2 |
2
.github/workflows/build_pull_request.yml
vendored
2
.github/workflows/build_pull_request.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
run: ./gradlew :patches:buildAndroid --no-daemon
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: revanced-patches
|
||||
path: patches/build/libs
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
run: ./gradlew :patches:buildAndroid clean
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
cache: 'npm'
|
||||
|
||||
157
CHANGELOG.md
157
CHANGELOG.md
@@ -1,3 +1,160 @@
|
||||
# [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)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.46.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.8...v5.46.0-dev.9) (2025-11-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.46.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.7...v5.46.0-dev.8) (2025-11-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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.7](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.6...v5.46.0-dev.7) (2025-11-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Settings:** Add additional languages to ReVanced language preference ([d390b54](https://github.com/ReVanced/revanced-patches/commit/d390b54dab92d75b4e0d3e38344eae489dd69d98))
|
||||
|
||||
# [5.46.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.5...v5.46.0-dev.6) (2025-11-08)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
# [5.46.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.4...v5.46.0-dev.5) (2025-11-07)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
# [5.46.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.3...v5.46.0-dev.4) (2025-11-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.46.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.2...v5.46.0-dev.3) (2025-11-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.46.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.1...v5.46.0-dev.2) (2025-11-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.46.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.45.0...v5.46.0-dev.1) (2025-11-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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 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))
|
||||
|
||||
# [5.45.0](https://github.com/ReVanced/revanced-patches/compare/v5.44.0...v5.45.0) (2025-11-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram:** Update failing fingerprints on newer versions ([#6181](https://github.com/ReVanced/revanced-patches/issues/6181)) ([c73a03c](https://github.com/ReVanced/revanced-patches/commit/c73a03c9e18a12262939c974cdf16221221d1487))
|
||||
* **TikTok - Downloads:** Fix download path setting ([#6191](https://github.com/ReVanced/revanced-patches/issues/6191)) ([3e4990a](https://github.com/ReVanced/revanced-patches/commit/3e4990afff4c86b93970b153db713ad0f813124d))
|
||||
* **YouTube - Change header:** Do not mirror header graphic with RTL languages ([a0c5604](https://github.com/ReVanced/revanced-patches/commit/a0c56049510ce040e1ccd49257864672c343344d))
|
||||
* **YouTube - Force original audio:** Fall back to visionOS and not Android Studio if Android VR is not available ([6d01863](https://github.com/ReVanced/revanced-patches/commit/6d01863ec70617d9abc864ce6686ed9764dd151d))
|
||||
* **YouTube - Spoof video streams:** Remove spoof stream audio selector that no longer works ([292fae4](https://github.com/ReVanced/revanced-patches/commit/292fae440c6d5694c5e84407becec2d91f1fd156))
|
||||
* **YouTube Music - Hide category bar:** Correctly hide the category bar in newer app targets ([#6175](https://github.com/ReVanced/revanced-patches/issues/6175)) ([13cf172](https://github.com/ReVanced/revanced-patches/commit/13cf1724bf2f946c7129cab0db96721c90f9fe89))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spoof video streams:** Add experimental "Android No SDK" client type ([5f23bfe](https://github.com/ReVanced/revanced-patches/commit/5f23bfe833c6e01617a7dbc5325b4a3fb931e53e))
|
||||
* **TikTok:** Add `Sanitize sharing links` patch ([#6176](https://github.com/ReVanced/revanced-patches/issues/6176)) ([ef44eaa](https://github.com/ReVanced/revanced-patches/commit/ef44eaa119b9d6c5faec051e22d20f883d0da4f1))
|
||||
* **YouTube - Change Header:** Use SVG for header logo ([#6178](https://github.com/ReVanced/revanced-patches/issues/6178)) ([e9f45ce](https://github.com/ReVanced/revanced-patches/commit/e9f45ce92695d5857473ff71c14b190bded28a73))
|
||||
|
||||
# [5.45.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.5...v5.45.0-dev.6) (2025-11-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spoof video streams:** Add experimental "Android No SDK" client type ([5f23bfe](https://github.com/ReVanced/revanced-patches/commit/5f23bfe833c6e01617a7dbc5325b4a3fb931e53e))
|
||||
|
||||
# [5.45.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.4...v5.45.0-dev.5) (2025-11-01)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ChangeMiniplayerColorPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean changeMiniplayerColor() {
|
||||
return Settings.CHANGE_MINIPLAYER_COLOR.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.hideViewBy0dpUnderCondition;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideButtonsPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static int hideCastButton(int original) {
|
||||
return Settings.HIDE_CAST_BUTTON.get() ? View.GONE : original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static void hideCastButton(View view) {
|
||||
hideViewBy0dpUnderCondition(Settings.HIDE_CAST_BUTTON, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean hideHistoryButton(boolean original) {
|
||||
return original && !Settings.HIDE_HISTORY_BUTTON.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static void hideNotificationButton(View view) {
|
||||
if (view.getParent() instanceof ViewGroup viewGroup) {
|
||||
hideViewBy0dpUnderCondition(Settings.HIDE_NOTIFICATION_BUTTON, viewGroup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static void hideSearchButton(View view) {
|
||||
hideViewBy0dpUnderCondition(Settings.HIDE_SEARCH_BUTTON, view);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.hideViewBy0dpUnderCondition;
|
||||
|
||||
import android.view.View;
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideCastButtonPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static int hideCastButton(int original) {
|
||||
return Settings.HIDE_CAST_BUTTON.get() ? View.GONE : original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static void hideCastButton(View view) {
|
||||
hideViewBy0dpUnderCondition(Settings.HIDE_CAST_BUTTON, view);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package app.revanced.extension.music.patches;
|
||||
import static app.revanced.extension.shared.Utils.hideViewBy0dpUnderCondition;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.extension.music.patches.spoof;
|
||||
|
||||
import static app.revanced.extension.music.settings.Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_NO_SDK;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
|
||||
@@ -18,8 +19,9 @@ public class SpoofVideoStreamsPatch {
|
||||
public static void setClientOrderToUse() {
|
||||
List<ClientType> availableClients = List.of(
|
||||
ANDROID_VR_1_43_32,
|
||||
ANDROID_VR_1_61_48,
|
||||
VISIONOS
|
||||
ANDROID_NO_SDK,
|
||||
VISIONOS,
|
||||
ANDROID_VR_1_61_48
|
||||
);
|
||||
|
||||
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.widget.Toolbar;
|
||||
import app.revanced.extension.music.settings.preference.MusicPreferenceFragment;
|
||||
import app.revanced.extension.music.settings.search.MusicSearchViewController;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseActivityHook;
|
||||
|
||||
@@ -46,15 +47,7 @@ public class MusicActivityHook extends BaseActivityHook {
|
||||
// Override the default YouTube Music theme to increase start padding of list items.
|
||||
// Custom style located in resources/music/values/style.xml
|
||||
activity.setTheme(Utils.getResourceIdentifierOrThrow(
|
||||
"Theme.ReVanced.YouTubeMusic.Settings", "style"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the YouTube Music settings layout.
|
||||
*/
|
||||
@Override
|
||||
protected int getContentViewResourceId() {
|
||||
return LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR;
|
||||
ResourceType.STYLE, "Theme.ReVanced.YouTubeMusic.Settings"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,8 +16,11 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_GET_PREMIUM_LABEL = new BooleanSetting("revanced_music_hide_get_premium_label", TRUE, true);
|
||||
|
||||
// General
|
||||
public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_music_hide_cast_button", TRUE, false);
|
||||
public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_music_hide_cast_button", TRUE, true);
|
||||
public static final BooleanSetting HIDE_CATEGORY_BAR = new BooleanSetting("revanced_music_hide_category_bar", FALSE, true);
|
||||
public static final BooleanSetting HIDE_HISTORY_BUTTON = new BooleanSetting("revanced_music_hide_history_button", FALSE, true);
|
||||
public static final BooleanSetting HIDE_SEARCH_BUTTON = new BooleanSetting("revanced_music_hide_search_button", FALSE, true);
|
||||
public static final BooleanSetting HIDE_NOTIFICATION_BUTTON = new BooleanSetting("revanced_music_hide_notification_button", FALSE, true);
|
||||
public static final BooleanSetting HIDE_NAVIGATION_BAR_HOME_BUTTON = new BooleanSetting("revanced_music_hide_navigation_bar_home_button", FALSE, true);
|
||||
public static final BooleanSetting HIDE_NAVIGATION_BAR_SAMPLES_BUTTON = new BooleanSetting("revanced_music_hide_navigation_bar_samples_button", FALSE, true);
|
||||
public static final BooleanSetting HIDE_NAVIGATION_BAR_EXPLORE_BUTTON = new BooleanSetting("revanced_music_hide_navigation_bar_explore_button", FALSE, true);
|
||||
@@ -27,6 +30,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_NAVIGATION_BAR_LABEL = new BooleanSetting("revanced_music_hide_navigation_bar_labels", FALSE, true);
|
||||
|
||||
// Player
|
||||
public static final BooleanSetting CHANGE_MINIPLAYER_COLOR = new BooleanSetting("revanced_music_change_miniplayer_color", FALSE, true);
|
||||
public static final BooleanSetting PERMANENT_REPEAT = new BooleanSetting("revanced_music_play_permanent_repeat", FALSE, true);
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.Arrays;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
import com.amazon.video.sdk.player.Player;
|
||||
|
||||
@@ -64,9 +65,8 @@ public class PlaybackSpeedPatch {
|
||||
SpeedIconDrawable speedIcon = new SpeedIconDrawable();
|
||||
speedButton.setImageDrawable(speedIcon);
|
||||
|
||||
int buttonSize = Utils.dipToPixels(48);
|
||||
speedButton.setMinimumWidth(buttonSize);
|
||||
speedButton.setMinimumHeight(buttonSize);
|
||||
speedButton.setMinimumWidth(Dim.dp48);
|
||||
speedButton.setMinimumHeight(Dim.dp48);
|
||||
|
||||
return speedButton;
|
||||
}
|
||||
@@ -197,11 +197,11 @@ class SpeedIconDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return Utils.dipToPixels(32);
|
||||
return Dim.dp32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return Utils.dipToPixels(32);
|
||||
return Dim.dp32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package app.revanced.extension.shared;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum ResourceType {
|
||||
ANIM("anim"),
|
||||
ANIMATOR("animator"),
|
||||
ARRAY("array"),
|
||||
ATTR("attr"),
|
||||
BOOL("bool"),
|
||||
COLOR("color"),
|
||||
DIMEN("dimen"),
|
||||
DRAWABLE("drawable"),
|
||||
FONT("font"),
|
||||
FRACTION("fraction"),
|
||||
ID("id"),
|
||||
INTEGER("integer"),
|
||||
INTERPOLATOR("interpolator"),
|
||||
LAYOUT("layout"),
|
||||
MENU("menu"),
|
||||
MIPMAP("mipmap"),
|
||||
NAVIGATION("navigation"),
|
||||
PLURALS("plurals"),
|
||||
RAW("raw"),
|
||||
STRING("string"),
|
||||
STYLE("style"),
|
||||
STYLEABLE("styleable"),
|
||||
TRANSITION("transition"),
|
||||
VALUES("values"),
|
||||
XML("xml");
|
||||
|
||||
private static final Map<String, ResourceType> VALUE_MAP;
|
||||
|
||||
static {
|
||||
ResourceType[] values = values();
|
||||
VALUE_MAP = new HashMap<>(2 * values.length);
|
||||
|
||||
for (ResourceType type : values) {
|
||||
VALUE_MAP.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public final String value;
|
||||
|
||||
public static ResourceType fromValue(String value) {
|
||||
ResourceType type = VALUE_MAP.get(value);
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Unknown resource type: " + value);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
ResourceType(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,7 @@ import android.os.Looper;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -45,10 +43,14 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.text.Bidi;
|
||||
import java.text.Collator;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -61,6 +63,7 @@ import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
import app.revanced.extension.shared.settings.preference.ReVancedAboutPreference;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
@SuppressWarnings("NewApi")
|
||||
public class Utils {
|
||||
@@ -79,6 +82,17 @@ public class Utils {
|
||||
@Nullable
|
||||
private static Boolean isDarkModeEnabled;
|
||||
|
||||
private static boolean appIsUsingBoldIcons;
|
||||
|
||||
// Cached Collator instance with its locale.
|
||||
@Nullable
|
||||
private static Locale cachedCollatorLocale;
|
||||
@Nullable
|
||||
private static Collator cachedCollator;
|
||||
|
||||
private static final Pattern PUNCTUATION_PATTERN = Pattern.compile("\\p{P}+");
|
||||
private static final Pattern DIACRITICS_PATTERN = Pattern.compile("\\p{M}");
|
||||
|
||||
private Utils() {
|
||||
} // utility class
|
||||
|
||||
@@ -142,12 +156,12 @@ public class Utils {
|
||||
/**
|
||||
* Hide a view by setting its layout height and width to 1dp.
|
||||
*
|
||||
* @param condition The setting to check for hiding the view.
|
||||
* @param setting The setting to check for hiding the view.
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static void hideViewBy0dpUnderCondition(BooleanSetting condition, View view) {
|
||||
if (hideViewBy0dpUnderCondition(condition.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + condition);
|
||||
public static void hideViewBy0dpUnderCondition(BooleanSetting setting, View view) {
|
||||
if (hideViewBy0dpUnderCondition(setting.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + setting);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,22 +173,47 @@ public class Utils {
|
||||
*/
|
||||
public static boolean hideViewBy0dpUnderCondition(boolean condition, View view) {
|
||||
if (condition) {
|
||||
hideViewByLayoutParams(view);
|
||||
hideViewBy0dp(view);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a view by setting its layout params to 0x0
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static void hideViewBy0dp(View view) {
|
||||
if (view instanceof LinearLayout) {
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams);
|
||||
} else if (view instanceof FrameLayout) {
|
||||
FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams2);
|
||||
} else if (view instanceof RelativeLayout) {
|
||||
RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams3);
|
||||
} else if (view instanceof Toolbar) {
|
||||
Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams4);
|
||||
} else {
|
||||
ViewGroup.LayoutParams params = view.getLayoutParams();
|
||||
params.width = 0;
|
||||
params.height = 0;
|
||||
view.setLayoutParams(params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a view by setting its visibility to GONE.
|
||||
*
|
||||
* @param condition The setting to check for hiding the view.
|
||||
* @param setting The setting to check for hiding the view.
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static void hideViewUnderCondition(BooleanSetting condition, View view) {
|
||||
if (hideViewUnderCondition(condition.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + condition);
|
||||
public static void hideViewUnderCondition(BooleanSetting setting, View view) {
|
||||
if (hideViewUnderCondition(setting.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + setting);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,14 +232,14 @@ public class Utils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting condition, View view) {
|
||||
if (hideViewByRemovingFromParentUnderCondition(condition.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + condition);
|
||||
public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting setting, View view) {
|
||||
if (hideViewByRemovingFromParentUnderCondition(setting.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + setting);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hideViewByRemovingFromParentUnderCondition(boolean setting, View view) {
|
||||
if (setting) {
|
||||
public static boolean hideViewByRemovingFromParentUnderCondition(boolean condition, View view) {
|
||||
if (condition) {
|
||||
ViewParent parent = view.getParent();
|
||||
if (parent instanceof ViewGroup parentGroup) {
|
||||
parentGroup.removeView(view);
|
||||
@@ -272,12 +311,13 @@ public class Utils {
|
||||
* @return zero, if the resource is not found.
|
||||
*/
|
||||
@SuppressLint("DiscouragedApi")
|
||||
public static int getResourceIdentifier(Context context, String resourceIdentifierName, @Nullable String type) {
|
||||
return context.getResources().getIdentifier(resourceIdentifierName, type, context.getPackageName());
|
||||
public static int getResourceIdentifier(Context context, @Nullable ResourceType type, String resourceIdentifierName) {
|
||||
return context.getResources().getIdentifier(resourceIdentifierName,
|
||||
type == null ? null : type.value, context.getPackageName());
|
||||
}
|
||||
|
||||
public static int getResourceIdentifierOrThrow(Context context, String resourceIdentifierName, @Nullable String type) {
|
||||
final int resourceId = getResourceIdentifier(context, resourceIdentifierName, type);
|
||||
public static int getResourceIdentifierOrThrow(Context context, @Nullable ResourceType type, String resourceIdentifierName) {
|
||||
final int resourceId = getResourceIdentifier(context, type, resourceIdentifierName);
|
||||
if (resourceId == 0) {
|
||||
throw new Resources.NotFoundException("No resource id exists with name: " + resourceIdentifierName
|
||||
+ " type: " + type);
|
||||
@@ -287,48 +327,44 @@ public class Utils {
|
||||
|
||||
/**
|
||||
* @return zero, if the resource is not found.
|
||||
* @see #getResourceIdentifierOrThrow(String, String)
|
||||
* @see #getResourceIdentifierOrThrow(ResourceType, String)
|
||||
*/
|
||||
public static int getResourceIdentifier(String resourceIdentifierName, @Nullable String type) {
|
||||
return getResourceIdentifier(getContext(), resourceIdentifierName, type);
|
||||
public static int getResourceIdentifier(@Nullable ResourceType type, String resourceIdentifierName) {
|
||||
return getResourceIdentifier(getContext(), type, resourceIdentifierName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The resource identifier, or throws an exception if not found.
|
||||
* @return zero, if the resource is not found.
|
||||
* @see #getResourceIdentifier(ResourceType, String)
|
||||
*/
|
||||
public static int getResourceIdentifierOrThrow(String resourceIdentifierName, @Nullable String type) {
|
||||
final int resourceId = getResourceIdentifier(getContext(), resourceIdentifierName, type);
|
||||
if (resourceId == 0) {
|
||||
throw new Resources.NotFoundException("No resource id exists with name: " + resourceIdentifierName
|
||||
+ " type: " + type);
|
||||
}
|
||||
return resourceId;
|
||||
public static int getResourceIdentifierOrThrow(@Nullable ResourceType type, String resourceIdentifierName) {
|
||||
return getResourceIdentifierOrThrow(getContext(), type, resourceIdentifierName);
|
||||
}
|
||||
|
||||
public static int getResourceInteger(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||
return getContext().getResources().getInteger(getResourceIdentifierOrThrow(resourceIdentifierName, "integer"));
|
||||
return getContext().getResources().getInteger(getResourceIdentifierOrThrow(ResourceType.INTEGER, resourceIdentifierName));
|
||||
}
|
||||
|
||||
public static Animation getResourceAnimation(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||
return AnimationUtils.loadAnimation(getContext(), getResourceIdentifierOrThrow(resourceIdentifierName, "anim"));
|
||||
return AnimationUtils.loadAnimation(getContext(), getResourceIdentifierOrThrow(ResourceType.ANIM, resourceIdentifierName));
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
public static int getResourceColor(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||
//noinspection deprecation
|
||||
return getContext().getResources().getColor(getResourceIdentifierOrThrow(resourceIdentifierName, "color"));
|
||||
return getContext().getResources().getColor(getResourceIdentifierOrThrow(ResourceType.COLOR, resourceIdentifierName));
|
||||
}
|
||||
|
||||
public static int getResourceDimensionPixelSize(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||
return getContext().getResources().getDimensionPixelSize(getResourceIdentifierOrThrow(resourceIdentifierName, "dimen"));
|
||||
return getContext().getResources().getDimensionPixelSize(getResourceIdentifierOrThrow(ResourceType.DIMEN, resourceIdentifierName));
|
||||
}
|
||||
|
||||
public static float getResourceDimension(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||
return getContext().getResources().getDimension(getResourceIdentifierOrThrow(resourceIdentifierName, "dimen"));
|
||||
return getContext().getResources().getDimension(getResourceIdentifierOrThrow(ResourceType.DIMEN, resourceIdentifierName));
|
||||
}
|
||||
|
||||
public static String[] getResourceStringArray(String resourceIdentifierName) throws Resources.NotFoundException {
|
||||
return getContext().getResources().getStringArray(getResourceIdentifierOrThrow(resourceIdentifierName, "array"));
|
||||
return getContext().getResources().getStringArray(getResourceIdentifierOrThrow(ResourceType.ARRAY, resourceIdentifierName));
|
||||
}
|
||||
|
||||
public interface MatchFilter<T> {
|
||||
@@ -339,7 +375,7 @@ public class Utils {
|
||||
* Includes sub children.
|
||||
*/
|
||||
public static <R extends View> R getChildViewByResourceName(View view, String str) {
|
||||
var child = view.findViewById(Utils.getResourceIdentifierOrThrow(str, "id"));
|
||||
var child = view.findViewById(Utils.getResourceIdentifierOrThrow(ResourceType.ID, str));
|
||||
//noinspection unchecked
|
||||
return (R) child;
|
||||
}
|
||||
@@ -749,31 +785,25 @@ public class Utils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a view by setting its layout params to 0x0
|
||||
* @param view The view to hide.
|
||||
* Hides a view by setting its layout width and height to 0dp.
|
||||
* Handles null layout params safely.
|
||||
*
|
||||
* @param view The view to hide. If null, does nothing.
|
||||
*/
|
||||
public static void hideViewByLayoutParams(View view) {
|
||||
if (view instanceof LinearLayout) {
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams);
|
||||
} else if (view instanceof FrameLayout) {
|
||||
FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams2);
|
||||
} else if (view instanceof RelativeLayout) {
|
||||
RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams3);
|
||||
} else if (view instanceof Toolbar) {
|
||||
Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams4);
|
||||
} else if (view instanceof ViewGroup) {
|
||||
ViewGroup.LayoutParams layoutParams5 = new ViewGroup.LayoutParams(0, 0);
|
||||
view.setLayoutParams(layoutParams5);
|
||||
public static void hideViewByLayoutParams(@Nullable View view) {
|
||||
if (view == null) return;
|
||||
|
||||
ViewGroup.LayoutParams params = view.getLayoutParams();
|
||||
|
||||
if (params == null) {
|
||||
// Create generic 0x0 layout params accepted by all ViewGroups.
|
||||
params = new ViewGroup.LayoutParams(0, 0);
|
||||
} else {
|
||||
ViewGroup.LayoutParams params = view.getLayoutParams();
|
||||
params.width = 0;
|
||||
params.height = 0;
|
||||
view.setLayoutParams(params);
|
||||
}
|
||||
|
||||
view.setLayoutParams(params);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -790,13 +820,10 @@ public class Utils {
|
||||
public static void setDialogWindowParameters(Window window, int gravity, int yOffsetDip, int widthPercentage, boolean dimAmount) {
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
|
||||
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
|
||||
int portraitWidth = Math.min(displayMetrics.widthPixels, displayMetrics.heightPixels);
|
||||
|
||||
params.width = (int) (portraitWidth * (widthPercentage / 100.0f)); // Set width based on parameters.
|
||||
params.width = Dim.pctPortraitWidth(widthPercentage);
|
||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
params.gravity = gravity;
|
||||
params.y = yOffsetDip > 0 ? dipToPixels(yOffsetDip) : 0;
|
||||
params.y = yOffsetDip > 0 ? Dim.dp(yOffsetDip) : 0;
|
||||
if (dimAmount) {
|
||||
params.dimAmount = 0f;
|
||||
}
|
||||
@@ -806,15 +833,18 @@ public class Utils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of corner radii for a rounded rectangle shape.
|
||||
*
|
||||
* @param dp Radius in density-independent pixels (dip) to apply to all corners.
|
||||
* @return An array of eight float values representing the corner radii
|
||||
* (top-left, top-right, bottom-right, bottom-left).
|
||||
* @return If the unpatched app is currently using bold icons.
|
||||
*/
|
||||
public static float[] createCornerRadii(float dp) {
|
||||
final float radius = dipToPixels(dp);
|
||||
return new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
|
||||
public static boolean appIsUsingBoldIcons() {
|
||||
return appIsUsingBoldIcons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls if ReVanced bold icons are shown in various places.
|
||||
* @param boldIcons If the app is currently using bold icons.
|
||||
*/
|
||||
public static void setAppIsUsingBoldIcons(boolean boldIcons) {
|
||||
appIsUsingBoldIcons = boldIcons;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -976,30 +1006,60 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern punctuationPattern = Pattern.compile("\\p{P}+");
|
||||
|
||||
/**
|
||||
* Strips all punctuation and converts to lower case. A null parameter returns an empty string.
|
||||
* Removes punctuation and converts text to lowercase. Returns an empty string if input is null.
|
||||
*/
|
||||
public static String removePunctuationToLowercase(@Nullable CharSequence original) {
|
||||
if (original == null) return "";
|
||||
return punctuationPattern.matcher(original).replaceAll("")
|
||||
return PUNCTUATION_PATTERN.matcher(original).replaceAll("")
|
||||
.toLowerCase(BaseSettings.REVANCED_LANGUAGE.get().getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a PreferenceGroup and all it's sub groups by title or key.
|
||||
* Normalizes text for search: applies NFD, removes diacritics, and lowercases (locale-neutral).
|
||||
* Returns an empty string if input is null.
|
||||
*/
|
||||
public static String normalizeTextToLowercase(@Nullable CharSequence original) {
|
||||
if (original == null) return "";
|
||||
return DIACRITICS_PATTERN.matcher(Normalizer.normalize(original, Normalizer.Form.NFD))
|
||||
.replaceAll("").toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cached Collator for the current locale, or creates a new one if locale changed.
|
||||
*/
|
||||
private static Collator getCollator() {
|
||||
Locale currentLocale = BaseSettings.REVANCED_LANGUAGE.get().getLocale();
|
||||
|
||||
if (cachedCollator == null || !currentLocale.equals(cachedCollatorLocale)) {
|
||||
cachedCollatorLocale = currentLocale;
|
||||
cachedCollator = Collator.getInstance(currentLocale);
|
||||
cachedCollator.setStrength(Collator.SECONDARY); // Case-insensitive, diacritic-insensitive.
|
||||
}
|
||||
|
||||
return cachedCollator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts a {@link PreferenceGroup} and all nested subgroups by title or key.
|
||||
* <p>
|
||||
* Sort order is determined by the preferences key {@link Sort} suffix.
|
||||
* The sort order is controlled by the {@link Sort} suffix present in the preference key.
|
||||
* Preferences without a key or without a {@link Sort} suffix remain in their original order.
|
||||
* <p>
|
||||
* If a preference has no key or no {@link Sort} suffix,
|
||||
* then the preferences are left unsorted.
|
||||
* Sorting is performed using {@link Collator} with the current user locale,
|
||||
* ensuring correct alphabetical ordering for all supported languages
|
||||
* (e.g., Ukrainian "і", German "ß", French accented characters, etc.).
|
||||
*
|
||||
* @param group the {@link PreferenceGroup} to sort
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void sortPreferenceGroups(PreferenceGroup group) {
|
||||
Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED);
|
||||
List<Pair<String, Preference>> preferences = new ArrayList<>();
|
||||
|
||||
// Get cached Collator for locale-aware string comparison.
|
||||
Collator collator = getCollator();
|
||||
|
||||
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
|
||||
Preference preference = group.getPreference(i);
|
||||
|
||||
@@ -1030,10 +1090,11 @@ public class Utils {
|
||||
preferences.add(new Pair<>(sortValue, preference));
|
||||
}
|
||||
|
||||
//noinspection ComparatorCombinators
|
||||
// Sort the list using locale-specific collation rules.
|
||||
Collections.sort(preferences, (pair1, pair2)
|
||||
-> pair1.first.compareTo(pair2.first));
|
||||
-> collator.compare(pair1.first, pair2.first));
|
||||
|
||||
// Reassign order values to reflect the new sorted sequence
|
||||
int index = 0;
|
||||
for (Pair<String, Preference> pair : preferences) {
|
||||
int order = index++;
|
||||
@@ -1090,42 +1151,6 @@ public class Utils {
|
||||
return getResourceColor(colorString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts dip value to actual device pixels.
|
||||
*
|
||||
* @param dip The density-independent pixels value.
|
||||
* @return The device pixel value.
|
||||
*/
|
||||
public static int dipToPixels(float dip) {
|
||||
return (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
dip,
|
||||
Resources.getSystem().getDisplayMetrics()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen height to actual device pixels.
|
||||
*
|
||||
* @param percentage The percentage of the screen height (e.g., 30 for 30%).
|
||||
* @return The device pixel value corresponding to the percentage of screen height.
|
||||
*/
|
||||
public static int percentageHeightToPixels(int percentage) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
return (int) (metrics.heightPixels * (percentage / 100.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen width to actual device pixels.
|
||||
*
|
||||
* @param percentage The percentage of the screen width (e.g., 30 for 30%).
|
||||
* @return The device pixel value corresponding to the percentage of screen width.
|
||||
*/
|
||||
public static int percentageWidthToPixels(int percentage) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
return (int) (metrics.widthPixels * (percentage / 100.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@link #adjustColorBrightness(int, float)} depending if light or dark mode is active.
|
||||
*/
|
||||
@@ -1183,4 +1208,18 @@ public class Utils {
|
||||
public static float clamp(float value, float lower, float upper) {
|
||||
return Math.max(lower, Math.min(value, upper));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxSize The maximum number of elements to keep in the map.
|
||||
* @return A {@link LinkedHashMap} that automatically evicts the oldest entry
|
||||
* when the size exceeds {@code maxSize}.
|
||||
*/
|
||||
public static <T, V> Map<T, V> createSizeRestrictedMap(int maxSize) {
|
||||
return new LinkedHashMap<>(2 * maxSize) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry eldest) {
|
||||
return size() > maxSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
@@ -128,7 +129,7 @@ abstract class Check {
|
||||
// Add icon to the dialog.
|
||||
ImageView iconView = new ImageView(activity);
|
||||
iconView.setImageResource(Utils.getResourceIdentifierOrThrow(
|
||||
"revanced_ic_dialog_alert", "drawable"));
|
||||
ResourceType.DRAWABLE, "revanced_ic_dialog_alert"));
|
||||
iconView.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
|
||||
iconView.setPadding(0, 0, 0, 0);
|
||||
LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(
|
||||
|
||||
@@ -15,7 +15,6 @@ import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
|
||||
public abstract class BaseFixRedgifsApiPatch implements Interceptor {
|
||||
protected static BaseFixRedgifsApiPatch INSTANCE;
|
||||
public abstract String getDefaultUserAgent();
|
||||
|
||||
@@ -61,7 +61,11 @@ public class CheckWatchHistoryDomainNameResolutionPatch {
|
||||
// Prevent this false positive by verify youtube.com resolves.
|
||||
// If youtube.com does not resolve, then it's not a watch history domain resolving error
|
||||
// because the entire app will not work since no domains are resolving.
|
||||
if (!domainResolvesToValidIP("youtube.com")
|
||||
String domainYouTube = "youtube.com";
|
||||
if (!domainResolvesToValidIP(domainYouTube)
|
||||
|| domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)
|
||||
// Check multiple times, so a false positive from a flaky connection is almost impossible.
|
||||
|| !domainResolvesToValidIP(domainYouTube)
|
||||
|| domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -12,6 +13,7 @@ import java.util.Locale;
|
||||
|
||||
import app.revanced.extension.shared.GmsCoreSupport;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
@@ -64,13 +66,24 @@ public class CustomBrandingPatch {
|
||||
iconName += "_custom";
|
||||
}
|
||||
|
||||
notificationSmallIcon = Utils.getResourceIdentifier(iconName, "drawable");
|
||||
notificationSmallIcon = Utils.getResourceIdentifier(ResourceType.DRAWABLE, iconName);
|
||||
if (notificationSmallIcon == 0) {
|
||||
Logger.printException(() -> "Could not load notification small icon");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static View getLottieViewOrNull(View lottieStartupView) {
|
||||
if (BaseSettings.CUSTOM_BRANDING_ICON.get() == BrandingTheme.ORIGINAL) {
|
||||
return lottieStartupView;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package app.revanced.extension.shared.patches;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -21,12 +25,28 @@ public final class EnableDebuggingPatch {
|
||||
? new ConcurrentHashMap<>(800, 0.5f, 1)
|
||||
: null;
|
||||
|
||||
private static final Set<Long> DISABLED_FEATURE_FLAGS = parseFlags(BaseSettings.DISABLED_FEATURE_FLAGS.get());
|
||||
|
||||
// Log all disabled flags on app startup.
|
||||
static {
|
||||
if (LOG_FEATURE_FLAGS && !DISABLED_FEATURE_FLAGS.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder("Disabled feature flags:\n");
|
||||
for (Long flag : DISABLED_FEATURE_FLAGS) {
|
||||
sb.append(" ").append(flag).append('\n');
|
||||
}
|
||||
Logger.printDebug(sb::toString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isBooleanFeatureFlagEnabled(boolean value, Long flag) {
|
||||
if (LOG_FEATURE_FLAGS && value) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
if (DISABLED_FEATURE_FLAGS.contains(flag)) {
|
||||
return false;
|
||||
}
|
||||
if (featureFlags.putIfAbsent(flag, TRUE) == null) {
|
||||
Logger.printDebug(() -> "boolean feature is enabled: " + flag);
|
||||
}
|
||||
}
|
||||
@@ -70,10 +90,44 @@ public final class EnableDebuggingPatch {
|
||||
if (LOG_FEATURE_FLAGS && !defaultValue.equals(value)) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
Logger.printDebug(() -> " string feature is enabled: " + flag
|
||||
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
|
||||
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all logged feature flags.
|
||||
* @return Set of all known flags
|
||||
*/
|
||||
public static Set<Long> getAllLoggedFlags() {
|
||||
if (featureFlags != null) {
|
||||
return new HashSet<>(featureFlags.keySet());
|
||||
}
|
||||
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method for parsing flags.
|
||||
* @param flags String containing newline-separated flag IDs
|
||||
* @return Set of parsed flag IDs
|
||||
*/
|
||||
public static Set<Long> parseFlags(String flags) {
|
||||
Set<Long> parsedFlags = new HashSet<>();
|
||||
if (!flags.isBlank()) {
|
||||
for (String flag : flags.split("\n")) {
|
||||
String trimmedFlag = flag.trim();
|
||||
if (trimmedFlag.isEmpty()) continue; // Skip empty lines.
|
||||
try {
|
||||
parsedFlags.add(Long.parseLong(trimmedFlag));
|
||||
} catch (NumberFormatException e) {
|
||||
Logger.printException(() -> "Invalid flag ID: " + flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parsedFlags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,15 @@ public class LinkSanitizer {
|
||||
|
||||
public Uri sanitizeUri(Uri uri) {
|
||||
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();
|
||||
|
||||
if (!parametersToRemove.isEmpty()) {
|
||||
|
||||
@@ -7,15 +7,16 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
/**
|
||||
* Base class for hooking activities to inject a custom PreferenceFragment with a toolbar.
|
||||
@@ -25,13 +26,13 @@ import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragme
|
||||
public abstract class BaseActivityHook extends Activity {
|
||||
|
||||
private static final int ID_REVANCED_SETTINGS_FRAGMENTS =
|
||||
getResourceIdentifierOrThrow("revanced_settings_fragments", "id");
|
||||
getResourceIdentifierOrThrow(ResourceType.ID, "revanced_settings_fragments");
|
||||
private static final int ID_REVANCED_TOOLBAR_PARENT =
|
||||
getResourceIdentifierOrThrow("revanced_toolbar_parent", "id");
|
||||
getResourceIdentifierOrThrow(ResourceType.ID, "revanced_toolbar_parent");
|
||||
public static final int LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR =
|
||||
getResourceIdentifierOrThrow("revanced_settings_with_toolbar", "layout");
|
||||
getResourceIdentifierOrThrow(ResourceType.LAYOUT, "revanced_settings_with_toolbar");
|
||||
private static final int STRING_REVANCED_SETTINGS_TITLE =
|
||||
getResourceIdentifierOrThrow("revanced_settings_title", "string");
|
||||
getResourceIdentifierOrThrow(ResourceType.STRING, "revanced_settings_title");
|
||||
|
||||
/**
|
||||
* Layout parameters for the toolbar, extracted from the dummy toolbar.
|
||||
@@ -109,13 +110,12 @@ public abstract class BaseActivityHook extends Activity {
|
||||
toolbar.setNavigationOnClickListener(getNavigationClickListener(activity));
|
||||
toolbar.setTitle(STRING_REVANCED_SETTINGS_TITLE);
|
||||
|
||||
final int margin = Utils.dipToPixels(16);
|
||||
toolbar.setTitleMarginStart(margin);
|
||||
toolbar.setTitleMarginEnd(margin);
|
||||
toolbar.setTitleMarginStart(Dim.dp16);
|
||||
toolbar.setTitleMarginEnd(Dim.dp16);
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar, false, view -> view instanceof TextView);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
toolbarTextView.setTextSize(20);
|
||||
}
|
||||
setToolbarLayoutParams(toolbar);
|
||||
|
||||
@@ -124,16 +124,18 @@ public abstract class BaseActivityHook extends Activity {
|
||||
toolBarParent.addView(toolbar, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the content view layout.
|
||||
*/
|
||||
protected int getContentViewResourceId() {
|
||||
return LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the activity's theme.
|
||||
*/
|
||||
protected abstract void customizeActivityTheme(Activity activity);
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the content view layout.
|
||||
*/
|
||||
protected abstract int getContentViewResourceId();
|
||||
|
||||
/**
|
||||
* Returns the background color for the toolbar.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,8 @@ import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.extension.shared.patches.CustomBrandingPatch.BrandingTheme;
|
||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
/**
|
||||
* Settings shared across multiple apps.
|
||||
* <p>
|
||||
@@ -24,10 +26,19 @@ public class BaseSettings {
|
||||
* Use the icons declared in the preferences created during patching. If no icons or styles are declared then this setting does nothing.
|
||||
*/
|
||||
public static final BooleanSetting SHOW_MENU_ICONS = new BooleanSetting("revanced_show_menu_icons", TRUE, true);
|
||||
/**
|
||||
* Do not use this setting directly. Instead use {@link app.revanced.extension.shared.Utils#appIsUsingBoldIcons()}
|
||||
*/
|
||||
public static final BooleanSetting SETTINGS_DISABLE_BOLD_ICONS = new BooleanSetting("revanced_settings_disable_bold_icons", FALSE, true);
|
||||
|
||||
public static final BooleanSetting SETTINGS_SEARCH_HISTORY = new BooleanSetting("revanced_settings_search_history", TRUE, true);
|
||||
public static final StringSetting SETTINGS_SEARCH_ENTRIES = new StringSetting("revanced_settings_search_entries", "");
|
||||
|
||||
/**
|
||||
* The first time the app was launched with no previous app data (either a clean install, or after wiping app data).
|
||||
*/
|
||||
public static final LongSetting FIRST_TIME_APP_LAUNCHED = new LongSetting("revanced_last_time_app_was_launched", -1L, false, false);
|
||||
|
||||
//
|
||||
// Settings shared by YouTube and YouTube Music.
|
||||
//
|
||||
@@ -42,4 +53,15 @@ public class BaseSettings {
|
||||
|
||||
public static final EnumSetting<BrandingTheme> CUSTOM_BRANDING_ICON = new EnumSetting<>("revanced_custom_branding_icon", BrandingTheme.ORIGINAL, true);
|
||||
public static final IntegerSetting CUSTOM_BRANDING_NAME = new IntegerSetting("revanced_custom_branding_name", 1, true);
|
||||
|
||||
public static final StringSetting DISABLED_FEATURE_FLAGS = new StringSetting("revanced_disabled_feature_flags", "", true, parent(DEBUG));
|
||||
|
||||
static {
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
if (FIRST_TIME_APP_LAUNCHED.get() < 0) {
|
||||
Logger.printInfo(() -> "First launch of installation with no prior app data");
|
||||
FIRST_TIME_APP_LAUNCHED.save(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,10 +392,13 @@ public abstract class Setting<T> {
|
||||
|
||||
/**
|
||||
* Get the parent Settings that this setting depends on.
|
||||
* @return List of parent Settings (e.g., BooleanSetting or EnumSetting), or empty list if no dependencies exist.
|
||||
* @return List of parent Settings, or empty list if no dependencies exist.
|
||||
* Defensive: handles null availability or missing getParentSettings() override.
|
||||
*/
|
||||
public List<Setting<?>> getParentSettings() {
|
||||
return availability == null ? Collections.emptyList() : availability.getParentSettings();
|
||||
return availability == null
|
||||
? Collections.emptyList()
|
||||
: Objects.requireNonNullElse(availability.getParentSettings(), Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
@@ -103,10 +104,16 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
* so all app specific {@link Setting} instances are loaded before this method returns.
|
||||
*/
|
||||
protected void initialize() {
|
||||
String preferenceResourceName = BaseSettings.SHOW_MENU_ICONS.get()
|
||||
? "revanced_prefs_icons"
|
||||
: "revanced_prefs";
|
||||
final var identifier = Utils.getResourceIdentifier(preferenceResourceName, "xml");
|
||||
String preferenceResourceName;
|
||||
if (BaseSettings.SHOW_MENU_ICONS.get()) {
|
||||
preferenceResourceName = Utils.appIsUsingBoldIcons()
|
||||
? "revanced_prefs_icons_bold"
|
||||
: "revanced_prefs_icons";
|
||||
} else {
|
||||
preferenceResourceName = "revanced_prefs";
|
||||
}
|
||||
|
||||
final var identifier = Utils.getResourceIdentifier(ResourceType.XML, preferenceResourceName);
|
||||
if (identifier == 0) return;
|
||||
addPreferencesFromResource(identifier);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
|
||||
|
||||
import android.app.Dialog;
|
||||
@@ -32,11 +31,13 @@ import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.StringSetting;
|
||||
import app.revanced.extension.shared.ui.ColorDot;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
/**
|
||||
* A custom preference for selecting a color via a hexadecimal code or a color picker dialog.
|
||||
@@ -81,13 +82,13 @@ public class ColorPickerPreference extends EditTextPreference {
|
||||
private boolean opacitySliderEnabled = false;
|
||||
|
||||
public static final int ID_REVANCED_COLOR_PICKER_VIEW =
|
||||
getResourceIdentifierOrThrow("revanced_color_picker_view", "id");
|
||||
getResourceIdentifierOrThrow(ResourceType.ID, "revanced_color_picker_view");
|
||||
public static final int ID_PREFERENCE_COLOR_DOT =
|
||||
getResourceIdentifierOrThrow("preference_color_dot", "id");
|
||||
getResourceIdentifierOrThrow(ResourceType.ID, "preference_color_dot");
|
||||
public static final int LAYOUT_REVANCED_COLOR_DOT_WIDGET =
|
||||
getResourceIdentifierOrThrow("revanced_color_dot_widget", "layout");
|
||||
getResourceIdentifierOrThrow(ResourceType.LAYOUT, "revanced_color_dot_widget");
|
||||
public static final int LAYOUT_REVANCED_COLOR_PICKER =
|
||||
getResourceIdentifierOrThrow("revanced_color_picker", "layout");
|
||||
getResourceIdentifierOrThrow(ResourceType.LAYOUT, "revanced_color_picker");
|
||||
|
||||
/**
|
||||
* Removes non valid hex characters, converts to all uppercase,
|
||||
@@ -310,11 +311,8 @@ public class ColorPickerPreference extends EditTextPreference {
|
||||
inputLayout.setGravity(Gravity.CENTER_VERTICAL);
|
||||
|
||||
dialogColorDot = new View(context);
|
||||
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(
|
||||
dipToPixels(20),
|
||||
dipToPixels(20)
|
||||
);
|
||||
previewParams.setMargins(dipToPixels(16), 0, dipToPixels(10), 0);
|
||||
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(Dim.dp20,Dim.dp20);
|
||||
previewParams.setMargins(Dim.dp16, 0, Dim.dp10, 0);
|
||||
dialogColorDot.setLayoutParams(previewParams);
|
||||
inputLayout.addView(dialogColorDot);
|
||||
updateDialogColorDot();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.getColorString;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -21,6 +20,7 @@ import androidx.annotation.ColorInt;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
/**
|
||||
* A custom color picker view that allows the user to select a color using a hue slider, a saturation-value selector
|
||||
@@ -54,28 +54,28 @@ public class ColorPickerView extends View {
|
||||
}
|
||||
|
||||
/** Expanded touch area for the hue and opacity bars to increase the touch-sensitive area. */
|
||||
public static final float TOUCH_EXPANSION = dipToPixels(20f);
|
||||
public static final float TOUCH_EXPANSION = Dim.dp20;
|
||||
|
||||
/** Margin between different areas of the view (saturation-value selector, hue bar, and opacity slider). */
|
||||
private static final float MARGIN_BETWEEN_AREAS = dipToPixels(24);
|
||||
private static final float MARGIN_BETWEEN_AREAS = Dim.dp24;
|
||||
|
||||
/** Padding around the view. */
|
||||
private static final float VIEW_PADDING = dipToPixels(16);
|
||||
private static final float VIEW_PADDING = Dim.dp16;
|
||||
|
||||
/** Height of the hue bar. */
|
||||
private static final float HUE_BAR_HEIGHT = dipToPixels(12);
|
||||
private static final float HUE_BAR_HEIGHT = Dim.dp12;
|
||||
|
||||
/** Height of the opacity slider. */
|
||||
private static final float OPACITY_BAR_HEIGHT = dipToPixels(12);
|
||||
private static final float OPACITY_BAR_HEIGHT = Dim.dp12;
|
||||
|
||||
/** Corner radius for the hue bar. */
|
||||
private static final float HUE_CORNER_RADIUS = dipToPixels(6);
|
||||
private static final float HUE_CORNER_RADIUS = Dim.dp6;
|
||||
|
||||
/** Corner radius for the opacity slider. */
|
||||
private static final float OPACITY_CORNER_RADIUS = dipToPixels(6);
|
||||
private static final float OPACITY_CORNER_RADIUS = Dim.dp6;
|
||||
|
||||
/** Radius of the selector handles. */
|
||||
private static final float SELECTOR_RADIUS = dipToPixels(12);
|
||||
private static final float SELECTOR_RADIUS = Dim.dp12;
|
||||
|
||||
/** Stroke width for the selector handle outlines. */
|
||||
private static final float SELECTOR_STROKE_WIDTH = 8;
|
||||
@@ -202,7 +202,7 @@ public class ColorPickerView extends View {
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
final float DESIRED_ASPECT_RATIO = 0.8f; // height = width * 0.8
|
||||
|
||||
final int minWidth = dipToPixels(250);
|
||||
final int minWidth = Dim.dp(250);
|
||||
final int minHeight = (int) (minWidth * DESIRED_ASPECT_RATIO) + (int) (HUE_BAR_HEIGHT + MARGIN_BETWEEN_AREAS)
|
||||
+ (opacitySliderEnabled ? (int) (OPACITY_BAR_HEIGHT + MARGIN_BETWEEN_AREAS) : 0);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
|
||||
@@ -30,14 +31,18 @@ import app.revanced.extension.shared.ui.CustomDialog;
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class CustomDialogListPreference extends ListPreference {
|
||||
|
||||
public static final int ID_REVANCED_CHECK_ICON =
|
||||
getResourceIdentifierOrThrow("revanced_check_icon", "id");
|
||||
public static final int ID_REVANCED_CHECK_ICON_PLACEHOLDER =
|
||||
getResourceIdentifierOrThrow("revanced_check_icon_placeholder", "id");
|
||||
public static final int ID_REVANCED_ITEM_TEXT =
|
||||
getResourceIdentifierOrThrow("revanced_item_text", "id");
|
||||
public static final int LAYOUT_REVANCED_CUSTOM_LIST_ITEM_CHECKED =
|
||||
getResourceIdentifierOrThrow("revanced_custom_list_item_checked", "layout");
|
||||
public static final int ID_REVANCED_CHECK_ICON = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "revanced_check_icon");
|
||||
public static final int ID_REVANCED_CHECK_ICON_PLACEHOLDER = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "revanced_check_icon_placeholder");
|
||||
public static final int ID_REVANCED_ITEM_TEXT = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "revanced_item_text");
|
||||
public static final int LAYOUT_REVANCED_CUSTOM_LIST_ITEM_CHECKED = getResourceIdentifierOrThrow(
|
||||
ResourceType.LAYOUT, "revanced_custom_list_item_checked");
|
||||
public static final int DRAWABLE_CHECKMARK = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_custom_checkmark");
|
||||
public static final int DRAWABLE_CHECKMARK_BOLD = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_custom_checkmark_bold");
|
||||
|
||||
private String staticSummary = null;
|
||||
private CharSequence[] highlightedEntriesForDialog = null;
|
||||
@@ -125,9 +130,13 @@ public class CustomDialogListPreference extends ListPreference {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(layoutResourceId, parent, false);
|
||||
holder = new SubViewDataContainer();
|
||||
holder.checkIcon = view.findViewById(ID_REVANCED_CHECK_ICON);
|
||||
holder.placeholder = view.findViewById(ID_REVANCED_CHECK_ICON_PLACEHOLDER);
|
||||
holder.itemText = view.findViewById(ID_REVANCED_ITEM_TEXT);
|
||||
holder.checkIcon = view.findViewById(ID_REVANCED_CHECK_ICON);
|
||||
holder.checkIcon.setImageResource(Utils.appIsUsingBoldIcons()
|
||||
? DRAWABLE_CHECKMARK_BOLD
|
||||
: DRAWABLE_CHECKMARK
|
||||
);
|
||||
view.setTag(holder);
|
||||
} else {
|
||||
holder = (SubViewDataContainer) view.getTag();
|
||||
|
||||
@@ -0,0 +1,625 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.preference.Preference;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.patches.EnableDebuggingPatch;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
/**
|
||||
* A custom preference that opens a dialog for managing feature flags.
|
||||
* Allows moving boolean flags between active and blocked states with advanced selection.
|
||||
*/
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class FeatureFlagsManagerPreference extends Preference {
|
||||
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_SELECT_ALL =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_select_all");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_DESELECT_ALL =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_deselect_all");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_COPY_ALL =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_copy_all");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_ONE =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_right_one");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_DOUBLE =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_right_double");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_ONE =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_left_one");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_DOUBLE =
|
||||
getResourceIdentifierOrThrow(ResourceType.DRAWABLE, "revanced_settings_arrow_left_double");
|
||||
|
||||
/**
|
||||
* Flags to hide from the UI.
|
||||
*/
|
||||
private static final Set<Long> FLAGS_TO_IGNORE = Set.of(
|
||||
45386834L, // 'You' tab settings icon.
|
||||
45685201L // Bold icons. Forcing off interferes with patch changes and YT icons are broken.
|
||||
);
|
||||
|
||||
/**
|
||||
* Tracks state for range selection in ListView.
|
||||
*/
|
||||
private static class ListViewSelectionState {
|
||||
int lastClickedPosition = -1; // Position of the last clicked item.
|
||||
boolean isRangeSelecting = false; // True while a range is being selected.
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to pass ListView and Adapter together.
|
||||
*/
|
||||
private record ColumnViews(ListView listView, FlagAdapter adapter) {}
|
||||
|
||||
{
|
||||
setOnPreferenceClickListener(pref -> {
|
||||
showFlagsManagerDialog();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public FeatureFlagsManagerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public FeatureFlagsManagerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public FeatureFlagsManagerPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FeatureFlagsManagerPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the main dialog for managing feature flags.
|
||||
*/
|
||||
private void showFlagsManagerDialog() {
|
||||
if (!BaseSettings.DEBUG.get()) {
|
||||
Utils.showToastShort(str("revanced_debug_logs_disabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
Context context = getContext();
|
||||
|
||||
// Load all known and disabled flags.
|
||||
TreeSet<Long> allKnownFlags = new TreeSet<>(EnableDebuggingPatch.getAllLoggedFlags());
|
||||
allKnownFlags.removeAll(FLAGS_TO_IGNORE);
|
||||
|
||||
TreeSet<Long> disabledFlags = new TreeSet<>(EnableDebuggingPatch.parseFlags(
|
||||
BaseSettings.DISABLED_FEATURE_FLAGS.get()));
|
||||
disabledFlags.removeAll(FLAGS_TO_IGNORE);
|
||||
|
||||
if (allKnownFlags.isEmpty() && disabledFlags.isEmpty()) {
|
||||
// String does not need to be localized because it's basically impossible
|
||||
// to reach the settings menu without encountering at least 1 flag.
|
||||
Utils.showToastShort("No feature flags logged yet");
|
||||
return;
|
||||
}
|
||||
|
||||
TreeSet<Long> availableFlags = new TreeSet<>(allKnownFlags);
|
||||
availableFlags.removeAll(disabledFlags);
|
||||
TreeSet<Long> blockedFlags = new TreeSet<>(disabledFlags);
|
||||
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
context,
|
||||
getTitle() != null ? getTitle().toString() : "",
|
||||
null,
|
||||
null,
|
||||
str("revanced_settings_save"),
|
||||
() -> saveFlags(blockedFlags),
|
||||
() -> {},
|
||||
str("revanced_settings_reset"),
|
||||
this::resetFlags,
|
||||
true
|
||||
);
|
||||
|
||||
LinearLayout mainLayout = dialogPair.second;
|
||||
LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f);
|
||||
|
||||
// Insert content before the dialog button row.
|
||||
View contentView = createContentView(context, availableFlags, blockedFlags);
|
||||
mainLayout.addView(contentView, mainLayout.getChildCount() - 1, contentParams);
|
||||
|
||||
Dialog dialog = dialogPair.first;
|
||||
dialog.show();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
Utils.setDialogWindowParameters(window, Gravity.CENTER, 0, 100, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the main content view with two columns.
|
||||
*/
|
||||
private View createContentView(Context context, TreeSet<Long> availableFlags, TreeSet<Long> blockedFlags) {
|
||||
LinearLayout contentLayout = new LinearLayout(context);
|
||||
contentLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
// Headers.
|
||||
TextView availableHeader = createHeader(context, "revanced_debug_feature_flags_manager_active_header");
|
||||
TextView blockedHeader = createHeader(context, "revanced_debug_feature_flags_manager_blocked_header");
|
||||
|
||||
LinearLayout headersLayout = new LinearLayout(context);
|
||||
headersLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
headersLayout.addView(availableHeader, new LinearLayout.LayoutParams(
|
||||
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
||||
headersLayout.addView(blockedHeader, new LinearLayout.LayoutParams(
|
||||
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
||||
|
||||
// Columns.
|
||||
View leftColumn = createColumn(context, availableFlags, availableHeader);
|
||||
View rightColumn = createColumn(context, blockedFlags, blockedHeader);
|
||||
|
||||
ColumnViews leftViews = (ColumnViews) leftColumn.getTag();
|
||||
ColumnViews rightViews = (ColumnViews) rightColumn.getTag();
|
||||
|
||||
updateHeaderCount(availableHeader, leftViews.adapter);
|
||||
updateHeaderCount(blockedHeader, rightViews.adapter);
|
||||
|
||||
// Main columns layout.
|
||||
LinearLayout columnsLayout = new LinearLayout(context);
|
||||
columnsLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
columnsLayout.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
|
||||
columnsLayout.addView(leftColumn, new LinearLayout.LayoutParams(
|
||||
0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
|
||||
|
||||
Space spaceBetweenColumns = new Space(context);
|
||||
spaceBetweenColumns.setLayoutParams(new LinearLayout.LayoutParams(Dim.dp8, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
columnsLayout.addView(spaceBetweenColumns);
|
||||
|
||||
columnsLayout.addView(rightColumn, new LinearLayout.LayoutParams(
|
||||
0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
|
||||
|
||||
// Move buttons below columns.
|
||||
Pair<LinearLayout, LinearLayout> moveButtons = createMoveButtons(context,
|
||||
leftViews.listView, rightViews.listView,
|
||||
availableFlags, blockedFlags, availableHeader, blockedHeader);
|
||||
|
||||
// Layout for buttons row.
|
||||
LinearLayout buttonsRow = new LinearLayout(context);
|
||||
buttonsRow.setOrientation(LinearLayout.HORIZONTAL);
|
||||
buttonsRow.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
buttonsRow.addView(moveButtons.first, new LinearLayout.LayoutParams(
|
||||
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
||||
|
||||
Space spaceBetweenButtons = new Space(context);
|
||||
spaceBetweenButtons.setLayoutParams(new LinearLayout.LayoutParams(Dim.dp8, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
buttonsRow.addView(spaceBetweenButtons);
|
||||
|
||||
buttonsRow.addView(moveButtons.second, new LinearLayout.LayoutParams(
|
||||
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
||||
|
||||
contentLayout.addView(headersLayout);
|
||||
contentLayout.addView(columnsLayout);
|
||||
contentLayout.addView(buttonsRow);
|
||||
|
||||
return contentLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a header TextView.
|
||||
*/
|
||||
private TextView createHeader(Context context, String tag) {
|
||||
TextView textview = new TextView(context);
|
||||
textview.setTag(tag);
|
||||
textview.setTextSize(16);
|
||||
textview.setTextColor(Utils.getAppForegroundColor());
|
||||
textview.setGravity(Gravity.CENTER);
|
||||
|
||||
return textview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single column (search + buttons + list).
|
||||
*/
|
||||
private View createColumn(Context context, TreeSet<Long> flags, TextView countText) {
|
||||
LinearLayout wrapper = new LinearLayout(context);
|
||||
wrapper.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
Pair<ListView, FlagAdapter> pair = createListView(context, flags, countText);
|
||||
ListView listView = pair.first;
|
||||
FlagAdapter adapter = pair.second;
|
||||
|
||||
EditText search = createSearchBox(context, adapter, listView, countText);
|
||||
LinearLayout buttons = createActionButtons(context, listView, adapter);
|
||||
|
||||
listView.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Dim.roundedCorners(10), null, null));
|
||||
background.getPaint().setColor(Utils.getEditTextBackground());
|
||||
listView.setPadding(0, Dim.dp4, 0, Dim.dp4);
|
||||
listView.setBackground(background);
|
||||
listView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
|
||||
wrapper.addView(search);
|
||||
wrapper.addView(buttons);
|
||||
wrapper.addView(listView);
|
||||
|
||||
// Save references for move buttons.
|
||||
wrapper.setTag(new ColumnViews(listView, adapter));
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the header text with the current count.
|
||||
*/
|
||||
private void updateHeaderCount(TextView header, FlagAdapter adapter) {
|
||||
header.setText(str((String) header.getTag(), adapter.getCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a search box that filters the list.
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private EditText createSearchBox(Context context, FlagAdapter adapter, ListView listView, TextView countText) {
|
||||
EditText search = new EditText(context);
|
||||
search.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
search.setTextSize(16);
|
||||
search.setHint(str("revanced_debug_feature_flags_manager_search_hint"));
|
||||
search.setHapticFeedbackEnabled(false);
|
||||
search.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
search.addTextChangedListener(new TextWatcher() {
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
adapter.setSearchQuery(s.toString());
|
||||
listView.clearChoices();
|
||||
updateHeaderCount(countText, adapter);
|
||||
Drawable clearIcon = context.getResources().getDrawable(android.R.drawable.ic_menu_close_clear_cancel);
|
||||
clearIcon.setBounds(0, 0, Dim.dp20, Dim.dp20);
|
||||
search.setCompoundDrawables(null, null, TextUtils.isEmpty(s) ? null : clearIcon, null);
|
||||
}
|
||||
@Override public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
|
||||
search.setOnTouchListener((v, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
Drawable[] compoundDrawables = search.getCompoundDrawables();
|
||||
if (compoundDrawables[2] != null &&
|
||||
event.getRawX() >= (search.getRight() - compoundDrawables[2].getBounds().width())) {
|
||||
search.setText("");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates action buttons.
|
||||
*/
|
||||
private LinearLayout createActionButtons(Context context, ListView listView, FlagAdapter adapter) {
|
||||
LinearLayout row = new LinearLayout(context);
|
||||
row.setOrientation(LinearLayout.HORIZONTAL);
|
||||
row.setGravity(Gravity.CENTER);
|
||||
row.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
ImageButton selectAll = createButton(context, DRAWABLE_REVANCED_SETTINGS_SELECT_ALL,
|
||||
() -> {
|
||||
for (int i = 0, count = adapter.getCount(); i < count; i++) {
|
||||
listView.setItemChecked(i, true);
|
||||
}
|
||||
});
|
||||
|
||||
ImageButton clearAll = createButton(context, DRAWABLE_REVANCED_SETTINGS_DESELECT_ALL,
|
||||
() -> {
|
||||
listView.clearChoices();
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
|
||||
ImageButton copy = createButton(context, DRAWABLE_REVANCED_SETTINGS_COPY_ALL,
|
||||
() -> {
|
||||
List<String> items = new ArrayList<>();
|
||||
SparseBooleanArray checked = listView.getCheckedItemPositions();
|
||||
|
||||
if (checked.size() > 0) {
|
||||
for (int i = 0, count = adapter.getCount(); i < count; i++) {
|
||||
if (checked.get(i)) {
|
||||
items.add(adapter.getItem(i));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Long flag : adapter.getFullFlags()) {
|
||||
items.add(String.valueOf(flag));
|
||||
}
|
||||
}
|
||||
|
||||
Utils.setClipboard(TextUtils.join("\n", items));
|
||||
|
||||
Utils.showToastShort(str("revanced_debug_feature_flags_manager_toast_copied"));
|
||||
});
|
||||
|
||||
row.addView(selectAll);
|
||||
row.addView(clearAll);
|
||||
row.addView(copy);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the move buttons (left and right groups).
|
||||
*/
|
||||
private Pair<LinearLayout, LinearLayout> createMoveButtons(Context context,
|
||||
ListView availableListView, ListView blockedListView,
|
||||
TreeSet<Long> availableFlags, TreeSet<Long> blockedFlags,
|
||||
TextView availableCountText, TextView blockedCountText) {
|
||||
// Left group: >> >
|
||||
LinearLayout leftButtons = new LinearLayout(context);
|
||||
leftButtons.setOrientation(LinearLayout.HORIZONTAL);
|
||||
leftButtons.setGravity(Gravity.CENTER);
|
||||
|
||||
ImageButton moveAllRight = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_DOUBLE,
|
||||
() -> moveFlags(availableListView, blockedListView, availableFlags, blockedFlags,
|
||||
availableCountText, blockedCountText, true));
|
||||
|
||||
ImageButton moveOneRight = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_ONE,
|
||||
() -> moveFlags(availableListView, blockedListView, availableFlags, blockedFlags,
|
||||
availableCountText, blockedCountText, false));
|
||||
|
||||
leftButtons.addView(moveAllRight);
|
||||
leftButtons.addView(moveOneRight);
|
||||
|
||||
// Right group: < <<
|
||||
LinearLayout rightButtons = new LinearLayout(context);
|
||||
rightButtons.setOrientation(LinearLayout.HORIZONTAL);
|
||||
rightButtons.setGravity(Gravity.CENTER);
|
||||
|
||||
ImageButton moveOneLeft = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_ONE,
|
||||
() -> moveFlags(blockedListView, availableListView, blockedFlags, availableFlags,
|
||||
blockedCountText, availableCountText, false));
|
||||
|
||||
ImageButton moveAllLeft = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_DOUBLE,
|
||||
() -> moveFlags(blockedListView, availableListView, blockedFlags, availableFlags,
|
||||
blockedCountText, availableCountText, true));
|
||||
|
||||
rightButtons.addView(moveOneLeft);
|
||||
rightButtons.addView(moveAllLeft);
|
||||
|
||||
return new Pair<>(leftButtons, rightButtons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a styled ImageButton.
|
||||
*/
|
||||
@SuppressLint("ResourceType")
|
||||
private ImageButton createButton(Context context, int drawableResId, Runnable action) {
|
||||
ImageButton button = new ImageButton(context);
|
||||
|
||||
button.setImageResource(drawableResId);
|
||||
button.setScaleType(ImageView.ScaleType.CENTER);
|
||||
int[] attrs = {android.R.attr.selectableItemBackgroundBorderless};
|
||||
//noinspection Recycle
|
||||
TypedArray ripple = context.obtainStyledAttributes(attrs);
|
||||
button.setBackgroundDrawable(ripple.getDrawable(0));
|
||||
ripple.close();
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(Dim.dp32, Dim.dp32);
|
||||
params.setMargins(Dim.dp8, Dim.dp8, Dim.dp8, Dim.dp8);
|
||||
button.setLayoutParams(params);
|
||||
|
||||
button.setOnClickListener(v -> action.run());
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom adapter with search filtering.
|
||||
*/
|
||||
private static class FlagAdapter extends ArrayAdapter<String> {
|
||||
private final TreeSet<Long> fullFlags;
|
||||
private String searchQuery = "";
|
||||
|
||||
public FlagAdapter(Context context, TreeSet<Long> fullFlags) {
|
||||
super(context, android.R.layout.simple_list_item_multiple_choice, new ArrayList<>());
|
||||
this.fullFlags = fullFlags;
|
||||
updateFiltered();
|
||||
}
|
||||
|
||||
public void setSearchQuery(String query) {
|
||||
searchQuery = query == null ? "" : query.trim();
|
||||
updateFiltered();
|
||||
}
|
||||
|
||||
private void updateFiltered() {
|
||||
clear();
|
||||
for (Long flag : fullFlags) {
|
||||
String flagString = String.valueOf(flag);
|
||||
if (searchQuery.isEmpty() || flagString.contains(searchQuery)) {
|
||||
add(flagString);
|
||||
}
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
updateFiltered();
|
||||
}
|
||||
|
||||
public List<Long> getFullFlags() {
|
||||
return new ArrayList<>(fullFlags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ListView with filtering, multi-select, and range selection.
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private Pair<ListView, FlagAdapter> createListView(Context context,
|
||||
TreeSet<Long> flags, TextView countText) {
|
||||
ListView listView = new ListView(context);
|
||||
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
listView.setDividerHeight(0);
|
||||
|
||||
FlagAdapter adapter = new FlagAdapter(context, flags);
|
||||
listView.setAdapter(adapter);
|
||||
|
||||
final ListViewSelectionState state = new ListViewSelectionState();
|
||||
|
||||
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
if (!state.isRangeSelecting) {
|
||||
state.lastClickedPosition = position;
|
||||
} else {
|
||||
state.isRangeSelecting = false;
|
||||
}
|
||||
});
|
||||
|
||||
listView.setOnItemLongClickListener((parent, view, position, id) -> {
|
||||
if (state.lastClickedPosition == -1) {
|
||||
listView.setItemChecked(position, true);
|
||||
state.lastClickedPosition = position;
|
||||
} else {
|
||||
int start = Math.min(state.lastClickedPosition, position);
|
||||
int end = Math.max(state.lastClickedPosition, position);
|
||||
for (int i = start; i <= end; i++) {
|
||||
listView.setItemChecked(i, true);
|
||||
}
|
||||
state.isRangeSelecting = true;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
listView.setOnTouchListener((view, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP && state.isRangeSelecting) {
|
||||
state.isRangeSelecting = false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return new Pair<>(listView, adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves selected or all flags from one list to another.
|
||||
*
|
||||
* @param fromListView Source ListView.
|
||||
* @param toListView Destination ListView.
|
||||
* @param fromFlags Source flag set.
|
||||
* @param toFlags Destination flag set.
|
||||
* @param fromCountText Header showing count of source items.
|
||||
* @param toCountText Header showing count of destination items.
|
||||
* @param moveAll If true, move all items; if false, move only selected.
|
||||
*/
|
||||
private void moveFlags(ListView fromListView, ListView toListView,
|
||||
TreeSet<Long> fromFlags, TreeSet<Long> toFlags,
|
||||
TextView fromCountText, TextView toCountText,
|
||||
boolean moveAll) {
|
||||
if (fromListView == null || toListView == null) return;
|
||||
|
||||
List<Long> flagsToMove = new ArrayList<>();
|
||||
FlagAdapter fromAdapter = (FlagAdapter) fromListView.getAdapter();
|
||||
|
||||
if (moveAll) {
|
||||
flagsToMove.addAll(fromFlags);
|
||||
} else {
|
||||
SparseBooleanArray checked = fromListView.getCheckedItemPositions();
|
||||
for (int i = 0, count = fromAdapter.getCount(); i < count; i++) {
|
||||
if (checked.get(i)) {
|
||||
String item = fromAdapter.getItem(i);
|
||||
if (item != null) {
|
||||
flagsToMove.add(Long.parseLong(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flagsToMove.isEmpty()) return;
|
||||
|
||||
for (Long flag : flagsToMove) {
|
||||
fromFlags.remove(flag);
|
||||
toFlags.add(flag);
|
||||
}
|
||||
|
||||
// Clear selections before refreshing.
|
||||
fromListView.clearChoices();
|
||||
toListView.clearChoices();
|
||||
|
||||
// Refresh both adapters.
|
||||
fromAdapter.refresh();
|
||||
((FlagAdapter) toListView.getAdapter()).refresh();
|
||||
|
||||
// Update headers.
|
||||
updateHeaderCount(fromCountText, fromAdapter);
|
||||
updateHeaderCount(toCountText, (FlagAdapter) toListView.getAdapter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves blocked flags to settings.
|
||||
*/
|
||||
private void saveFlags(TreeSet<Long> blockedFlags) {
|
||||
StringBuilder flagsString = new StringBuilder();
|
||||
for (Long flag : blockedFlags) {
|
||||
if (flagsString.length() > 0) {
|
||||
flagsString.append("\n");
|
||||
}
|
||||
flagsString.append(flag);
|
||||
}
|
||||
|
||||
BaseSettings.DISABLED_FEATURE_FLAGS.save(flagsString.toString());
|
||||
Utils.showToastShort(str("revanced_debug_feature_flags_manager_toast_saved"));
|
||||
Logger.printDebug(() -> "Feature flags saved. Blocked: " + blockedFlags.size());
|
||||
|
||||
AbstractPreferenceFragment.showRestartDialog(getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all blocked flags.
|
||||
*/
|
||||
private void resetFlags() {
|
||||
BaseSettings.DISABLED_FEATURE_FLAGS.save("");
|
||||
Utils.showToastShort(str("revanced_debug_feature_flags_manager_toast_reset"));
|
||||
|
||||
AbstractPreferenceFragment.showRestartDialog(getContext());
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import android.preference.Preference;
|
||||
import android.text.InputType;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
@@ -35,7 +34,7 @@ public class ImportExportPreference extends EditTextPreference implements Prefer
|
||||
editText.setAutofillHints((String) null);
|
||||
}
|
||||
editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 7); // Use a smaller font to reduce text wrap.
|
||||
editText.setTextSize(14);
|
||||
|
||||
setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.shared.requests.Route.Method.GET;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -41,6 +40,7 @@ import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.requests.Requester;
|
||||
import app.revanced.extension.shared.requests.Route;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
/**
|
||||
* Opens a dialog showing official links.
|
||||
@@ -222,11 +222,10 @@ class WebViewDialog extends Dialog {
|
||||
LinearLayout mainLayout = new LinearLayout(getContext());
|
||||
mainLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
final int padding = dipToPixels(10);
|
||||
mainLayout.setPadding(padding, padding, padding, padding);
|
||||
mainLayout.setPadding(Dim.dp10, Dim.dp10, Dim.dp10, Dim.dp10);
|
||||
// Set rounded rectangle background.
|
||||
ShapeDrawable mainBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(28), null, null));
|
||||
Dim.roundedCorners(28), null, null));
|
||||
mainBackground.getPaint().setColor(Utils.getDialogBackgroundColor());
|
||||
mainLayout.setBackground(mainBackground);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.os.Build;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
@@ -18,8 +17,11 @@ import android.widget.Toolbar;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseActivityHook;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
@SuppressWarnings({"deprecation", "NewApi"})
|
||||
public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
|
||||
@@ -88,14 +90,13 @@ public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
|
||||
toolbar.setNavigationIcon(getBackButtonDrawable());
|
||||
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
|
||||
|
||||
final int margin = Utils.dipToPixels(16);
|
||||
toolbar.setTitleMargin(margin, 0, margin, 0);
|
||||
toolbar.setTitleMargin(Dim.dp16, 0, Dim.dp16, 0);
|
||||
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar,
|
||||
true, TextView.class::isInstance);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
toolbarTextView.setTextSize(20);
|
||||
}
|
||||
|
||||
// Allow package-specific toolbar customization.
|
||||
@@ -134,8 +135,10 @@ public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
|
||||
*/
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
public static Drawable getBackButtonDrawable() {
|
||||
final int backButtonResource = Utils.getResourceIdentifierOrThrow(
|
||||
"revanced_settings_toolbar_arrow_left", "drawable");
|
||||
final int backButtonResource = Utils.getResourceIdentifierOrThrow(ResourceType.DRAWABLE,
|
||||
Utils.appIsUsingBoldIcons()
|
||||
? "revanced_settings_toolbar_arrow_left_bold"
|
||||
: "revanced_settings_toolbar_arrow_left");
|
||||
Drawable drawable = Utils.getContext().getResources().getDrawable(backButtonResource);
|
||||
customizeBackButtonDrawable(drawable);
|
||||
return drawable;
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
|
||||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
@@ -38,18 +39,18 @@ public abstract class BaseSearchResultItem {
|
||||
// Get the corresponding layout resource ID.
|
||||
public int getLayoutResourceId() {
|
||||
return switch (this) {
|
||||
case REGULAR, URL_LINK -> getResourceIdentifier("revanced_preference_search_result_regular");
|
||||
case SWITCH -> getResourceIdentifier("revanced_preference_search_result_switch");
|
||||
case LIST -> getResourceIdentifier("revanced_preference_search_result_list");
|
||||
case COLOR_PICKER -> getResourceIdentifier("revanced_preference_search_result_color");
|
||||
case GROUP_HEADER -> getResourceIdentifier("revanced_preference_search_result_group_header");
|
||||
case NO_RESULTS -> getResourceIdentifier("revanced_preference_search_no_result");
|
||||
case REGULAR, URL_LINK -> getResourceIdentifier("revanced_preference_search_result_regular");
|
||||
case SWITCH -> getResourceIdentifier("revanced_preference_search_result_switch");
|
||||
case LIST -> getResourceIdentifier("revanced_preference_search_result_list");
|
||||
case COLOR_PICKER -> getResourceIdentifier("revanced_preference_search_result_color");
|
||||
case GROUP_HEADER -> getResourceIdentifier("revanced_preference_search_result_group_header");
|
||||
case NO_RESULTS -> getResourceIdentifier("revanced_preference_search_no_result");
|
||||
};
|
||||
}
|
||||
|
||||
private static int getResourceIdentifier(String name) {
|
||||
// Placeholder for actual resource identifier retrieval.
|
||||
return Utils.getResourceIdentifierOrThrow(name, "layout");
|
||||
return Utils.getResourceIdentifierOrThrow(ResourceType.LAYOUT, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +76,7 @@ public abstract class BaseSearchResultItem {
|
||||
|
||||
// Shared method for highlighting text with search query.
|
||||
protected static CharSequence highlightSearchQuery(CharSequence text, Pattern queryPattern) {
|
||||
if (TextUtils.isEmpty(text)) return text;
|
||||
if (TextUtils.isEmpty(text) || queryPattern == null) return text;
|
||||
|
||||
final int adjustedColor = Utils.adjustColorBrightness(
|
||||
Utils.getAppBackgroundColor(), 0.95f, 1.20f);
|
||||
@@ -84,7 +85,10 @@ public abstract class BaseSearchResultItem {
|
||||
|
||||
Matcher matcher = queryPattern.matcher(text);
|
||||
while (matcher.find()) {
|
||||
spannable.setSpan(highlightSpan, matcher.start(), matcher.end(),
|
||||
int start = matcher.start();
|
||||
int end = matcher.end();
|
||||
if (start == end) continue; // Skip zero matches.
|
||||
spannable.setSpan(highlightSpan, start, end,
|
||||
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
@@ -224,10 +228,14 @@ public abstract class BaseSearchResultItem {
|
||||
return searchBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends normalized searchable text to the builder.
|
||||
* Uses full Unicode normalization for accurate search across all languages.
|
||||
*/
|
||||
private void appendText(StringBuilder builder, CharSequence text) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
if (builder.length() > 0) builder.append(" ");
|
||||
builder.append(Utils.removePunctuationToLowercase(text));
|
||||
builder.append(Utils.normalizeTextToLowercase(text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +280,7 @@ public abstract class BaseSearchResultItem {
|
||||
*/
|
||||
@Override
|
||||
boolean matchesQuery(String query) {
|
||||
return searchableText.contains(Utils.removePunctuationToLowercase(query));
|
||||
return searchableText.contains(Utils.normalizeTextToLowercase(query));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.shared.settings.search;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
|
||||
import static app.revanced.extension.shared.settings.search.BaseSearchViewController.DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ArgbEvaluator;
|
||||
@@ -33,6 +32,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
|
||||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
@@ -54,15 +54,15 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
|
||||
protected static final int PAUSE_BETWEEN_BLINKS = 100;
|
||||
|
||||
protected static final int ID_PREFERENCE_TITLE = getResourceIdentifierOrThrow(
|
||||
"preference_title", "id");
|
||||
ResourceType.ID, "preference_title");
|
||||
protected static final int ID_PREFERENCE_SUMMARY = getResourceIdentifierOrThrow(
|
||||
"preference_summary", "id");
|
||||
ResourceType.ID, "preference_summary");
|
||||
protected static final int ID_PREFERENCE_PATH = getResourceIdentifierOrThrow(
|
||||
"preference_path", "id");
|
||||
ResourceType.ID, "preference_path");
|
||||
protected static final int ID_PREFERENCE_SWITCH = getResourceIdentifierOrThrow(
|
||||
"preference_switch", "id");
|
||||
ResourceType.ID, "preference_switch");
|
||||
protected static final int ID_PREFERENCE_COLOR_DOT = getResourceIdentifierOrThrow(
|
||||
"preference_color_dot", "id");
|
||||
ResourceType.ID, "preference_color_dot");
|
||||
|
||||
protected static class RegularViewHolder {
|
||||
TextView titleView;
|
||||
@@ -275,7 +275,7 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
|
||||
holder.titleView.setText(item.highlightedTitle);
|
||||
holder.summaryView.setText(item.highlightedSummary);
|
||||
holder.summaryView.setVisibility(TextUtils.isEmpty(item.highlightedSummary) ? View.GONE : View.VISIBLE);
|
||||
holder.iconView.setImageResource(DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON);
|
||||
holder.iconView.setImageResource(BaseSearchViewController.getSearchIcon());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -484,7 +484,7 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < adapter.getCount(); i++) {
|
||||
for (int i = 0, count = adapter.getCount(); i < count; i++) {
|
||||
Object item = adapter.getItem(i);
|
||||
if (item == targetPreference) {
|
||||
return i;
|
||||
@@ -522,8 +522,8 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
|
||||
if (currentAnimator != null && currentAnimator.isRunning()) {
|
||||
currentAnimator.cancel();
|
||||
}
|
||||
int startColor = Utils.getAppBackgroundColor();
|
||||
int highlightColor = Utils.adjustColorBrightness(
|
||||
final int startColor = Utils.getAppBackgroundColor();
|
||||
final int highlightColor = Utils.adjustColorBrightness(
|
||||
startColor,
|
||||
Utils.isDarkModeEnabled() ? 1.25f : 0.8f
|
||||
);
|
||||
@@ -566,7 +566,7 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
|
||||
}
|
||||
|
||||
// First search on current level.
|
||||
for (int i = 0; i < group.getPreferenceCount(); i++) {
|
||||
for (int i = 0, count = group.getPreferenceCount(); i < count; i++) {
|
||||
Preference pref = group.getPreference(i);
|
||||
if (key.equals(pref.getKey())) {
|
||||
return pref;
|
||||
|
||||
@@ -13,8 +13,8 @@ import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@@ -38,6 +38,7 @@ import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
@@ -45,6 +46,7 @@ import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
|
||||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
import app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
/**
|
||||
* Abstract controller for managing the overlay search view in ReVanced settings.
|
||||
@@ -70,14 +72,29 @@ public abstract class BaseSearchViewController {
|
||||
|
||||
protected static final int MAX_SEARCH_RESULTS = 50; // Maximum number of search results displayed.
|
||||
|
||||
protected static final int ID_REVANCED_SEARCH_VIEW = getResourceIdentifierOrThrow("revanced_search_view", "id");
|
||||
protected static final int ID_REVANCED_SEARCH_VIEW_CONTAINER = getResourceIdentifierOrThrow("revanced_search_view_container", "id");
|
||||
protected static final int ID_ACTION_SEARCH = getResourceIdentifierOrThrow("action_search", "id");
|
||||
protected static final int ID_REVANCED_SETTINGS_FRAGMENTS = getResourceIdentifierOrThrow("revanced_settings_fragments", "id");
|
||||
public static final int DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON =
|
||||
getResourceIdentifierOrThrow("revanced_settings_search_icon", "drawable");
|
||||
protected static final int MENU_REVANCED_SEARCH_MENU =
|
||||
getResourceIdentifierOrThrow("revanced_search_menu", "menu");
|
||||
protected static final int ID_REVANCED_SEARCH_VIEW = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "revanced_search_view");
|
||||
protected static final int ID_REVANCED_SEARCH_VIEW_CONTAINER = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "revanced_search_view_container");
|
||||
protected static final int ID_ACTION_SEARCH = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "action_search");
|
||||
protected static final int ID_REVANCED_SETTINGS_FRAGMENTS = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "revanced_settings_fragments");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_search_icon");
|
||||
private static final int DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON_BOLD = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_search_icon_bold");
|
||||
protected static final int MENU_REVANCED_SEARCH_MENU = getResourceIdentifierOrThrow(
|
||||
ResourceType.MENU, "revanced_search_menu");
|
||||
|
||||
/**
|
||||
* @return The search icon, either bold or not bold, depending on the ReVanced UI setting.
|
||||
*/
|
||||
public static int getSearchIcon() {
|
||||
return Utils.appIsUsingBoldIcons()
|
||||
? DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON_BOLD
|
||||
: DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new BaseSearchViewController instance.
|
||||
@@ -112,7 +129,7 @@ public abstract class BaseSearchViewController {
|
||||
// Retrieve SearchView and container from XML.
|
||||
searchView = activity.findViewById(ID_REVANCED_SEARCH_VIEW);
|
||||
EditText searchEditText = searchView.findViewById(Utils.getResourceIdentifierOrThrow(
|
||||
"android:id/search_src_text", null));
|
||||
null, "android:id/search_src_text"));
|
||||
// Disable fullscreen keyboard mode.
|
||||
searchEditText.setImeOptions(searchEditText.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
|
||||
@@ -123,7 +140,7 @@ public abstract class BaseSearchViewController {
|
||||
searchView.setQueryHint(str("revanced_settings_search_hint"));
|
||||
|
||||
// Set text size.
|
||||
searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
|
||||
searchEditText.setTextSize(16);
|
||||
|
||||
// Set cursor color.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
@@ -149,7 +166,7 @@ public abstract class BaseSearchViewController {
|
||||
// Create cursor drawable.
|
||||
GradientDrawable cursorDrawable = new GradientDrawable();
|
||||
cursorDrawable.setShape(GradientDrawable.RECTANGLE);
|
||||
cursorDrawable.setSize(Utils.dipToPixels(2), -1); // Width: 2dp, Height: match text height.
|
||||
cursorDrawable.setSize(Dim.dp2, -1); // Width: 2dp, Height: match text height.
|
||||
cursorDrawable.setColor(cursorColor);
|
||||
|
||||
// Set cursor drawable.
|
||||
@@ -164,7 +181,7 @@ public abstract class BaseSearchViewController {
|
||||
overlayContainer = new FrameLayout(activity);
|
||||
overlayContainer.setVisibility(View.GONE);
|
||||
overlayContainer.setBackgroundColor(Utils.getAppBackgroundColor());
|
||||
overlayContainer.setElevation(Utils.dipToPixels(8));
|
||||
overlayContainer.setElevation(Dim.dp8);
|
||||
|
||||
// Container for search results.
|
||||
FrameLayout searchResultsContainer = new FrameLayout(activity);
|
||||
@@ -248,6 +265,10 @@ public abstract class BaseSearchViewController {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Set bold icon if needed.
|
||||
MenuItem search = toolbar.getMenu().findItem(ID_ACTION_SEARCH);
|
||||
search.setIcon(getSearchIcon());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -450,7 +471,7 @@ public abstract class BaseSearchViewController {
|
||||
|
||||
filteredSearchItems.clear();
|
||||
|
||||
String queryLower = Utils.removePunctuationToLowercase(query);
|
||||
String queryLower = Utils.normalizeTextToLowercase(query);
|
||||
Pattern queryPattern = Pattern.compile(Pattern.quote(queryLower), Pattern.CASE_INSENSITIVE);
|
||||
|
||||
// Clear highlighting only for items that were previously visible.
|
||||
@@ -524,7 +545,7 @@ public abstract class BaseSearchViewController {
|
||||
noResultsPreference.setTitle(str("revanced_settings_search_no_results_title", query));
|
||||
noResultsPreference.setSummary(str("revanced_settings_search_no_results_summary"));
|
||||
noResultsPreference.setSelectable(false);
|
||||
noResultsPreference.setIcon(DRAWABLE_REVANCED_SETTINGS_SEARCH_ICON);
|
||||
noResultsPreference.setIcon(getSearchIcon());
|
||||
filteredSearchItems.add(new BaseSearchResultItem.PreferenceSearchItem(noResultsPreference, "", Collections.emptyList()));
|
||||
}
|
||||
|
||||
@@ -669,7 +690,7 @@ public abstract class BaseSearchViewController {
|
||||
protected static GradientDrawable createBackgroundDrawable() {
|
||||
GradientDrawable background = new GradientDrawable();
|
||||
background.setShape(GradientDrawable.RECTANGLE);
|
||||
background.setCornerRadius(Utils.dipToPixels(28));
|
||||
background.setCornerRadius(Dim.dp28);
|
||||
background.setColor(getSearchViewBackground());
|
||||
return background;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.BulletPointPreference;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
|
||||
@@ -37,25 +39,35 @@ public class SearchHistoryManager {
|
||||
private static final int MAX_HISTORY_SIZE = 5; // Maximum history items stored.
|
||||
|
||||
private static final int ID_CLEAR_HISTORY_BUTTON = getResourceIdentifierOrThrow(
|
||||
"clear_history_button", "id");
|
||||
ResourceType.ID, "clear_history_button");
|
||||
private static final int ID_HISTORY_TEXT = getResourceIdentifierOrThrow(
|
||||
"history_text", "id");
|
||||
ResourceType.ID, "history_text");
|
||||
private static final int ID_HISTORY_ICON = getResourceIdentifierOrThrow(
|
||||
ResourceType.ID, "history_icon");
|
||||
private static final int ID_DELETE_ICON = getResourceIdentifierOrThrow(
|
||||
"delete_icon", "id");
|
||||
ResourceType.ID, "delete_icon");
|
||||
private static final int ID_EMPTY_HISTORY_TITLE = getResourceIdentifierOrThrow(
|
||||
"empty_history_title", "id");
|
||||
ResourceType.ID, "empty_history_title");
|
||||
private static final int ID_EMPTY_HISTORY_SUMMARY = getResourceIdentifierOrThrow(
|
||||
"empty_history_summary", "id");
|
||||
ResourceType.ID, "empty_history_summary");
|
||||
private static final int ID_SEARCH_HISTORY_HEADER = getResourceIdentifierOrThrow(
|
||||
"search_history_header", "id");
|
||||
ResourceType.ID, "search_history_header");
|
||||
private static final int ID_SEARCH_TIPS_SUMMARY = getResourceIdentifierOrThrow(
|
||||
"revanced_settings_search_tips_summary", "id");
|
||||
ResourceType.ID, "revanced_settings_search_tips_summary");
|
||||
private static final int LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_SCREEN = getResourceIdentifierOrThrow(
|
||||
"revanced_preference_search_history_screen", "layout");
|
||||
ResourceType.LAYOUT, "revanced_preference_search_history_screen");
|
||||
private static final int LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_ITEM = getResourceIdentifierOrThrow(
|
||||
"revanced_preference_search_history_item", "layout");
|
||||
ResourceType.LAYOUT, "revanced_preference_search_history_item");
|
||||
private static final int ID_SEARCH_HISTORY_LIST = getResourceIdentifierOrThrow(
|
||||
"search_history_list", "id");
|
||||
ResourceType.ID, "search_history_list");
|
||||
private static final int ID_SEARCH_REMOVE_ICON = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_search_remove");
|
||||
private static final int ID_SEARCH_REMOVE_ICON_BOLD = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_search_remove_bold");
|
||||
private static final int ID_SEARCH_ARROW_TIME_ICON = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_arrow_time");
|
||||
private static final int ID_SEARCH_ARROW_TIME_ICON_BOLD = getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, "revanced_settings_arrow_time_bold");
|
||||
|
||||
private final Deque<String> searchHistory;
|
||||
private final Activity activity;
|
||||
@@ -97,7 +109,8 @@ public class SearchHistoryManager {
|
||||
|
||||
// Inflate search history layout.
|
||||
LayoutInflater inflater = LayoutInflater.from(activity);
|
||||
View historyView = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_SCREEN, searchHistoryContainer, false);
|
||||
View historyView = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_SCREEN,
|
||||
searchHistoryContainer, false);
|
||||
searchHistoryContainer.addView(historyView, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
@@ -320,17 +333,29 @@ public class SearchHistoryManager {
|
||||
public void notifyDataSetChanged() {
|
||||
container.removeAllViews();
|
||||
for (String query : history) {
|
||||
View view = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_ITEM, container, false);
|
||||
|
||||
TextView historyText = view.findViewById(ID_HISTORY_TEXT);
|
||||
ImageView deleteIcon = view.findViewById(ID_DELETE_ICON);
|
||||
|
||||
historyText.setText(query);
|
||||
|
||||
View view = inflater.inflate(LAYOUT_REVANCED_PREFERENCE_SEARCH_HISTORY_ITEM,
|
||||
container, false);
|
||||
// Set click listener for main item (select query).
|
||||
view.setOnClickListener(v -> onSelectHistoryItemListener.onSelectHistoryItem(query));
|
||||
|
||||
// Set history icon.
|
||||
ImageView historyIcon = view.findViewById(ID_HISTORY_ICON);
|
||||
historyIcon.setImageResource(Utils.appIsUsingBoldIcons()
|
||||
? ID_SEARCH_ARROW_TIME_ICON_BOLD
|
||||
: ID_SEARCH_ARROW_TIME_ICON
|
||||
);
|
||||
|
||||
TextView historyText = view.findViewById(ID_HISTORY_TEXT);
|
||||
historyText.setText(query);
|
||||
|
||||
// Set click listener for delete icon.
|
||||
ImageView deleteIcon = view.findViewById(ID_DELETE_ICON);
|
||||
|
||||
deleteIcon.setImageResource(Utils.appIsUsingBoldIcons()
|
||||
? ID_SEARCH_REMOVE_ICON_BOLD
|
||||
: ID_SEARCH_REMOVE_ICON
|
||||
);
|
||||
|
||||
deleteIcon.setOnClickListener(v -> createAndShowDialog(
|
||||
query,
|
||||
str("revanced_settings_search_remove_message"),
|
||||
|
||||
@@ -54,6 +54,33 @@ public enum ClientType {
|
||||
ANDROID_VR_1_61_48.supportsMultiAudioTracks,
|
||||
"Android VR 1.43"
|
||||
),
|
||||
/**
|
||||
* Video not playable: Paid / Movie / Private / Age-restricted.
|
||||
* Note: The 'Authorization' key must be excluded from the header.
|
||||
*
|
||||
* According to TeamNewPipe in 2022, if the 'androidSdkVersion' field is missing,
|
||||
* the GVS did not return a valid response:
|
||||
* [NewPipe#8713 (comment)](https://github.com/TeamNewPipe/NewPipe/issues/8713#issuecomment-1207443550).
|
||||
*
|
||||
* According to the latest commit in yt-dlp, the GVS returns a valid response
|
||||
* even if the 'androidSdkVersion' field is missing:
|
||||
* [yt-dlp#14693](https://github.com/yt-dlp/yt-dlp/pull/14693).
|
||||
*
|
||||
* For some reason, PoToken is not required.
|
||||
*/
|
||||
ANDROID_NO_SDK(
|
||||
3,
|
||||
"ANDROID",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
Build.VERSION.RELEASE,
|
||||
"20.05.46",
|
||||
"com.google.android.youtube/20.05.46 (Linux; U; Android " + Build.VERSION.RELEASE + ") gzip",
|
||||
false,
|
||||
true,
|
||||
"Android No SDK"
|
||||
),
|
||||
/**
|
||||
* Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
|
||||
* <a href="https://dumps.tadiphone.dev/dumps/google/barbet">Google Pixel 9 Pro Fold</a>
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SpoofVideoStreamsPatch {
|
||||
public static boolean spoofingToClientWithNoMultiAudioStreams() {
|
||||
return isPatchIncluded()
|
||||
&& SPOOF_STREAMING_DATA
|
||||
&& preferredClient != ClientType.IPADOS;
|
||||
&& !preferredClient.supportsMultiAudioTracks;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -83,22 +82,15 @@ public class StreamingDataRequest {
|
||||
*/
|
||||
private static final int MAX_MILLISECONDS_TO_WAIT_FOR_FETCH = 20 * 1000;
|
||||
|
||||
/**
|
||||
* Cache limit must be greater than the maximum number of videos open at once,
|
||||
* which theoretically is more than 4 (3 Shorts + one regular minimized video).
|
||||
* But instead use a much larger value, to handle if a video viewed a while ago
|
||||
* is somehow still referenced. Each stream is a small array of Strings
|
||||
* so memory usage is not a concern.
|
||||
*/
|
||||
private static final Map<String, StreamingDataRequest> cache = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>(100) {
|
||||
/**
|
||||
* Cache limit must be greater than the maximum number of videos open at once,
|
||||
* which theoretically is more than 4 (3 Shorts + one regular minimized video).
|
||||
* But instead use a much larger value, to handle if a video viewed a while ago
|
||||
* is somehow still referenced. Each stream is a small array of Strings
|
||||
* so memory usage is not a concern.
|
||||
*/
|
||||
private static final int CACHE_LIMIT = 50;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry eldest) {
|
||||
return size() > CACHE_LIMIT; // Evict the oldest entry if over the cache limit.
|
||||
}
|
||||
});
|
||||
Utils.createSizeRestrictedMap(50));
|
||||
|
||||
/**
|
||||
* Strings found in the response if the video is a livestream.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.shared.ui;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.adjustColorBrightness;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.shared.Utils.getAppBackgroundColor;
|
||||
import static app.revanced.extension.shared.Utils.isDarkModeEnabled;
|
||||
import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.DISABLED_ALPHA;
|
||||
@@ -13,7 +12,7 @@ import android.view.View;
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
public class ColorDot {
|
||||
private static final int STROKE_WIDTH = dipToPixels(1.5f); // Stroke width in dp.
|
||||
private static final int STROKE_WIDTH = Dim.dp(1.5f);
|
||||
|
||||
/**
|
||||
* Creates a circular drawable with a main fill and a stroke.
|
||||
@@ -55,7 +54,7 @@ public class ColorDot {
|
||||
targetView.setAlpha(enabled ? 1.0f : DISABLED_ALPHA);
|
||||
if (!isDarkModeEnabled()) {
|
||||
targetView.setClipToOutline(true);
|
||||
targetView.setElevation(dipToPixels(2));
|
||||
targetView.setElevation(Dim.dp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.shared.ui;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
@@ -37,7 +35,6 @@ public class CustomDialog {
|
||||
private final Context context;
|
||||
private final Dialog dialog;
|
||||
private final LinearLayout mainLayout;
|
||||
private final int dip4, dip8, dip16, dip24, dip36;
|
||||
|
||||
/**
|
||||
* Creates a custom dialog with a styled layout, including a title, message, buttons, and an optional EditText.
|
||||
@@ -93,13 +90,6 @@ public class CustomDialog {
|
||||
this.dialog = new Dialog(context);
|
||||
this.dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // Remove default title bar.
|
||||
|
||||
// Preset size constants.
|
||||
dip4 = dipToPixels(4);
|
||||
dip8 = dipToPixels(8);
|
||||
dip16 = dipToPixels(16);
|
||||
dip24 = dipToPixels(24);
|
||||
dip36 = dipToPixels(36);
|
||||
|
||||
// Create main layout.
|
||||
mainLayout = createMainLayout();
|
||||
addTitle(title);
|
||||
@@ -122,11 +112,11 @@ public class CustomDialog {
|
||||
private LinearLayout createMainLayout() {
|
||||
LinearLayout layout = new LinearLayout(context);
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
layout.setPadding(dip24, dip16, dip24, dip24);
|
||||
layout.setPadding(Dim.dp24, Dim.dp16, Dim.dp24, Dim.dp24);
|
||||
|
||||
// Set rounded rectangle background.
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(28), null, null));
|
||||
Dim.roundedCorners(28), null, null));
|
||||
// Dialog background.
|
||||
background.getPaint().setColor(Utils.getDialogBackgroundColor());
|
||||
layout.setBackground(background);
|
||||
@@ -152,7 +142,7 @@ public class CustomDialog {
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.setMargins(0, 0, 0, dip16);
|
||||
params.setMargins(0, 0, 0, Dim.dp16);
|
||||
titleView.setLayoutParams(params);
|
||||
|
||||
mainLayout.addView(titleView);
|
||||
@@ -180,9 +170,9 @@ public class CustomDialog {
|
||||
// EditText (if provided).
|
||||
if (editText != null) {
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(10), null, null));
|
||||
Dim.roundedCorners(10), null, null));
|
||||
background.getPaint().setColor(Utils.getEditTextBackground());
|
||||
scrollView.setPadding(dip8, dip8, dip8, dip8);
|
||||
scrollView.setPadding(Dim.dp8, Dim.dp8, Dim.dp8, Dim.dp8);
|
||||
scrollView.setBackground(background);
|
||||
scrollView.setClipToOutline(true);
|
||||
|
||||
@@ -241,7 +231,7 @@ public class CustomDialog {
|
||||
LinearLayout.LayoutParams buttonContainerParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
buttonContainerParams.setMargins(0, dip16, 0, 0);
|
||||
buttonContainerParams.setMargins(0, Dim.dp16, 0, 0);
|
||||
buttonContainer.setLayoutParams(buttonContainerParams);
|
||||
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
@@ -289,12 +279,12 @@ public class CustomDialog {
|
||||
button.setEllipsize(TextUtils.TruncateAt.END);
|
||||
button.setGravity(Gravity.CENTER);
|
||||
// Set internal padding.
|
||||
button.setPadding(dip16, 0, dip16, 0);
|
||||
button.setPadding(Dim.dp16, 0, Dim.dp16, 0);
|
||||
|
||||
// Background color for OK button (inversion).
|
||||
// Background color for Cancel or Neutral buttons.
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(20), null, null));
|
||||
Dim.roundedCorners(20), null, null));
|
||||
background.getPaint().setColor(isOkButton
|
||||
? Utils.getOkButtonBackgroundColor()
|
||||
: Utils.getCancelOrNeutralButtonBackgroundColor());
|
||||
@@ -331,20 +321,19 @@ public class CustomDialog {
|
||||
if (buttons.isEmpty()) return;
|
||||
|
||||
// Check if buttons fit in one row.
|
||||
int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
|
||||
int totalWidth = 0;
|
||||
for (Integer width : buttonWidths) {
|
||||
totalWidth += width;
|
||||
}
|
||||
if (buttonWidths.size() > 1) {
|
||||
// Add margins for gaps.
|
||||
totalWidth += (buttonWidths.size() - 1) * dip8;
|
||||
totalWidth += (buttonWidths.size() - 1) * Dim.dp8;
|
||||
}
|
||||
|
||||
// Single button: stretch to full width.
|
||||
if (buttons.size() == 1) {
|
||||
layoutSingleButton(buttonContainer, buttons.get(0));
|
||||
} else if (totalWidth <= screenWidth * 0.8) {
|
||||
} else if (totalWidth <= Dim.pctWidth(80)) {
|
||||
// Single row: Neutral, Cancel, OK.
|
||||
layoutButtonsInRow(buttonContainer, buttons, buttonWidths);
|
||||
} else {
|
||||
@@ -369,7 +358,7 @@ public class CustomDialog {
|
||||
|
||||
button.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
dip36));
|
||||
Dim.dp36));
|
||||
singleContainer.addView(button);
|
||||
buttonContainer.addView(singleContainer);
|
||||
}
|
||||
@@ -405,17 +394,17 @@ public class CustomDialog {
|
||||
if (parent != null) parent.removeView(button);
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
0, dip36, buttonWidths.get(i));
|
||||
0, Dim.dp36, buttonWidths.get(i));
|
||||
|
||||
// Set margins based on button type and combination.
|
||||
if (buttons.size() == 2) {
|
||||
// Neutral + OK or Cancel + OK.
|
||||
params.setMargins(i == 0 ? 0 : dip4, 0, i == 0 ? dip4 : 0, 0);
|
||||
params.setMargins(i == 0 ? 0 : Dim.dp4, 0, i == 0 ? Dim.dp4 : 0, 0);
|
||||
} else if (buttons.size() == 3) {
|
||||
// Neutral.
|
||||
// Cancel.
|
||||
// OK.
|
||||
params.setMargins(i == 0 ? 0 : dip4, 0, i == 2 ? 0 : dip4, 0);
|
||||
params.setMargins(i == 0 ? 0 : Dim.dp4, 0, i == 2 ? 0 : Dim.dp4, 0);
|
||||
}
|
||||
|
||||
button.setLayoutParams(params);
|
||||
@@ -447,14 +436,14 @@ public class CustomDialog {
|
||||
singleContainer.setGravity(Gravity.CENTER);
|
||||
singleContainer.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
dip36));
|
||||
Dim.dp36));
|
||||
|
||||
ViewGroup parent = (ViewGroup) button.getParent();
|
||||
if (parent != null) parent.removeView(button);
|
||||
|
||||
button.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
dip36));
|
||||
Dim.dp36));
|
||||
singleContainer.addView(button);
|
||||
buttonContainer.addView(singleContainer);
|
||||
|
||||
@@ -463,7 +452,7 @@ public class CustomDialog {
|
||||
View spacer = new View(context);
|
||||
LinearLayout.LayoutParams spacerParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
dip8);
|
||||
Dim.dp8);
|
||||
spacer.setLayoutParams(spacerParams);
|
||||
buttonContainer.addView(spacer);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package app.revanced.extension.shared.ui;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
|
||||
/**
|
||||
* Utility class for converting design units (dp) and screen percentages to pixels.
|
||||
*/
|
||||
public final class Dim {
|
||||
private Dim() {} // Prevent instantiation.
|
||||
|
||||
private static final DisplayMetrics METRICS = Resources.getSystem().getDisplayMetrics();
|
||||
public static final int SCREEN_WIDTH = METRICS.widthPixels;
|
||||
public static final int SCREEN_HEIGHT = METRICS.heightPixels;
|
||||
|
||||
// DP constants (density-independent pixels).
|
||||
public static final int dp1 = dp(1);
|
||||
public static final int dp2 = dp(2);
|
||||
public static final int dp4 = dp(4);
|
||||
public static final int dp6 = dp(6);
|
||||
public static final int dp7 = dp(7);
|
||||
public static final int dp8 = dp(8);
|
||||
public static final int dp10 = dp(10);
|
||||
public static final int dp12 = dp(12);
|
||||
public static final int dp16 = dp(16);
|
||||
public static final int dp20 = dp(20);
|
||||
public static final int dp24 = dp(24);
|
||||
public static final int dp28 = dp(28);
|
||||
public static final int dp32 = dp(32);
|
||||
public static final int dp36 = dp(36);
|
||||
public static final int dp40 = dp(40);
|
||||
public static final int dp48 = dp(48);
|
||||
|
||||
/**
|
||||
* Converts dp (density-independent pixels) to actual device pixels.
|
||||
* Uses Android's official TypedValue.applyDimension() for accurate rounding.
|
||||
*
|
||||
* @param dp The dp value to convert (supports float, e.g. 1.2f).
|
||||
* @return The equivalent pixel value as int.
|
||||
*/
|
||||
public static int dp(float dp) {
|
||||
return (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, dp, METRICS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen height to pixels.
|
||||
*
|
||||
* @param percent The percentage (0–100).
|
||||
* @return The pixel value corresponding to the percentage of screen height.
|
||||
*/
|
||||
public static int pctHeight(int percent) {
|
||||
return (SCREEN_HEIGHT * percent) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen width to pixels.
|
||||
*
|
||||
* @param percent The percentage (0–100).
|
||||
* @return The pixel value corresponding to the percentage of screen width.
|
||||
*/
|
||||
public static int pctWidth(int percent) {
|
||||
return (SCREEN_WIDTH * percent) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen's portrait width (min side) to pixels.
|
||||
*
|
||||
* @param percent The percentage (0–100).
|
||||
* @return The pixel value.
|
||||
*/
|
||||
public static int pctPortraitWidth(int percent) {
|
||||
final int portraitWidth = Math.min(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
return (int) (portraitWidth * (percent / 100.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of corner radii for a rounded rectangle.
|
||||
* All corners use the same radius.
|
||||
*
|
||||
* @param dp radius in density-independent pixels
|
||||
* @return array of 8 floats: [top-left-x, top-left-y, top-right-x, top-right-y, ...]
|
||||
*/
|
||||
public static float[] roundedCorners(float dp) {
|
||||
final float r = dp(dp);
|
||||
return new float[]{r, r, r, r, r, r, r, r};
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.shared.ui;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
@@ -63,9 +61,8 @@ public class SheetBottomDialog {
|
||||
|
||||
// Add top spacer.
|
||||
View spacer = new View(context);
|
||||
final int dip40 = dipToPixels(40);
|
||||
LinearLayout.LayoutParams spacerParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, dip40);
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, Dim.dp40);
|
||||
spacer.setLayoutParams(spacerParams);
|
||||
spacer.setClickable(true);
|
||||
dragContainer.addView(spacer);
|
||||
@@ -105,20 +102,15 @@ public class SheetBottomDialog {
|
||||
* @return A configured {@link DraggableLinearLayout} with a handle bar and styled background.
|
||||
*/
|
||||
public static DraggableLinearLayout createMainLayout(@NonNull Context context, @Nullable Integer backgroundColor) {
|
||||
// Preset size constants.
|
||||
final int dip4 = dipToPixels(4); // Handle bar height.
|
||||
final int dip8 = dipToPixels(8); // Dialog padding.
|
||||
final int dip40 = dipToPixels(40); // Handle bar width.
|
||||
|
||||
DraggableLinearLayout mainLayout = new DraggableLinearLayout(context);
|
||||
mainLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.setMargins(dip8, 0, dip8, dip8);
|
||||
layoutParams.setMargins(Dim.dp8, 0, Dim.dp8, Dim.dp8);
|
||||
mainLayout.setLayoutParams(layoutParams);
|
||||
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(12), null, null));
|
||||
Dim.roundedCorners(12), null, null));
|
||||
int color = (backgroundColor != null) ? backgroundColor : Utils.getDialogBackgroundColor();
|
||||
background.getPaint().setColor(color);
|
||||
mainLayout.setBackground(background);
|
||||
@@ -127,14 +119,14 @@ public class SheetBottomDialog {
|
||||
LinearLayout handleContainer = new LinearLayout(context);
|
||||
LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
containerParams.setMargins(0, dip8, 0, 0);
|
||||
containerParams.setMargins(0, Dim.dp8, 0, 0);
|
||||
handleContainer.setLayoutParams(containerParams);
|
||||
handleContainer.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
||||
View handleBar = new View(context);
|
||||
ShapeDrawable handleBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(4), null, null));
|
||||
Dim.roundedCorners(4), null, null));
|
||||
handleBackground.getPaint().setColor(Utils.adjustColorBrightness(color, 0.9f, 1.25f));
|
||||
LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(dip40, dip4);
|
||||
LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(Dim.dp40, Dim.dp4);
|
||||
handleBar.setLayoutParams(handleParams);
|
||||
handleBar.setBackground(handleBackground);
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package app.revanced.extension.spotify.layout.hide.createbutton;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.spotify.shared.ComponentFilters.ComponentFilter;
|
||||
import app.revanced.extension.spotify.shared.ComponentFilters.ResourceIdComponentFilter;
|
||||
import app.revanced.extension.spotify.shared.ComponentFilters.StringComponentFilter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@SuppressWarnings("unused")
|
||||
public final class HideCreateButtonPatch {
|
||||
|
||||
@@ -15,7 +17,7 @@ public final class HideCreateButtonPatch {
|
||||
* The main approach used is matching the resource id for the Create button title.
|
||||
*/
|
||||
private static final List<ComponentFilter> CREATE_BUTTON_COMPONENT_FILTERS = List.of(
|
||||
new ResourceIdComponentFilter("navigationbar_musicappitems_create_title", "string"),
|
||||
new ResourceIdComponentFilter(ResourceType.STRING, "navigationbar_musicappitems_create_title"),
|
||||
// Temporary fallback and fix for APKs merged with AntiSplit-M not having resources properly encoded,
|
||||
// and thus getting the resource identifier for the Create button title always return 0.
|
||||
// FIXME: Remove this once the above issue is no longer relevant.
|
||||
@@ -27,7 +29,7 @@ public final class HideCreateButtonPatch {
|
||||
* Used in older versions of the app.
|
||||
*/
|
||||
private static final ResourceIdComponentFilter OLD_CREATE_BUTTON_COMPONENT_FILTER =
|
||||
new ResourceIdComponentFilter("bottom_navigation_bar_create_tab_title", "string");
|
||||
new ResourceIdComponentFilter(ResourceType.STRING, "bottom_navigation_bar_create_tab_title");
|
||||
|
||||
/**
|
||||
* Injection point. This method is called on every navigation bar item to check whether it is the Create button.
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.extension.spotify.shared;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
public final class ComponentFilters {
|
||||
@@ -19,21 +20,26 @@ public final class ComponentFilters {
|
||||
public static final class ResourceIdComponentFilter implements ComponentFilter {
|
||||
|
||||
public final String resourceName;
|
||||
public final String resourceType;
|
||||
public final ResourceType resourceType;
|
||||
// Android resources are always positive, so -1 is a valid sentinel value to indicate it has not been loaded.
|
||||
// 0 is returned when a resource has not been found.
|
||||
private int resourceId = -1;
|
||||
@Nullable
|
||||
private String stringfiedResourceId;
|
||||
|
||||
@Deprecated
|
||||
public ResourceIdComponentFilter(String resourceName, String resourceType) {
|
||||
this(ResourceType.valueOf(resourceType), resourceName);
|
||||
}
|
||||
|
||||
public ResourceIdComponentFilter(ResourceType resourceType, String resourceName) {
|
||||
this.resourceName = resourceName;
|
||||
this.resourceType = resourceType;
|
||||
}
|
||||
|
||||
public int getResourceId() {
|
||||
if (resourceId == -1) {
|
||||
resourceId = Utils.getResourceIdentifier(resourceName, resourceType);
|
||||
resourceId = Utils.getResourceIdentifier(resourceType, resourceName);
|
||||
}
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package app.revanced.extension.twitch;
|
||||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
|
||||
public class Utils {
|
||||
|
||||
/* Called from SettingsPatch smali */
|
||||
public static int getStringId(String name) {
|
||||
return app.revanced.extension.shared.Utils.getResourceIdentifier(name, "string");
|
||||
return app.revanced.extension.shared.Utils.getResourceIdentifier(
|
||||
ResourceType.STRING, name);
|
||||
}
|
||||
|
||||
/* Called from SettingsPatch smali */
|
||||
public static int getDrawableId(String name) {
|
||||
return app.revanced.extension.shared.Utils.getResourceIdentifier(name, "drawable");
|
||||
return app.revanced.extension.shared.Utils.getResourceIdentifier(
|
||||
ResourceType.DRAWABLE, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,21 @@ import static app.revanced.extension.twitch.Utils.getStringId;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.twitch.settings.preference.TwitchPreferenceFragment;
|
||||
|
||||
import tv.twitch.android.feature.settings.menu.SettingsMenuGroup;
|
||||
import tv.twitch.android.settings.SettingsActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Hooks AppCompatActivity to inject a custom {@link TwitchPreferenceFragment}.
|
||||
*/
|
||||
@@ -108,7 +110,7 @@ public class TwitchActivityHook {
|
||||
|
||||
base.getFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(Utils.getResourceIdentifier("fragment_container", "id"), fragment)
|
||||
.replace(Utils.getResourceIdentifier(ResourceType.ID, "fragment_container"), fragment)
|
||||
.commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -528,14 +528,8 @@ public final class AlternativeThumbnailsPatch {
|
||||
* Cache used to verify if an alternative thumbnails exists for a given video id.
|
||||
*/
|
||||
@GuardedBy("itself")
|
||||
private static final Map<String, VerifiedQualities> altVideoIdLookup = new LinkedHashMap<>(100) {
|
||||
private static final int CACHE_LIMIT = 1000;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry eldest) {
|
||||
return size() > CACHE_LIMIT; // Evict the oldest entry if over the cache limit.
|
||||
}
|
||||
};
|
||||
private static final Map<String, VerifiedQualities> altVideoIdLookup =
|
||||
Utils.createSizeRestrictedMap(1000);
|
||||
|
||||
private static VerifiedQualities getVerifiedQualities(@NonNull String videoId, boolean returnNullIfDoesNotExist) {
|
||||
synchronized (altVideoIdLookup) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -50,7 +51,7 @@ public class ChangeHeaderPatch {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int identifier = Utils.getResourceIdentifier(attributeName, "attr");
|
||||
final int identifier = Utils.getResourceIdentifier(ResourceType.ATTR, attributeName);
|
||||
if (identifier == 0) {
|
||||
// Should never happen.
|
||||
Logger.printException(() -> "Could not find attribute: " + drawableName);
|
||||
@@ -71,7 +72,7 @@ public class ChangeHeaderPatch {
|
||||
? "_dark"
|
||||
: "_light");
|
||||
|
||||
final int identifier = Utils.getResourceIdentifier(drawableFullName, "drawable");
|
||||
final int identifier = Utils.getResourceIdentifier(ResourceType.DRAWABLE, drawableFullName);
|
||||
if (identifier != 0) {
|
||||
return Utils.getContext().getDrawable(identifier);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public final class DownloadsPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void activityCreated(Activity mainActivity) {
|
||||
public static void setMainActivity(Activity mainActivity) {
|
||||
activityRef = new WeakReference<>(mainActivity);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class FixContentProviderPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void removeNullMapEntries(Map<?, ?> map) {
|
||||
map.entrySet().removeIf(entry -> {
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
Logger.printDebug(() -> "Removing content provider key with null value: " + entry.getKey());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -29,6 +30,15 @@ public final class HidePlayerOverlayButtonsPatch {
|
||||
return Settings.HIDE_CAST_BUTTON.get() ? View.GONE : original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getCastButtonOverrideV2(boolean original) {
|
||||
if (Settings.HIDE_CAST_BUTTON.get()) return false;
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@@ -40,10 +50,10 @@ public final class HidePlayerOverlayButtonsPatch {
|
||||
= Settings.HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS.get();
|
||||
|
||||
private static final int PLAYER_CONTROL_PREVIOUS_BUTTON_TOUCH_AREA_ID = getResourceIdentifierOrThrow(
|
||||
"player_control_previous_button_touch_area", "id");
|
||||
ResourceType.ID, "player_control_previous_button_touch_area");
|
||||
|
||||
private static final int PLAYER_CONTROL_NEXT_BUTTON_TOUCH_AREA_ID = getResourceIdentifierOrThrow(
|
||||
"player_control_next_button_touch_area", "id");
|
||||
ResourceType.ID, "player_control_next_button_touch_area");
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
|
||||
@@ -4,7 +4,17 @@ import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideSeekbarPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean hideSeekbar() {
|
||||
return Settings.HIDE_SEEKBAR.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean useFullscreenLargeSeekbar(boolean original) {
|
||||
return Settings.FULLSCREEN_LARGE_SEEKBAR.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -115,7 +116,7 @@ public final class MiniplayerPatch {
|
||||
* Resource is not present in older targets, and this field will be zero.
|
||||
*/
|
||||
private static final int MODERN_OVERLAY_SUBTITLE_TEXT
|
||||
= Utils.getResourceIdentifier("modern_miniplayer_subtitle_text", "id");
|
||||
= Utils.getResourceIdentifier(ResourceType.ID, "modern_miniplayer_subtitle_text");
|
||||
|
||||
private static final MiniplayerType CURRENT_TYPE = Settings.MINIPLAYER_TYPE.get();
|
||||
|
||||
@@ -378,6 +379,19 @@ public final class MiniplayerPatch {
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean allowBoldIcons(boolean original) {
|
||||
if (CURRENT_TYPE == MINIMAL) {
|
||||
// Minimal player does not have the correct pause/play icon (it's too large).
|
||||
// Use the non bold icons instead.
|
||||
return false;
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
|
||||
@@ -5,12 +5,11 @@ import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButt
|
||||
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.widget.TextView;
|
||||
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -30,13 +29,13 @@ public final class NavigationButtonsPatch {
|
||||
private static final boolean SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON
|
||||
= Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get();
|
||||
|
||||
private static final Boolean DISABLE_TRANSLUCENT_STATUS_BAR
|
||||
private static final boolean DISABLE_TRANSLUCENT_STATUS_BAR
|
||||
= Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get();
|
||||
|
||||
private static final Boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT
|
||||
private static final boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT
|
||||
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT.get();
|
||||
|
||||
private static final Boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
|
||||
private static final boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
|
||||
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK.get();
|
||||
|
||||
/**
|
||||
@@ -62,6 +61,13 @@ public final class NavigationButtonsPatch {
|
||||
hideViewUnderCondition(Settings.HIDE_NAVIGATION_BUTTON_LABELS, navigationLabelsView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean useAnimatedNavigationButtons(boolean original) {
|
||||
return Settings.NAVIGATION_BAR_ANIMATIONS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
|
||||
@@ -20,15 +20,6 @@ public class OpenShortsInRegularPlayerPatch {
|
||||
REGULAR_PLAYER_FULLSCREEN
|
||||
}
|
||||
|
||||
static {
|
||||
if (!VersionCheckPatch.IS_19_46_OR_GREATER
|
||||
&& Settings.SHORTS_PLAYER_TYPE.get() == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN) {
|
||||
// User imported newer settings to an older app target.
|
||||
Logger.printInfo(() -> "Resetting " + Settings.SHORTS_PLAYER_TYPE);
|
||||
Settings.SHORTS_PLAYER_TYPE.resetToDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private static WeakReference<Activity> mainActivityRef = new WeakReference<>(null);
|
||||
|
||||
private static volatile boolean overrideBackPressToExit;
|
||||
|
||||
@@ -24,18 +24,20 @@ public class OpenVideosFullscreenHookPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Returns negated value.
|
||||
*/
|
||||
public static boolean openVideoFullscreenPortrait(boolean original) {
|
||||
public static boolean doNotOpenVideoFullscreenPortrait(boolean original) {
|
||||
Boolean openFullscreen = openNextVideoFullscreen;
|
||||
if (openFullscreen != null) {
|
||||
openNextVideoFullscreen = null;
|
||||
return openFullscreen;
|
||||
return !openFullscreen;
|
||||
}
|
||||
|
||||
if (!isFullScreenPatchIncluded()) {
|
||||
return original;
|
||||
}
|
||||
|
||||
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
||||
return !Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class PlayerControlsPatch {
|
||||
|
||||
Logger.printDebug(() -> "fullscreen button visibility: "
|
||||
+ (visibility == View.VISIBLE ? "VISIBLE" :
|
||||
visibility == View.GONE ? "GONE" : "INVISIBLE"));
|
||||
visibility == View.GONE ? "GONE" : "INVISIBLE"));
|
||||
|
||||
fullscreenButtonVisibilityChanged(visibility == View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/** @noinspection unused*/
|
||||
@SuppressWarnings("unused")
|
||||
public class RemoveViewerDiscretionDialogPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void confirmDialog(AlertDialog dialog) {
|
||||
if (!Settings.REMOVE_VIEWER_DISCRETION_DIALOG.get()) {
|
||||
// Since the patch replaces the AlertDialog#show() method, we need to call the original method here.
|
||||
dialog.show();
|
||||
if (Settings.REMOVE_VIEWER_DISCRETION_DIALOG.get()) {
|
||||
Logger.printDebug(() -> "Clicking alert dialog dismiss button");
|
||||
|
||||
final var button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
button.setSoundEffectsEnabled(false);
|
||||
button.performClick();
|
||||
return;
|
||||
}
|
||||
|
||||
final var button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
button.setSoundEffectsEnabled(false);
|
||||
button.performClick();
|
||||
// Since the patch replaces the AlertDialog#show() method, we need to call the original method here.
|
||||
Logger.printDebug(() -> "Showing alert dialog");
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,11 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilter;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -131,6 +133,10 @@ public class ReturnYouTubeDislikePatch {
|
||||
|
||||
String conversionContextString = conversionContext.toString();
|
||||
|
||||
if (Settings.RYD_ENABLED.get()) { // FIXME: Remove this.
|
||||
Logger.printDebug(() -> "RYD conversion context: " + conversionContext);
|
||||
}
|
||||
|
||||
if (isRollingNumber && !conversionContextString.contains("video_action_bar.e")) {
|
||||
return original;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -78,7 +76,7 @@ public class ShortsAutoplayPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static Enum<?> changeShortsRepeatBehavior(@Nullable Enum<?> original) {
|
||||
public static Enum<?> changeShortsRepeatBehavior(Enum<?> original) {
|
||||
try {
|
||||
final boolean autoplay;
|
||||
|
||||
@@ -95,19 +93,19 @@ public class ShortsAutoplayPatch {
|
||||
autoplay = Settings.SHORTS_AUTOPLAY.get();
|
||||
}
|
||||
|
||||
final ShortsLoopBehavior behavior = autoplay
|
||||
Enum<?> overrideBehavior = (autoplay
|
||||
? ShortsLoopBehavior.SINGLE_PLAY
|
||||
: ShortsLoopBehavior.REPEAT;
|
||||
: ShortsLoopBehavior.REPEAT).ytEnumValue;
|
||||
|
||||
if (behavior.ytEnumValue != null) {
|
||||
if (overrideBehavior != null) {
|
||||
Logger.printDebug(() -> {
|
||||
String name = (original == null ? "unknown (null)" : original.name());
|
||||
return behavior == original
|
||||
return overrideBehavior == original
|
||||
? "Behavior setting is same as original. Using original: " + name
|
||||
: "Changing Shorts repeat behavior from: " + name + " to: " + behavior.name();
|
||||
: "Changing Shorts repeat behavior from: " + name + " to: " + overrideBehavior.name();
|
||||
});
|
||||
|
||||
return behavior.ytEnumValue;
|
||||
return overrideBehavior;
|
||||
}
|
||||
|
||||
if (original == null) {
|
||||
@@ -118,13 +116,12 @@ public class ShortsAutoplayPatch {
|
||||
return unknown;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "changeShortsRepeatBehavior failure", ex);
|
||||
Logger.printException(() -> "changeShortsRepeatState failure", ex);
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
|
||||
@@ -19,5 +19,12 @@ public class VersionCheckPatch {
|
||||
public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_34_OR_GREATER = isVersionOrGreater("19.34.00");
|
||||
public static final boolean IS_19_46_OR_GREATER = isVersionOrGreater("19.46.00");
|
||||
|
||||
public static final boolean IS_20_21_OR_GREATER = isVersionOrGreater("20.21.00");
|
||||
|
||||
public static final boolean IS_20_22_OR_GREATER = isVersionOrGreater("20.22.00");
|
||||
|
||||
public static final boolean IS_20_31_OR_GREATER = isVersionOrGreater("20.31.00");
|
||||
|
||||
public static final boolean IS_20_37_OR_GREATER = isVersionOrGreater("20.37.00");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.view.View;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -31,7 +32,7 @@ public final class WideSearchbarPatch {
|
||||
final int paddingRight = searchBarView.getPaddingRight();
|
||||
final int paddingTop = searchBarView.getPaddingTop();
|
||||
final int paddingBottom = searchBarView.getPaddingBottom();
|
||||
final int paddingStart = Utils.dipToPixels(8);
|
||||
final int paddingStart = Dim.dp8;
|
||||
|
||||
if (Utils.isRightToLeftLocale()) {
|
||||
searchBarView.setPadding(paddingLeft, paddingTop, paddingStart, paddingBottom);
|
||||
|
||||
@@ -2,7 +2,6 @@ package app.revanced.extension.youtube.patches.announcements;
|
||||
|
||||
import static android.text.Html.FROM_HTML_MODE_COMPACT;
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENTS;
|
||||
import static app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENT_IDS;
|
||||
|
||||
@@ -24,6 +23,7 @@ import java.time.LocalDateTime;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.requests.Requester;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -148,7 +148,7 @@ public final class AnnouncementsPatch {
|
||||
if (child instanceof TextView childTextView && finalTitle.equals(childTextView.getText().toString())) {
|
||||
childTextView.setCompoundDrawablesWithIntrinsicBounds(
|
||||
finalLevel.icon, 0, 0, 0);
|
||||
childTextView.setCompoundDrawablePadding(dipToPixels(8));
|
||||
childTextView.setCompoundDrawablePadding(Dim.dp8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -38,7 +39,6 @@ final class ButtonsFilter extends Filter {
|
||||
|
||||
addPathCallbacks(
|
||||
likeSubscribeGlow,
|
||||
bufferFilterPathGroup,
|
||||
new StringFilterGroup(
|
||||
Settings.HIDE_LIKE_DISLIKE_BUTTON,
|
||||
"|segmented_like_dislike_button"
|
||||
@@ -57,6 +57,12 @@ final class ButtonsFilter extends Filter {
|
||||
)
|
||||
);
|
||||
|
||||
// FIXME: 20.22+ filtering of the action buttons doesn't work because
|
||||
// the buffer is the same for all buttons.
|
||||
if (!VersionCheckPatch.IS_20_22_OR_GREATER) {
|
||||
addPathCallbacks(bufferFilterPathGroup);
|
||||
}
|
||||
|
||||
bufferButtonsGroupList.addAll(
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_REPORT_BUTTON,
|
||||
@@ -108,11 +114,13 @@ final class ButtonsFilter extends Filter {
|
||||
}
|
||||
|
||||
private boolean isEveryFilterGroupEnabled() {
|
||||
for (var group : pathCallbacks)
|
||||
for (var group : pathCallbacks) {
|
||||
if (!group.isEnabled()) return false;
|
||||
}
|
||||
|
||||
for (var group : bufferButtonsGroupList)
|
||||
for (var group : bufferButtonsGroupList) {
|
||||
if (!group.isEnabled()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,16 +7,17 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@SuppressWarnings("unused")
|
||||
final class DescriptionComponentsFilter extends Filter {
|
||||
|
||||
private static final String INFOCARDS_SECTION_PATH = "infocards_section.e";
|
||||
|
||||
private final StringTrieSearch exceptions = new StringTrieSearch();
|
||||
|
||||
private final ByteArrayFilterGroupList macroMarkersCarouselGroupList = new ByteArrayFilterGroupList();
|
||||
|
||||
private final StringFilterGroup macroMarkersCarousel;
|
||||
|
||||
private final ByteArrayFilterGroupList macroMarkersCarouselGroupList = new ByteArrayFilterGroupList();
|
||||
private final StringFilterGroup horizontalShelf;
|
||||
private final ByteArrayFilterGroup cellVideoAttribute;
|
||||
|
||||
private final StringFilterGroup infoCardsSection;
|
||||
private final StringFilterGroup subscribeButton;
|
||||
private final StringFilterGroup aiGeneratedVideoSummarySection;
|
||||
private final StringFilterGroup hypePoints;
|
||||
|
||||
public DescriptionComponentsFilter() {
|
||||
exceptions.addPatterns(
|
||||
@@ -43,9 +44,10 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
"video_attributes_section"
|
||||
);
|
||||
|
||||
final StringFilterGroup infoCardsSection = new StringFilterGroup(
|
||||
Settings.HIDE_INFO_CARDS_SECTION,
|
||||
"infocards_section"
|
||||
final StringFilterGroup featuredSection = new StringFilterGroup(
|
||||
Settings.HIDE_FEATURED_SECTION,
|
||||
// "media_lockup", "structured_description_video_lockup"
|
||||
"compact_infocard"
|
||||
);
|
||||
|
||||
final StringFilterGroup podcastSection = new StringFilterGroup(
|
||||
@@ -63,6 +65,21 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
"how_this_was_made_section"
|
||||
);
|
||||
|
||||
hypePoints = new StringFilterGroup(
|
||||
Settings.HIDE_HYPE_POINTS,
|
||||
"hype_points_factoid"
|
||||
);
|
||||
|
||||
infoCardsSection = new StringFilterGroup(
|
||||
Settings.HIDE_INFO_CARDS_SECTION,
|
||||
INFOCARDS_SECTION_PATH
|
||||
);
|
||||
|
||||
subscribeButton = new StringFilterGroup(
|
||||
Settings.HIDE_DESCRIPTION_SUBSCRIBE_BUTTON,
|
||||
"subscribe_button"
|
||||
);
|
||||
|
||||
macroMarkersCarousel = new StringFilterGroup(
|
||||
null,
|
||||
"macro_markers_carousel.e"
|
||||
@@ -93,11 +110,14 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
aiGeneratedVideoSummarySection,
|
||||
askSection,
|
||||
attributesSection,
|
||||
infoCardsSection,
|
||||
featuredSection,
|
||||
horizontalShelf,
|
||||
howThisWasMadeSection,
|
||||
hypePoints,
|
||||
infoCardsSection,
|
||||
macroMarkersCarousel,
|
||||
podcastSection,
|
||||
subscribeButton,
|
||||
transcriptSection
|
||||
);
|
||||
}
|
||||
@@ -106,11 +126,15 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
|
||||
if (matchedGroup == aiGeneratedVideoSummarySection) {
|
||||
if (matchedGroup == aiGeneratedVideoSummarySection || matchedGroup == hypePoints) {
|
||||
// Only hide if player is open, in case this component is used somewhere else.
|
||||
return PlayerType.getCurrent().isMaximizedOrFullscreen();
|
||||
}
|
||||
|
||||
if (matchedGroup == subscribeButton) {
|
||||
return path.startsWith(INFOCARDS_SECTION_PATH);
|
||||
}
|
||||
|
||||
if (exceptions.matches(path)) return false;
|
||||
|
||||
if (matchedGroup == macroMarkersCarousel) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_20_21_OR_GREATER;
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -21,13 +22,14 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
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.
|
||||
"java.lang.ref.WeakReference"
|
||||
);
|
||||
private static final ByteArrayFilterGroup mixPlaylistsExceptions2 = new ByteArrayFilterGroup(
|
||||
private static final ByteArrayFilterGroup mixPlaylistsBufferExceptions = new ByteArrayFilterGroup(
|
||||
null,
|
||||
"cell_description_body"
|
||||
"cell_description_body",
|
||||
"channel_profile"
|
||||
);
|
||||
private static final ByteArrayFilterGroup mixPlaylists = new ByteArrayFilterGroup(
|
||||
null,
|
||||
@@ -369,28 +371,28 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
* Injection point.
|
||||
* Called from a different place then the other filters.
|
||||
*/
|
||||
public static boolean filterMixPlaylists(Object conversionContext, @Nullable final byte[] bytes) {
|
||||
public static boolean filterMixPlaylists(Object conversionContext, @Nullable byte[] buffer) {
|
||||
// Edit: This hook may no longer be needed, and mix playlist filtering
|
||||
// might be possible using the existing litho filters.
|
||||
try {
|
||||
if (!Settings.HIDE_MIX_PLAYLISTS.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bytes == null) {
|
||||
Logger.printDebug(() -> "bytes is null");
|
||||
if (buffer == null) {
|
||||
Logger.printDebug(() -> "buffer is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent playlist items being hidden, if a mix playlist is present in it.
|
||||
if (mixPlaylistsExceptions.matches(conversionContext.toString())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent hiding the description of some videos accidentally.
|
||||
if (mixPlaylistsExceptions2.check(bytes).isFiltered()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mixPlaylists.check(bytes).isFiltered()) {
|
||||
if (mixPlaylists.check(buffer).isFiltered()
|
||||
// Prevent hiding the description of some videos accidentally.
|
||||
&& !mixPlaylistsBufferExceptions.check(buffer).isFiltered()
|
||||
// Prevent playlist items being hidden, if a mix playlist is present in it.
|
||||
// Check last since it requires creating a context string.
|
||||
//
|
||||
// FIXME: The conversion context passed in does not always generate a valid toString.
|
||||
// This string check may no longer be needed, or the patch may be broken.
|
||||
&& !mixPlaylistsContextExceptions.matches(conversionContext.toString())) {
|
||||
Logger.printDebug(() -> "Filtered mix playlist");
|
||||
return true;
|
||||
}
|
||||
@@ -447,11 +449,23 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
: height;
|
||||
}
|
||||
|
||||
private static final boolean HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED
|
||||
= Settings.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS.get();
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideInRelatedVideos(View chipView) {
|
||||
Utils.hideViewBy0dpUnderCondition(Settings.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS, chipView);
|
||||
// Cannot use 0dp hide with later targets, otherwise the suggested videos
|
||||
// can be shown in full screen mode.
|
||||
// This behavior may also be present in earlier app targets.
|
||||
if (IS_20_21_OR_GREATER) {
|
||||
// FIXME: The filter bar is still briefly shown when dragging the suggested videos
|
||||
// below the video player.
|
||||
Utils.hideViewUnderCondition(HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED, chipView);
|
||||
} else {
|
||||
Utils.hideViewBy0dpUnderCondition(HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED, chipView);
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean HIDE_DOODLES_ENABLED = Settings.HIDE_DOODLES.get();
|
||||
@@ -476,7 +490,9 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
&& NavigationBar.isSearchBarActive()
|
||||
// Search bar can be active but behind the player.
|
||||
&& !PlayerType.getCurrent().isMaximizedOrFullscreen()) {
|
||||
Utils.hideViewByLayoutParams(view);
|
||||
// FIXME: "Show more" button is visible hidden,
|
||||
// but an empty space remains that can be clicked.
|
||||
Utils.hideViewBy0dp(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,16 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.StringTrieSearch;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -73,6 +78,15 @@ public final class LithoFilterPatch {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder for actual filters.
|
||||
*/
|
||||
private static final class DummyFilter extends Filter { }
|
||||
|
||||
private static final Filter[] filters = new Filter[] {
|
||||
new DummyFilter() // Replaced during patching, do not touch.
|
||||
};
|
||||
|
||||
/**
|
||||
* Litho layout fixed thread pool size override.
|
||||
* <p>
|
||||
@@ -90,25 +104,50 @@ public final class LithoFilterPatch {
|
||||
private static final int LITHO_LAYOUT_THREAD_POOL_SIZE = 1;
|
||||
|
||||
/**
|
||||
* Placeholder for actual filters.
|
||||
* 20.22+ cannot use the thread buffer, because frequently the buffer is not correct,
|
||||
* especially for components that are recreated such as dragging off screen then back on screen.
|
||||
* Instead, parse the identifier found near the start of the buffer and use that to
|
||||
* identify the correct buffer to use when filtering.
|
||||
*/
|
||||
private static final class DummyFilter extends Filter { }
|
||||
private static final boolean EXTRACT_IDENTIFIER_FROM_BUFFER = VersionCheckPatch.IS_20_22_OR_GREATER;
|
||||
|
||||
private static final Filter[] filters = new Filter[] {
|
||||
new DummyFilter() // Replaced patching, do not touch.
|
||||
};
|
||||
/**
|
||||
* Turns on additional logging, used for development purposes only.
|
||||
*/
|
||||
public static final boolean DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER = false;
|
||||
|
||||
private static final StringTrieSearch pathSearchTree = new StringTrieSearch();
|
||||
private static final StringTrieSearch identifierSearchTree = new StringTrieSearch();
|
||||
/**
|
||||
* String suffix for components.
|
||||
* Can be any of: ".eml", ".e-b", ".eml-js", "e-js-b"
|
||||
*/
|
||||
private static final String LITHO_COMPONENT_EXTENSION = ".e";
|
||||
private static final byte[] LITHO_COMPONENT_EXTENSION_BYTES = LITHO_COMPONENT_EXTENSION.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
|
||||
/**
|
||||
* Because litho filtering is multi-threaded and the buffer is passed in from a different injection point,
|
||||
* the buffer is saved to a ThreadLocal so each calling thread does not interfere with other threads.
|
||||
* Used for 20.21 and lower.
|
||||
*/
|
||||
private static final ThreadLocal<byte[]> bufferThreadLocal = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* Identifier to protocol buffer mapping. Only used for 20.22+.
|
||||
* Thread local is needed because filtering is multi-threaded and each thread can load
|
||||
* a different component with the same identifier.
|
||||
*/
|
||||
private static final ThreadLocal<Map<String, byte[]>> identifierToBufferThread = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* Global shared buffer. Used only if the buffer is not found in the ThreadLocal.
|
||||
*/
|
||||
private static final Map<String, byte[]> identifierToBufferGlobal
|
||||
= Collections.synchronizedMap(createIdentifierToBufferMap());
|
||||
|
||||
private static final StringTrieSearch pathSearchTree = new StringTrieSearch();
|
||||
private static final StringTrieSearch identifierSearchTree = new StringTrieSearch();
|
||||
|
||||
static {
|
||||
for (Filter filter : filters) {
|
||||
filterUsingCallbacks(identifierSearchTree, filter,
|
||||
@@ -160,16 +199,107 @@ public final class LithoFilterPatch {
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, byte[]> createIdentifierToBufferMap() {
|
||||
// It's unclear how many items should be cached. This is a guess.
|
||||
return Utils.createSizeRestrictedMap(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that differs from {@link Character#isDigit(char)}
|
||||
* as this only matches ascii and not unicode numbers.
|
||||
*/
|
||||
private static boolean isAsciiNumber(byte character) {
|
||||
return '0' <= character && character <= '9';
|
||||
}
|
||||
|
||||
private static boolean isAsciiLowerCaseLetter(byte character) {
|
||||
return 'a' <= character && character <= 'z';
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. Called off the main thread.
|
||||
* Targets 20.22+
|
||||
*/
|
||||
public static void setProtoBuffer(byte[] buffer) {
|
||||
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
|
||||
// This is intentional, as it appears the buffer can be set once and then filtered multiple times.
|
||||
// The buffer will be cleared from memory after a new buffer is set by the same thread,
|
||||
// or when the calling thread eventually dies.
|
||||
bufferThreadLocal.set(buffer);
|
||||
if (DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
LithoFilterParameters.findAsciiStrings(builder, buffer);
|
||||
Logger.printDebug(() -> "New buffer: " + builder);
|
||||
}
|
||||
|
||||
// Could use Boyer-Moore-Horspool since the string is ASCII and has a limited number of
|
||||
// unique characters, but it seems to be slower since the extra overhead of checking the
|
||||
// bad character array negates any performance gain of skipping a few extra subsearches.
|
||||
int emlIndex = -1;
|
||||
final int emlStringLength = LITHO_COMPONENT_EXTENSION_BYTES.length;
|
||||
for (int i = 0, lastStartIndex = buffer.length - emlStringLength; i <= lastStartIndex; i++) {
|
||||
boolean match = true;
|
||||
for (int j = 0; j < emlStringLength; j++) {
|
||||
if (buffer[i + j] != LITHO_COMPONENT_EXTENSION_BYTES[j]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
emlIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (emlIndex < 0) {
|
||||
// Buffer is not used for creating a new litho component.
|
||||
return;
|
||||
}
|
||||
|
||||
int startIndex = emlIndex - 1;
|
||||
while (startIndex > 0) {
|
||||
final byte character = buffer[startIndex];
|
||||
int startIndexFinal = startIndex;
|
||||
if (isAsciiLowerCaseLetter(character) || isAsciiNumber(character) || character == '_') {
|
||||
// Valid character for the first path element.
|
||||
startIndex--;
|
||||
} else {
|
||||
startIndex++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Strip away any numbers on the start of the identifier, which can
|
||||
// be from random data in the buffer before the identifier starts.
|
||||
while (true) {
|
||||
final byte character = buffer[startIndex];
|
||||
if (isAsciiNumber(character)) {
|
||||
startIndex++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the pipe character after the identifier.
|
||||
int endIndex = -1;
|
||||
for (int i = emlIndex, length = buffer.length; i < length; i++) {
|
||||
if (buffer[i] == '|') {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (endIndex < 0) {
|
||||
Logger.printException(() -> "Could not find buffer identifier");
|
||||
return;
|
||||
}
|
||||
|
||||
String identifier = new String(buffer, startIndex, endIndex - startIndex, StandardCharsets.US_ASCII);
|
||||
if (DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER) {
|
||||
Logger.printDebug(() -> "Found buffer for identifier: " + identifier);
|
||||
}
|
||||
identifierToBufferGlobal.put(identifier, buffer);
|
||||
|
||||
Map<String, byte[]> map = identifierToBufferThread.get();
|
||||
if (map == null) {
|
||||
map = createIdentifierToBufferMap();
|
||||
identifierToBufferThread.set(map);
|
||||
}
|
||||
map.put(identifier, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,46 +307,70 @@ public final class LithoFilterPatch {
|
||||
* Targets 20.21 and lower.
|
||||
*/
|
||||
public static void setProtoBuffer(@Nullable ByteBuffer buffer) {
|
||||
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
|
||||
// This is intentional, as it appears the buffer can be set once and then filtered multiple times.
|
||||
// The buffer will be cleared from memory after a new buffer is set by the same thread,
|
||||
// or when the calling thread eventually dies.
|
||||
if (buffer == null || !buffer.hasArray()) {
|
||||
// It appears the buffer can be cleared out just before the call to #filter()
|
||||
// Ignore this null value and retain the last buffer that was set.
|
||||
Logger.printDebug(() -> "Ignoring null or empty buffer: " + buffer);
|
||||
} else {
|
||||
setProtoBuffer(buffer.array());
|
||||
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
|
||||
// This is intentional, as it appears the buffer can be set once and then filtered multiple times.
|
||||
// The buffer will be cleared from memory after a new buffer is set by the same thread,
|
||||
// or when the calling thread eventually dies.
|
||||
bufferThreadLocal.set(buffer.array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isFiltered(String lithoIdentifier, StringBuilder pathBuilder) {
|
||||
public static boolean isFiltered(String identifier, StringBuilder pathBuilder) {
|
||||
try {
|
||||
if (lithoIdentifier.isEmpty() && pathBuilder.length() == 0) {
|
||||
if (identifier.isEmpty() || pathBuilder.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] buffer = bufferThreadLocal.get();
|
||||
byte[] buffer = null;
|
||||
if (EXTRACT_IDENTIFIER_FROM_BUFFER) {
|
||||
final int pipeIndex = identifier.indexOf('|');
|
||||
if (pipeIndex >= 0) {
|
||||
// If the identifier contains no pipe, then it's not an ".eml" identifier
|
||||
// and the buffer is not uniquely identified. Typically this only happens
|
||||
// for subcomponents where buffer filtering is not used.
|
||||
String identifierKey = identifier.substring(0, pipeIndex);
|
||||
|
||||
var map = identifierToBufferThread.get();
|
||||
if (map != null) {
|
||||
buffer = map.get(identifierKey);
|
||||
}
|
||||
|
||||
if (buffer == null) {
|
||||
// Buffer for thread local not found. Use the last buffer found from any thread.
|
||||
buffer = identifierToBufferGlobal.get(identifierKey);
|
||||
|
||||
if (DEBUG_EXTRACT_IDENTIFIER_FROM_BUFFER && buffer == null) {
|
||||
// No buffer is found for some components, such as
|
||||
// shorts_lockup_cell.eml on channel profiles.
|
||||
// For now, just ignore this and filter without a buffer.
|
||||
Logger.printException(() -> "Could not find global buffer for identifier: " + identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer = bufferThreadLocal.get();
|
||||
}
|
||||
|
||||
// Potentially the buffer may have been null or never set up until now.
|
||||
// Use an empty buffer so the litho id/path filters still work correctly.
|
||||
// Use an empty buffer so the litho id/path filters that do not use a buffer still work.
|
||||
if (buffer == null) {
|
||||
buffer = EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
LithoFilterParameters parameter = new LithoFilterParameters(
|
||||
lithoIdentifier, pathBuilder.toString(), buffer);
|
||||
String path = pathBuilder.toString();
|
||||
LithoFilterParameters parameter = new LithoFilterParameters(identifier, path, buffer);
|
||||
Logger.printDebug(() -> "Searching " + parameter);
|
||||
|
||||
if (identifierSearchTree.matches(parameter.identifier, parameter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pathSearchTree.matches(parameter.path, parameter)) {
|
||||
return true;
|
||||
}
|
||||
return identifierSearchTree.matches(identifier, parameter)
|
||||
|| pathSearchTree.matches(path, parameter);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "isFiltered failure", ex);
|
||||
}
|
||||
|
||||
@@ -12,13 +12,9 @@ import java.util.List;
|
||||
public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||
|
||||
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
|
||||
private static final boolean AVAILABLE_ON_LAUNCH = !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
// Check conditions of launch and now. Otherwise if spoofing is changed
|
||||
// without a restart the setting will show as available when it's not.
|
||||
return AVAILABLE_ON_LAUNCH && !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
||||
return !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,12 +59,12 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||
"volume_stable_"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_PLAYER_FLYOUT_HELP,
|
||||
"yt_outline_question_circle_"
|
||||
Settings.HIDE_PLAYER_FLYOUT_LISTEN_WITH_YOUTUBE_MUSIC,
|
||||
"yt_outline_youtube_music_"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_PLAYER_FLYOUT_MORE_INFO,
|
||||
"yt_outline_info_circle_"
|
||||
Settings.HIDE_PLAYER_FLYOUT_HELP,
|
||||
"yt_outline_question_circle_"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_PLAYER_FLYOUT_LOCK_SCREEN,
|
||||
|
||||
@@ -4,15 +4,15 @@ import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.TrieSearch;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.patches.ReturnYouTubeDislikePatch;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.TrieSearch;
|
||||
|
||||
/**
|
||||
* Searches for video id's in the proto buffer of Shorts dislike.
|
||||
@@ -33,18 +33,7 @@ public final class ReturnYouTubeDislikeFilter extends Filter {
|
||||
* Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry().
|
||||
*/
|
||||
@GuardedBy("itself")
|
||||
private static final Map<String, Boolean> lastVideoIds = new LinkedHashMap<>() {
|
||||
/**
|
||||
* Number of video id's to keep track of for searching thru the buffer.
|
||||
* A minimum value of 3 should be sufficient, but check a few more just in case.
|
||||
*/
|
||||
private static final int NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK = 5;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry eldest) {
|
||||
return size() > NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK;
|
||||
}
|
||||
};
|
||||
private static final Map<String, Boolean> lastVideoIds = Utils.createSizeRestrictedMap(5);
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.NavigationBar;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@@ -209,7 +210,11 @@ public final class ShortsFilter extends Filter {
|
||||
|
||||
videoActionButton = new StringFilterGroup(
|
||||
null,
|
||||
// Can be simply 'button.e', 'shorts_video_action_button.e' or 'reel_action_button.e'
|
||||
// Can be any of:
|
||||
// button.eml
|
||||
// shorts_video_action_button.eml
|
||||
// reel_action_button.eml
|
||||
// reel_pivot_button.eml
|
||||
"button.e"
|
||||
);
|
||||
|
||||
@@ -220,31 +225,37 @@ public final class ShortsFilter extends Filter {
|
||||
|
||||
addPathCallbacks(
|
||||
shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionButton,
|
||||
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar, previewComment,
|
||||
suggestedAction, pausedOverlayButtons, channelBar, previewComment,
|
||||
fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
|
||||
stickers, likeFountain, likeButton, dislikeButton
|
||||
);
|
||||
|
||||
//
|
||||
// All other action buttons.
|
||||
//
|
||||
videoActionButtonBuffer.addAll(
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_COMMENTS_BUTTON,
|
||||
"reel_comment_button",
|
||||
"youtube_shorts_comment_outline"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_SHARE_BUTTON,
|
||||
"reel_share_button",
|
||||
"youtube_shorts_share_outline"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_REMIX_BUTTON,
|
||||
"reel_remix_button",
|
||||
"youtube_shorts_remix_outline"
|
||||
)
|
||||
);
|
||||
// FIXME: The Shorts buffer is very different with 20.22+ and if any of these filters
|
||||
// are enabled then all Shorts player vertical buttons are hidden.
|
||||
if (!VersionCheckPatch.IS_20_22_OR_GREATER) {
|
||||
addPathCallbacks(shortsActionBar);
|
||||
|
||||
//
|
||||
// All other action buttons.
|
||||
//
|
||||
videoActionButtonBuffer.addAll(
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_COMMENTS_BUTTON,
|
||||
"reel_comment_button",
|
||||
"youtube_shorts_comment_outline"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_SHARE_BUTTON,
|
||||
"reel_share_button",
|
||||
"youtube_shorts_share_outline"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_REMIX_BUTTON,
|
||||
"reel_remix_button",
|
||||
"youtube_shorts_remix_outline"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Suggested actions.
|
||||
|
||||
@@ -21,7 +21,6 @@ public class RememberVideoQualityPatch {
|
||||
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE;
|
||||
|
||||
|
||||
public static boolean shouldRememberVideoQuality() {
|
||||
BooleanSetting preference = ShortsPlayerState.isOpen()
|
||||
? Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.youtube.patches.playback.speed;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.youtube.videoplayer.PlayerControlButton.fadeInDuration;
|
||||
import static app.revanced.extension.youtube.videoplayer.PlayerControlButton.getDialogBackgroundColor;
|
||||
|
||||
@@ -30,6 +29,7 @@ import java.util.function.Function;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.shared.ui.SheetBottomDialog;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilter;
|
||||
@@ -264,14 +264,6 @@ public class CustomPlaybackSpeedPatch {
|
||||
SheetBottomDialog.DraggableLinearLayout mainLayout =
|
||||
SheetBottomDialog.createMainLayout(context, getDialogBackgroundColor());
|
||||
|
||||
// Preset size constants.
|
||||
final int dip4 = dipToPixels(4);
|
||||
final int dip8 = dipToPixels(8);
|
||||
final int dip12 = dipToPixels(12);
|
||||
final int dip20 = dipToPixels(20);
|
||||
final int dip32 = dipToPixels(32);
|
||||
final int dip60 = dipToPixels(60);
|
||||
|
||||
// Display current playback speed.
|
||||
TextView currentSpeedText = new TextView(context);
|
||||
float currentSpeed = VideoInformation.getPlaybackSpeed();
|
||||
@@ -283,7 +275,7 @@ public class CustomPlaybackSpeedPatch {
|
||||
currentSpeedText.setGravity(Gravity.CENTER);
|
||||
LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
textParams.setMargins(0, dip20, 0, 0);
|
||||
textParams.setMargins(0, Dim.dp20, 0, 0);
|
||||
currentSpeedText.setLayoutParams(textParams);
|
||||
// Add current speed text view to main layout.
|
||||
mainLayout.addView(currentSpeedText);
|
||||
@@ -294,8 +286,8 @@ public class CustomPlaybackSpeedPatch {
|
||||
sliderLayout.setGravity(Gravity.CENTER_VERTICAL);
|
||||
|
||||
// Create +/- buttons.
|
||||
Button minusButton = createStyledButton(context, false, dip8, dip8);
|
||||
Button plusButton = createStyledButton(context, true, dip8, dip8);
|
||||
Button minusButton = createStyledButton(context, false);
|
||||
Button plusButton = createStyledButton(context, true);
|
||||
|
||||
// Create slider for speed adjustment.
|
||||
SeekBar speedSlider = new SeekBar(context);
|
||||
@@ -363,7 +355,7 @@ public class CustomPlaybackSpeedPatch {
|
||||
gridLayout.setRowCount((int) Math.ceil(customPlaybackSpeeds.length / 5.0));
|
||||
LinearLayout.LayoutParams gridParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
gridParams.setMargins(dip4, dip12, dip4, dip12); // Speed buttons container.
|
||||
gridParams.setMargins(Dim.dp4, Dim.dp12, Dim.dp4, Dim.dp12); // Speed buttons container.
|
||||
gridLayout.setLayoutParams(gridParams);
|
||||
|
||||
// For button use 1 digit minimum.
|
||||
@@ -378,8 +370,8 @@ public class CustomPlaybackSpeedPatch {
|
||||
GridLayout.LayoutParams containerParams = new GridLayout.LayoutParams();
|
||||
containerParams.width = 0; // Equal width for columns.
|
||||
containerParams.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1, 1f);
|
||||
containerParams.setMargins(dip4, 0, dip4, 0); // Button margins.
|
||||
containerParams.height = dip60; // Fixed height for button and label.
|
||||
containerParams.setMargins(Dim.dp4, 0, Dim.dp4, 0); // Button margins.
|
||||
containerParams.height = Dim.dp(60); // Fixed height for button and label.
|
||||
buttonContainer.setLayoutParams(containerParams);
|
||||
|
||||
// Create speed button.
|
||||
@@ -391,14 +383,14 @@ public class CustomPlaybackSpeedPatch {
|
||||
speedButton.setGravity(Gravity.CENTER);
|
||||
|
||||
ShapeDrawable buttonBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(20), null, null));
|
||||
Dim.roundedCorners(20), null, null));
|
||||
buttonBackground.getPaint().setColor(getAdjustedBackgroundColor(false));
|
||||
speedButton.setBackground(buttonBackground);
|
||||
speedButton.setPadding(dip4, dip4, dip4, dip4);
|
||||
speedButton.setPadding(Dim.dp4, Dim.dp4, Dim.dp4, Dim.dp4);
|
||||
|
||||
// Center button vertically and stretch horizontally in container.
|
||||
FrameLayout.LayoutParams buttonParams = new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT, dip32, Gravity.CENTER);
|
||||
FrameLayout.LayoutParams.MATCH_PARENT, Dim.dp32, Gravity.CENTER);
|
||||
speedButton.setLayoutParams(buttonParams);
|
||||
|
||||
// Add speed buttons view to buttons container layout.
|
||||
@@ -475,21 +467,18 @@ public class CustomPlaybackSpeedPatch {
|
||||
*
|
||||
* @param context The Android context used to create the button.
|
||||
* @param isPlus True to display a plus symbol, false to display a minus symbol.
|
||||
* @param marginStart The start margin in pixels (left for LTR, right for RTL).
|
||||
* @param marginEnd The end margin in pixels (right for LTR, left for RTL).
|
||||
* @return A configured {@link Button} with the specified styling and layout parameters.
|
||||
*/
|
||||
private static Button createStyledButton(Context context, boolean isPlus, int marginStart, int marginEnd) {
|
||||
private static Button createStyledButton(Context context, boolean isPlus) {
|
||||
Button button = new Button(context, null, 0); // Disable default theme style.
|
||||
button.setText(""); // No text on button.
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(20), null, null));
|
||||
Dim.roundedCorners(20), null, null));
|
||||
background.getPaint().setColor(getAdjustedBackgroundColor(false));
|
||||
button.setBackground(background);
|
||||
button.setForeground(new OutlineSymbolDrawable(isPlus)); // Plus or minus symbol.
|
||||
final int dip36 = dipToPixels(36);
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dip36, dip36);
|
||||
params.setMargins(marginStart, 0, marginEnd, 0); // Set margins.
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(Dim.dp36, Dim.dp36);
|
||||
params.setMargins(Dim.dp8, 0, Dim.dp8, 0); // Set margins.
|
||||
button.setLayoutParams(params);
|
||||
return button;
|
||||
}
|
||||
@@ -554,7 +543,7 @@ class OutlineSymbolDrawable extends Drawable {
|
||||
paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Enable anti-aliasing for smooth rendering.
|
||||
paint.setColor(Utils.getAppForegroundColor());
|
||||
paint.setStyle(Paint.Style.STROKE); // Use stroke style for outline.
|
||||
paint.setStrokeWidth(dipToPixels(1)); // 1dp stroke width.
|
||||
paint.setStrokeWidth(Dim.dp1); // 1dp stroke width.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.extension.youtube.patches.spoof;
|
||||
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_CREATOR;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_NO_SDK;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.IPADOS;
|
||||
@@ -21,6 +22,11 @@ public class SpoofVideoStreamsPatch {
|
||||
return Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.isAvailable()
|
||||
&& Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ANDROID_VR_1_43_32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Setting<?>> getParentSettings() {
|
||||
return List.of(Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,6 +47,7 @@ public class SpoofVideoStreamsPatch {
|
||||
VISIONOS,
|
||||
ANDROID_CREATOR,
|
||||
ANDROID_VR_1_43_32,
|
||||
ANDROID_NO_SDK,
|
||||
IPADOS);
|
||||
|
||||
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package app.revanced.extension.youtube.patches.theme;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
/**
|
||||
* Dynamic drawable that is either the regular or bolded ReVanced preference icon.
|
||||
*
|
||||
* This is needed because the YouTube ReVanced preference intent is an AndroidX preference,
|
||||
* and AndroidX classes are not built into Android which makes programmatically changing
|
||||
* the preference thru patching overly complex. This solves the problem by using a drawable
|
||||
* wrapper to dynamically pick which icon drawable to use at runtime.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ReVancedSettingsIconDynamicDrawable extends Drawable {
|
||||
|
||||
private final Drawable icon;
|
||||
|
||||
public ReVancedSettingsIconDynamicDrawable() {
|
||||
final int resId = Utils.getResourceIdentifier(ResourceType.DRAWABLE,
|
||||
Utils.appIsUsingBoldIcons()
|
||||
? "revanced_settings_icon_bold"
|
||||
: "revanced_settings_icon"
|
||||
);
|
||||
|
||||
icon = Utils.getContext().getDrawable(resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
icon.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
icon.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
icon.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return icon.getOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return icon.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return icon.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBounds(int left, int top, int right, int bottom) {
|
||||
super.setBounds(left, top, right, bottom);
|
||||
icon.setBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBounds(@NonNull Rect bounds) {
|
||||
super.setBounds(bounds);
|
||||
icon.setBounds(bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBoundsChange(@NonNull Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
icon.setBounds(bounds);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -101,16 +102,6 @@ public final class SeekbarColorPatch {
|
||||
return customSeekbarColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* injection point.
|
||||
*/
|
||||
public static boolean useLotteLaunchSplashScreen(boolean original) {
|
||||
// This method is only used for development purposes to force the old style launch screen.
|
||||
// Forcing this off on some devices can cause unexplained startup crashes,
|
||||
// where the lottie animation is still used even though this condition appears to bypass it.
|
||||
return original; // false = drawable style, true = lottie style.
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Modern Lottie style animation.
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.concurrent.TimeoutException;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.RYDVoteData;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -124,12 +125,12 @@ public class ReturnYouTubeDislike {
|
||||
|
||||
static {
|
||||
leftSeparatorBounds = new Rect(0, 0,
|
||||
Utils.dipToPixels(1.2f),
|
||||
Utils.dipToPixels(14f));
|
||||
final int middleSeparatorSize = Utils.dipToPixels(3.7f);
|
||||
Dim.dp(1.2f),
|
||||
Dim.dp(14f));
|
||||
final int middleSeparatorSize = Dim.dp(3.7f);
|
||||
middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize);
|
||||
|
||||
leftSeparatorShapePaddingPixels = Utils.dipToPixels(8.4f);
|
||||
leftSeparatorShapePaddingPixels = Dim.dp(8.4f);
|
||||
|
||||
leftSeparatorShape = new ShapeDrawable(new RectShape());
|
||||
leftSeparatorShape.setBounds(leftSeparatorBounds);
|
||||
@@ -259,7 +260,8 @@ public class ReturnYouTubeDislike {
|
||||
// middle separator
|
||||
String middleSeparatorString = compactLayout
|
||||
? " " + MIDDLE_SEPARATOR_CHARACTER + " "
|
||||
: " \u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009 "; // u2009 = 'narrow space' character
|
||||
: " \u2009\u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009\u2009 "; // u2009 = 'narrow space'
|
||||
|
||||
final int shapeInsertionIndex = middleSeparatorString.length() / 2;
|
||||
Spannable middleSeparatorSpan = new SpannableString(middleSeparatorString);
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
|
||||
@@ -554,7 +556,8 @@ public class ReturnYouTubeDislike {
|
||||
|
||||
if (originalDislikeSpan != null && replacementLikeDislikeSpan != null
|
||||
&& spansHaveEqualTextAndColor(original, originalDislikeSpan)) {
|
||||
Logger.printDebug(() -> "Replacing span with previously created dislike span of data: " + videoId);
|
||||
Logger.printDebug(() -> "Replacing span: " + original + " with " +
|
||||
"previously created dislike span of data: " + videoId);
|
||||
return replacementLikeDislikeSpan;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrow
|
||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
|
||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
|
||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailStillTime;
|
||||
import app.revanced.extension.youtube.patches.MiniplayerPatch;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
|
||||
import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider.SwipeOverlayStyle;
|
||||
|
||||
@@ -183,7 +183,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, new MiniplayerAnyModernAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerHideOverlayButtonsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, new MiniplayerHideSubtextsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, new MiniplayerPatch.MiniplayerHideRewindOrOverlayOpacityAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, new MiniplayerHideRewindOrOverlayOpacityAvailability());
|
||||
public static final IntegerSetting MINIPLAYER_WIDTH_DIP = new IntegerSetting("revanced_miniplayer_width_dip", 192, true, new MiniplayerAnyModernAvailability());
|
||||
public static final IntegerSetting MINIPLAYER_OPACITY = new IntegerSetting("revanced_miniplayer_opacity", 100, true, new MiniplayerHideRewindOrOverlayOpacityAvailability());
|
||||
|
||||
@@ -210,10 +210,13 @@ public class Settings extends BaseSettings {
|
||||
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_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_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_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_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);
|
||||
|
||||
// Action buttons
|
||||
@@ -239,9 +242,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_AUDIO_TRACK = new BooleanSetting("revanced_hide_player_flyout_audio_track", FALSE, new HideAudioFlyoutMenuAvailability());
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_CAPTIONS = new BooleanSetting("revanced_hide_player_flyout_captions", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_HELP = new BooleanSetting("revanced_hide_player_flyout_help", TRUE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_LISTEN_WITH_YOUTUBE_MUSIC = new BooleanSetting("revanced_hide_player_flyout_listen_with_youtube_music", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_LOCK_SCREEN = new BooleanSetting("revanced_hide_player_flyout_lock_screen", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_LOOP_VIDEO = new BooleanSetting("revanced_hide_player_flyout_loop_video", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_MORE_INFO = new BooleanSetting("revanced_hide_player_flyout_more_info", TRUE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_SLEEP_TIMER = new BooleanSetting("revanced_hide_player_flyout_sleep_timer", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_SPEED = new BooleanSetting("revanced_hide_player_flyout_speed", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_STABLE_VOLUME = new BooleanSetting("revanced_hide_player_flyout_stable_volume", FALSE);
|
||||
@@ -280,6 +283,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_hide_notifications_button", FALSE, true);
|
||||
public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true,
|
||||
"revanced_switch_create_with_notifications_button_user_dialog_message");
|
||||
public static final BooleanSetting NAVIGATION_BAR_ANIMATIONS = new BooleanSetting("revanced_navigation_bar_animations", FALSE);
|
||||
public static final BooleanSetting DISABLE_TRANSLUCENT_STATUS_BAR = new BooleanSetting("revanced_disable_translucent_status_bar", FALSE, true,
|
||||
"revanced_disable_translucent_status_bar_user_dialog_message");
|
||||
public static final BooleanSetting DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT = new BooleanSetting("revanced_disable_translucent_navigation_bar_light", FALSE, true);
|
||||
@@ -331,6 +335,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", FALSE);
|
||||
public static final BooleanSetting HIDE_SEEKBAR = new BooleanSetting("revanced_hide_seekbar", FALSE, true);
|
||||
public static final BooleanSetting HIDE_SEEKBAR_THUMBNAIL = new BooleanSetting("revanced_hide_seekbar_thumbnail", FALSE, true);
|
||||
public static final BooleanSetting FULLSCREEN_LARGE_SEEKBAR = new BooleanSetting("revanced_fullscreen_large_seekbar", FALSE);
|
||||
public static final BooleanSetting HIDE_TIMESTAMP = new BooleanSetting("revanced_hide_timestamp", FALSE);
|
||||
public static final BooleanSetting RESTORE_OLD_SEEKBAR_THUMBNAILS = new BooleanSetting("revanced_restore_old_seekbar_thumbnails", TRUE);
|
||||
public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", FALSE);
|
||||
@@ -465,6 +470,13 @@ public class Settings extends BaseSettings {
|
||||
static {
|
||||
// region Migration
|
||||
|
||||
// 20.37+ YT removed parts of the code for the legacy tablet miniplayer.
|
||||
// This check must remain until the Tablet type is eventually removed.
|
||||
if (VersionCheckPatch.IS_20_37_OR_GREATER && MINIPLAYER_TYPE.get() == MiniplayerType.TABLET) {
|
||||
Logger.printInfo(() -> "Resetting miniplayer tablet type");
|
||||
MINIPLAYER_TYPE.resetToDefault();
|
||||
}
|
||||
|
||||
// Migrate renamed change header enums.
|
||||
if (HEADER_LOGO.get() == HeaderLogo.REVANCED) {
|
||||
HEADER_LOGO.save(HeaderLogo.ROUNDED);
|
||||
@@ -507,6 +519,14 @@ public class Settings extends BaseSettings {
|
||||
SPOOF_APP_VERSION.resetToDefault();
|
||||
}
|
||||
|
||||
if (!BaseSettings.SETTINGS_DISABLE_BOLD_ICONS.get() && SPOOF_APP_VERSION.get()
|
||||
&& SPOOF_APP_VERSION_TARGET.get().compareTo("19.35.00") <= 0) {
|
||||
Logger.printInfo(() -> "Temporarily disabling bold icons that don't work with old spoof targets");
|
||||
// Don't save and only temporarily overwrite the value so
|
||||
// if spoofing is turned off the old setting value is used.
|
||||
BooleanSetting.privateSetValue(BaseSettings.SETTINGS_DISABLE_BOLD_ICONS, false);
|
||||
}
|
||||
|
||||
// VR 1.61 is not selectable in the settings, and it's selected by spoof stream patch if needed.
|
||||
if (SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_1_61_48) {
|
||||
SPOOF_VIDEO_STREAMS_CLIENT_TYPE.resetToDefault();
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.preference.PreferenceFragment;
|
||||
import android.view.View;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseActivityHook;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
@@ -15,11 +16,28 @@ import app.revanced.extension.youtube.settings.preference.YouTubePreferenceFragm
|
||||
import app.revanced.extension.youtube.settings.search.YouTubeSearchViewController;
|
||||
|
||||
/**
|
||||
* Hooks LicenseActivity to inject a custom {@link YouTubePreferenceFragment} with a toolbar and search functionality.
|
||||
* Hooks LicenseActivity to inject a custom {@link YouTubePreferenceFragment}
|
||||
* with a toolbar and search functionality.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class YouTubeActivityHook extends BaseActivityHook {
|
||||
|
||||
/**
|
||||
* How much time has passed since the first launch of the app. Simple check to prevent
|
||||
* forcing bold icons on first launch where the settings menu is partially broken
|
||||
* due to missing icon resources the client has not yet received.
|
||||
*/
|
||||
private static final long MINIMUM_TIME_AFTER_FIRST_LAUNCH_BEFORE_ALLOWING_BOLD_ICONS = 30 * 1000; // 30 seconds.
|
||||
|
||||
private static final boolean USE_BOLD_ICONS = VersionCheckPatch.IS_20_31_OR_GREATER
|
||||
&& !Settings.SETTINGS_DISABLE_BOLD_ICONS.get()
|
||||
&& (System.currentTimeMillis() - Settings.FIRST_TIME_APP_LAUNCHED.get())
|
||||
> MINIMUM_TIME_AFTER_FIRST_LAUNCH_BEFORE_ALLOWING_BOLD_ICONS;
|
||||
|
||||
static {
|
||||
Utils.setAppIsUsingBoldIcons(USE_BOLD_ICONS);
|
||||
}
|
||||
|
||||
private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.
|
||||
|
||||
/**
|
||||
@@ -44,15 +62,7 @@ public class YouTubeActivityHook extends BaseActivityHook {
|
||||
final var theme = Utils.isDarkModeEnabled()
|
||||
? "Theme.YouTube.Settings.Dark"
|
||||
: "Theme.YouTube.Settings";
|
||||
activity.setTheme(Utils.getResourceIdentifierOrThrow(theme, "style"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the YouTube settings layout.
|
||||
*/
|
||||
@Override
|
||||
protected int getContentViewResourceId() {
|
||||
return LAYOUT_REVANCED_SETTINGS_WITH_TOOLBAR;
|
||||
activity.setTheme(Utils.getResourceIdentifierOrThrow(ResourceType.STYLE, theme));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,4 +165,12 @@ public class YouTubeActivityHook extends BaseActivityHook {
|
||||
public static boolean handleBackPress() {
|
||||
return YouTubeSearchViewController.handleFinish(searchViewController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static boolean useBoldIcons(boolean original) {
|
||||
return USE_BOLD_ICONS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package app.revanced.extension.youtube.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.sf;
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
@@ -15,13 +14,9 @@ import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -37,6 +32,7 @@ import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
@@ -264,42 +260,12 @@ public class ExternalDownloaderPreference extends CustomDialogListPreference {
|
||||
|
||||
// Add ListView to content layout with initial height.
|
||||
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
0 // Initial height, will be updated.
|
||||
);
|
||||
listViewParams.bottomMargin = dipToPixels(16);
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f);
|
||||
listViewParams.bottomMargin = Dim.dp16;
|
||||
contentLayout.addView(listView, listViewParams);
|
||||
|
||||
// Add EditText for custom package name.
|
||||
editText = new EditText(context);
|
||||
editText.setText(packageName);
|
||||
editText.setSelection(packageName.length());
|
||||
editText.setHint(str("revanced_external_downloader_other_item_hint"));
|
||||
editText.setSingleLine(true); // Restrict EditText to a single line.
|
||||
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
|
||||
// Set initial EditText state based on selected downloader.
|
||||
editText.setEnabled(usingCustomDownloader);
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable edit) {
|
||||
String updatedPackageName = edit.toString().trim();
|
||||
updateListViewSelection.apply(updatedPackageName);
|
||||
}
|
||||
});
|
||||
|
||||
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(10), null, null));
|
||||
editTextBackground.getPaint().setColor(Utils.getEditTextBackground());
|
||||
final int dip8 = dipToPixels(8);
|
||||
editText.setPadding(dip8, dip8, dip8, dip8);
|
||||
editText.setBackground(editTextBackground);
|
||||
editText.setClipToOutline(true);
|
||||
editText = createEditText(context, packageName, usingCustomDownloader, updateListViewSelection);
|
||||
contentLayout.addView(editText);
|
||||
|
||||
// Create the custom dialog.
|
||||
@@ -350,50 +316,59 @@ public class ExternalDownloaderPreference extends CustomDialogListPreference {
|
||||
);
|
||||
|
||||
// Add the content layout directly to the dialog's main layout.
|
||||
LinearLayout dialogMainLayout = dialogPair.second;
|
||||
dialogMainLayout.addView(contentLayout, dialogMainLayout.getChildCount() - 1);
|
||||
LinearLayout mainLayout = dialogPair.second;
|
||||
LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f);
|
||||
|
||||
// Update ListView height dynamically based on orientation.
|
||||
//noinspection ExtractMethodRecommender
|
||||
Runnable updateListViewHeight = () -> {
|
||||
int totalHeight = 0;
|
||||
ListAdapter listAdapter = listView.getAdapter();
|
||||
if (listAdapter != null) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
final int listAdapterCount = listAdapter.getCount();
|
||||
for (int i = 0; i < listAdapterCount; i++) {
|
||||
View item = listAdapter.getView(i, null, listView);
|
||||
item.measure(
|
||||
View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.AT_MOST),
|
||||
View.MeasureSpec.UNSPECIFIED
|
||||
);
|
||||
totalHeight += item.getMeasuredHeight();
|
||||
}
|
||||
totalHeight += listView.getDividerHeight() * (listAdapterCount - 1);
|
||||
// Insert content before the dialog button row.
|
||||
mainLayout.addView(contentLayout, mainLayout.getChildCount() - 1, contentParams);
|
||||
|
||||
Dialog dialog = dialogPair.first;
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and configures the EditText for the custom package name.
|
||||
*
|
||||
* @param context Context for creating views.
|
||||
* @param initialPackageName The package name to pre-fill.
|
||||
* @param isCustom Whether the "Other" option is selected.
|
||||
* @param textChangeCallback Callback to run when text changes.
|
||||
* @return A configured EditText.
|
||||
*/
|
||||
private EditText createEditText(Context context,
|
||||
String initialPackageName, boolean isCustom,
|
||||
Function<String, Void> textChangeCallback) {
|
||||
EditText editText = new EditText(context);
|
||||
editText.setText(initialPackageName);
|
||||
editText.setSelection(initialPackageName.length());
|
||||
editText.setHint(str("revanced_external_downloader_other_item_hint"));
|
||||
editText.setSingleLine(true);
|
||||
editText.setTextSize(16);
|
||||
editText.setEnabled(isCustom);
|
||||
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable edit) {
|
||||
String updatedPackageName = edit.toString().trim();
|
||||
textChangeCallback.apply(updatedPackageName);
|
||||
}
|
||||
});
|
||||
|
||||
final int orientation = context.getResources().getConfiguration().orientation;
|
||||
if (orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT) {
|
||||
// In portrait orientation, use WRAP_CONTENT for ListView height.
|
||||
listViewParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
} else {
|
||||
// In landscape orientation, limit ListView height to 30% of screen height.
|
||||
final int maxHeight = Utils.percentageHeightToPixels(30);
|
||||
listViewParams.height = Math.min(totalHeight, maxHeight);
|
||||
}
|
||||
listView.setLayoutParams(listViewParams);
|
||||
};
|
||||
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Dim.roundedCorners(10), null, null));
|
||||
editTextBackground.getPaint().setColor(Utils.getEditTextBackground());
|
||||
editText.setPadding(Dim.dp8, Dim.dp8, Dim.dp8, Dim.dp8);
|
||||
editText.setBackground(editTextBackground);
|
||||
editText.setClipToOutline(true);
|
||||
|
||||
// Initial height calculation.
|
||||
updateListViewHeight.run();
|
||||
|
||||
// Listen for configuration changes (e.g., orientation).
|
||||
View dialogView = dialogPair.second;
|
||||
// Recalculate height when layout changes (e.g., orientation change).
|
||||
dialogView.getViewTreeObserver().addOnGlobalLayoutListener(updateListViewHeight::run);
|
||||
|
||||
// Show the dialog.
|
||||
dialogPair.first.show();
|
||||
return editText;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,29 +80,34 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
||||
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
||||
|
||||
String summary = str("revanced_spoof_video_streams_about_no_audio_tracks");
|
||||
String summary = "";
|
||||
|
||||
switch (clientType) {
|
||||
case ANDROID_CREATOR ->
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_no_stable_volume")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_force_original_audio");
|
||||
summary = str("revanced_spoof_video_streams_about_no_audio_tracks")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_stable_volume")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_force_original_audio");
|
||||
// VR 1.61 is not exposed in the UI and should never be reached here.
|
||||
case ANDROID_VR_1_43_32, ANDROID_VR_1_61_48 ->
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_no_stable_volume");
|
||||
summary = str("revanced_spoof_video_streams_about_no_audio_tracks")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_stable_volume");
|
||||
case ANDROID_NO_SDK ->
|
||||
summary = str("revanced_spoof_video_streams_about_playback_failure");
|
||||
case IPADOS ->
|
||||
summary = str("revanced_spoof_video_streams_about_playback_failure")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_av1");
|
||||
case VISIONOS ->
|
||||
summary = str("revanced_spoof_video_streams_about_experimental")
|
||||
+ '\n' + summary
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_audio_tracks")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_av1");
|
||||
default -> Logger.printException(() -> "Unknown client: " + clientType);
|
||||
}
|
||||
|
||||
// Only iPadOS can play children videos in incognito, but it commonly fails at 1 minute
|
||||
// or doesn't even start playback at all. List the side effect for other clients
|
||||
// or doesn't start playback at all. List the side effect for other clients
|
||||
// since they will fall over to iPadOS.
|
||||
if (clientType != ClientType.IPADOS) {
|
||||
if (clientType != ClientType.IPADOS && clientType != ClientType.ANDROID_NO_SDK) {
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -72,7 +74,7 @@ public final class NavigationBar {
|
||||
*/
|
||||
public static boolean isSearchBarActive() {
|
||||
View searchbarResults = searchBarResultsRef.get();
|
||||
return searchbarResults != null && searchbarResults.getParent() != null;
|
||||
return searchbarResults != null && searchbarResults.isShown();
|
||||
}
|
||||
|
||||
public static boolean isBackButtonVisible() {
|
||||
@@ -277,12 +279,14 @@ public final class NavigationBar {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the bundled non cairo filled icon instead of a custom icon.
|
||||
* Use the old non cairo filled icon, which is almost identical to
|
||||
* the what would be the filled cairo icon.
|
||||
* Custom cairo notification filled icon to fix unpatched app missing resource.
|
||||
*/
|
||||
private static final int fillBellCairoBlack = Utils.getResourceIdentifier(
|
||||
"yt_fill_bell_black_24", "drawable");
|
||||
private static final int fillBellCairoBlack = Utils.getResourceIdentifier(ResourceType.DRAWABLE,
|
||||
// The bold cairo notification filled icon is present,
|
||||
// but YT still has not fixed the icon not associated to the enum.
|
||||
VersionCheckPatch.IS_20_31_OR_GREATER && !Settings.SETTINGS_DISABLE_BOLD_ICONS.get()
|
||||
? "yt_fill_experimental_bell_vd_theme_24"
|
||||
: "revanced_fill_bell_cairo_black_24");
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
@@ -290,13 +294,12 @@ public final class NavigationBar {
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static void setCairoNotificationFilledIcon(EnumMap enumMap, Enum tabActivityCairo) {
|
||||
if (fillBellCairoBlack != 0) {
|
||||
// Show a popup informing this fix is no longer needed to those who might care.
|
||||
if (BaseSettings.DEBUG.get() && enumMap.containsKey(tabActivityCairo)) {
|
||||
Logger.printException(() -> "YouTube fixed the cairo notification icons");
|
||||
}
|
||||
enumMap.putIfAbsent(tabActivityCairo, fillBellCairoBlack);
|
||||
// Show a popup informing this fix is no longer needed to those who might care.
|
||||
if (BaseSettings.DEBUG.get() && enumMap.containsKey(tabActivityCairo)) {
|
||||
Logger.printException(() -> "YouTube fixed the notification icons");
|
||||
}
|
||||
|
||||
enumMap.putIfAbsent(tabActivityCairo, fillBellCairoBlack);
|
||||
}
|
||||
|
||||
public enum NavigationButton {
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.extension.youtube.shared
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import app.revanced.extension.shared.ResourceType
|
||||
import app.revanced.extension.shared.Utils
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
@@ -19,13 +20,13 @@ class PlayerControlsVisibilityObserverImpl(
|
||||
* id of the direct parent of controls_layout, R.id.youtube_controls_overlay
|
||||
*/
|
||||
private val controlsLayoutParentId =
|
||||
Utils.getResourceIdentifier(activity, "youtube_controls_overlay", "id")
|
||||
Utils.getResourceIdentifier(activity, ResourceType.ID, "youtube_controls_overlay")
|
||||
|
||||
/**
|
||||
* id of R.id.controls_layout
|
||||
*/
|
||||
private val controlsLayoutId =
|
||||
Utils.getResourceIdentifier(activity, "controls_layout", "id")
|
||||
Utils.getResourceIdentifier(activity, ResourceType.ID, "controls_layout")
|
||||
|
||||
/**
|
||||
* reference to the controls layout view
|
||||
|
||||
@@ -2,7 +2,6 @@ package app.revanced.extension.youtube.shared
|
||||
|
||||
import app.revanced.extension.shared.Logger
|
||||
import app.revanced.extension.youtube.Event
|
||||
import app.revanced.extension.youtube.patches.VideoInformation
|
||||
|
||||
/**
|
||||
* Regular player type.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.youtube.sponsorblock;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -25,7 +24,6 @@ import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -34,6 +32,7 @@ import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@@ -82,7 +81,7 @@ public class SegmentPlaybackController {
|
||||
* Highlight segments have zero length as they are a point in time.
|
||||
* Draw them on screen using a fixed width bar.
|
||||
*/
|
||||
private static final int HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH = dipToPixels(7);
|
||||
private static final int HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH = Dim.dp7;
|
||||
|
||||
@Nullable
|
||||
private static String currentVideoId;
|
||||
@@ -150,9 +149,9 @@ public class SegmentPlaybackController {
|
||||
private static long skipSegmentButtonEndTime;
|
||||
@Nullable
|
||||
private static String timeWithoutSegments;
|
||||
private static int sponsorBarAbsoluteLeft;
|
||||
private static int sponsorAbsoluteBarRight;
|
||||
private static int sponsorBarThickness;
|
||||
private static int seekbarAbsoluteLeft;
|
||||
private static int seekbarAbsoluteRight;
|
||||
private static int seekbarThickness;
|
||||
|
||||
@Nullable
|
||||
private static SponsorSegment lastSegmentSkipped;
|
||||
@@ -808,14 +807,12 @@ public class SegmentPlaybackController {
|
||||
|
||||
LinearLayout mainLayout = new LinearLayout(currentContext);
|
||||
mainLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
final int dip8 = dipToPixels(8);
|
||||
final int dip16 = dipToPixels(16);
|
||||
mainLayout.setPadding(dip16, dip8, dip16, dip8);
|
||||
mainLayout.setPadding(Dim.dp16, Dim.dp8, Dim.dp16, Dim.dp8);
|
||||
mainLayout.setGravity(Gravity.CENTER);
|
||||
mainLayout.setMinimumHeight(dipToPixels(48));
|
||||
mainLayout.setMinimumHeight(Dim.dp48);
|
||||
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(20), null, null));
|
||||
Dim.roundedCorners(20), null, null));
|
||||
background.getPaint().setColor(Utils.getDialogBackgroundColor());
|
||||
mainLayout.setBackground(background);
|
||||
|
||||
@@ -910,31 +907,13 @@ public class SegmentPlaybackController {
|
||||
* injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void setSponsorBarRect(Object self) {
|
||||
try {
|
||||
Field field = self.getClass().getDeclaredField("replaceMeWithsetSponsorBarRect");
|
||||
field.setAccessible(true);
|
||||
Rect rect = (Rect) Objects.requireNonNull(field.get(self));
|
||||
setSponsorBarAbsoluteLeft(rect);
|
||||
setSponsorBarAbsoluteRight(rect);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "setSponsorBarRect failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setSponsorBarAbsoluteLeft(Rect rect) {
|
||||
final int left = rect.left;
|
||||
if (sponsorBarAbsoluteLeft != left) {
|
||||
Logger.printDebug(() -> "setSponsorBarAbsoluteLeft: " + left);
|
||||
sponsorBarAbsoluteLeft = left;
|
||||
}
|
||||
}
|
||||
|
||||
private static void setSponsorBarAbsoluteRight(Rect rect) {
|
||||
final int right = rect.right;
|
||||
if (sponsorAbsoluteBarRight != right) {
|
||||
Logger.printDebug(() -> "setSponsorBarAbsoluteRight: " + right);
|
||||
sponsorAbsoluteBarRight = right;
|
||||
public static void setSeekbarRectangle(Rect seekbarRect) {
|
||||
final int left = seekbarRect.left;
|
||||
final int right = seekbarRect.right;
|
||||
if (seekbarAbsoluteLeft != left || seekbarAbsoluteRight != right) {
|
||||
Logger.printDebug(() -> "setSeekbarRectangle left: " + left + " right: " + right);
|
||||
seekbarAbsoluteLeft = left;
|
||||
seekbarAbsoluteRight = right;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,8 +921,8 @@ public class SegmentPlaybackController {
|
||||
* injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void setSponsorBarThickness(int thickness) {
|
||||
sponsorBarThickness = thickness;
|
||||
public static void setSeekbarThickness(int thickness) {
|
||||
seekbarThickness = thickness;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -953,8 +932,7 @@ public class SegmentPlaybackController {
|
||||
public static String appendTimeWithoutSegments(String totalTime) {
|
||||
try {
|
||||
if (Settings.SB_ENABLED.get() && Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.get()
|
||||
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)
|
||||
&& !isAdProgressTextVisible()) {
|
||||
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)) {
|
||||
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages
|
||||
return "\u202D" + totalTime + timeWithoutSegments; // u202D = left to right override
|
||||
}
|
||||
@@ -982,6 +960,7 @@ public class SegmentPlaybackController {
|
||||
continue;
|
||||
}
|
||||
foundNonhighlightSegments = true;
|
||||
|
||||
long start = segment.start;
|
||||
final long end = segment.end;
|
||||
// To prevent nested segments from incorrectly counting additional time,
|
||||
@@ -1013,17 +992,17 @@ public class SegmentPlaybackController {
|
||||
* Injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void drawSponsorTimeBars(final Canvas canvas, final float posY) {
|
||||
public static void drawSegmentTimeBars(final Canvas canvas, final float posY) {
|
||||
try {
|
||||
if (segments == null || isAdProgressTextVisible()) return;
|
||||
if (segments == null) return;
|
||||
final long videoLength = VideoInformation.getVideoLength();
|
||||
if (videoLength <= 0) return;
|
||||
|
||||
final int thicknessDiv2 = sponsorBarThickness / 2; // rounds down
|
||||
final float top = posY - (sponsorBarThickness - thicknessDiv2);
|
||||
final int thicknessDiv2 = seekbarThickness / 2; // Rounds down.
|
||||
final float top = posY - (seekbarThickness - thicknessDiv2);
|
||||
final float bottom = posY + thicknessDiv2;
|
||||
final float videoMillisecondsToPixels = (1f / videoLength) * (sponsorAbsoluteBarRight - sponsorBarAbsoluteLeft);
|
||||
final float leftPadding = sponsorBarAbsoluteLeft;
|
||||
final float videoMillisecondsToPixels = (1f / videoLength) * (seekbarAbsoluteRight - seekbarAbsoluteLeft);
|
||||
final float leftPadding = seekbarAbsoluteLeft;
|
||||
|
||||
for (SponsorSegment segment : segments) {
|
||||
final float left = leftPadding + segment.start * videoMillisecondsToPixels;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.youtube.sponsorblock.objects;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings.migrateOldColorString;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -17,6 +16,7 @@ import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
|
||||
import app.revanced.extension.shared.ui.ColorDot;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class SegmentCategoryPreference extends ColorPickerPreference {
|
||||
@@ -110,7 +110,7 @@ public class SegmentCategoryPreference extends ColorPickerPreference {
|
||||
}
|
||||
|
||||
radioGroup.setOnCheckedChangeListener((group, checkedId) -> selectedDialogEntryIndex = checkedId);
|
||||
radioGroup.setPadding(dipToPixels(10), 0, dipToPixels(10), dipToPixels(10));
|
||||
radioGroup.setPadding(Dim.dp10, 0, Dim.dp10, Dim.dp10);
|
||||
return radioGroup;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,26 @@
|
||||
package app.revanced.extension.youtube.sponsorblock.ui;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class CreateSegmentButton {
|
||||
|
||||
private static final int DRAWABLE_SB_LOGO = Utils.getResourceIdentifierOrThrow(
|
||||
ResourceType.DRAWABLE, Utils.appIsUsingBoldIcons()
|
||||
? "revanced_sb_logo_bold"
|
||||
: "revanced_sb_logo"
|
||||
);
|
||||
|
||||
@Nullable
|
||||
private static PlayerControlButton instance;
|
||||
|
||||
@@ -31,6 +41,14 @@ public class CreateSegmentButton {
|
||||
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
|
||||
null
|
||||
);
|
||||
|
||||
// FIXME: Bold YT player icons are currently forced off.
|
||||
// Enable this logic when the new player icons are not forced off.
|
||||
ImageView icon = Utils.getChildViewByResourceName(controlsView,
|
||||
"revanced_sb_create_segment_button");
|
||||
if (false) {
|
||||
icon.setImageResource(DRAWABLE_SB_LOGO);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initialize failure", ex);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SponsorBlockUtils;
|
||||
@@ -44,8 +46,8 @@ public final class NewSegmentLayout extends FrameLayout {
|
||||
final int defStyleAttr, final int defStyleRes) {
|
||||
super(context, attributeSet, defStyleAttr, defStyleRes);
|
||||
|
||||
LayoutInflater.from(context).inflate(
|
||||
getResourceIdentifierOrThrow(context, "revanced_sb_new_segment", "layout"), this, true
|
||||
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(context,
|
||||
ResourceType.LAYOUT, "revanced_sb_new_segment"), this, true
|
||||
);
|
||||
|
||||
initializeButton(
|
||||
@@ -104,7 +106,7 @@ public final class NewSegmentLayout extends FrameLayout {
|
||||
*/
|
||||
private void initializeButton(final Context context, final String resourceIdentifierName,
|
||||
final ButtonOnClickHandlerFunction handler, final String debugMessage) {
|
||||
ImageButton button = findViewById(getResourceIdentifierOrThrow(context, resourceIdentifierName, "id"));
|
||||
ImageButton button = findViewById(getResourceIdentifierOrThrow(context, ResourceType.ID, resourceIdentifierName));
|
||||
|
||||
// Add ripple effect
|
||||
RippleDrawable rippleDrawable = new RippleDrawable(
|
||||
@@ -132,9 +134,7 @@ public final class NewSegmentLayout extends FrameLayout {
|
||||
|
||||
GradientDrawable backgroundDrawable = new GradientDrawable();
|
||||
backgroundDrawable.setColor(getResourceColor("skip_ad_button_background_color"));
|
||||
final float cornerRadius = squareLayout
|
||||
? 0
|
||||
: 16 * getResources().getDisplayMetrics().density;
|
||||
final float cornerRadius = squareLayout ? 0f : Dim.dp16;
|
||||
backgroundDrawable.setCornerRadius(cornerRadius);
|
||||
setBackground(backgroundDrawable);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
|
||||
@@ -57,11 +58,10 @@ public class SkipSponsorButton extends FrameLayout {
|
||||
public SkipSponsorButton(Context context, AttributeSet attributeSet, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attributeSet, defStyleAttr, defStyleRes);
|
||||
|
||||
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(context,
|
||||
"revanced_sb_skip_sponsor_button", "layout"), this, true); // layout:skip_ad_button
|
||||
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(context, ResourceType.LAYOUT, "revanced_sb_skip_sponsor_button"), this, true); // layout:skip_ad_button
|
||||
setMinimumHeight(getResourceDimensionPixelSize("ad_skip_ad_button_min_height")); // dimen:ad_skip_ad_button_min_height
|
||||
skipSponsorBtnContainer = Objects.requireNonNull(findViewById(getResourceIdentifierOrThrow(
|
||||
context, "revanced_sb_skip_sponsor_button_container", "id"))); // id:skip_ad_button_container
|
||||
context, ResourceType.ID, "revanced_sb_skip_sponsor_button_container"))); // id:skip_ad_button_container
|
||||
|
||||
background = new Paint();
|
||||
background.setColor(getResourceColor("skip_ad_button_background_color")); // color:skip_ad_button_background_color);
|
||||
@@ -72,7 +72,7 @@ public class SkipSponsorButton extends FrameLayout {
|
||||
border.setStrokeWidth(getResourceDimension("ad_skip_ad_button_border_width")); // dimen:ad_skip_ad_button_border_width);
|
||||
border.setStyle(Paint.Style.STROKE);
|
||||
|
||||
skipSponsorTextView = Objects.requireNonNull(findViewById(getResourceIdentifier(context, "revanced_sb_skip_sponsor_button_text", "id"))); // id:skip_ad_button_text;
|
||||
skipSponsorTextView = Objects.requireNonNull(findViewById(getResourceIdentifier(context, ResourceType.ID, "revanced_sb_skip_sponsor_button_text"))); // id:skip_ad_button_text;
|
||||
defaultBottomMargin = getResourceDimensionPixelSize("skip_button_default_bottom_margin"); // dimen:skip_button_default_bottom_margin
|
||||
ctaBottomMargin = getResourceDimensionPixelSize("skip_button_cta_bottom_margin"); // dimen:skip_button_cta_bottom_margin
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import android.preference.SwitchPreference;
|
||||
import android.text.InputType;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
@@ -34,6 +33,7 @@ import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
import app.revanced.extension.shared.settings.preference.ResettableEditTextPreference;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
|
||||
@@ -507,7 +507,7 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup {
|
||||
EditText editText = getEditText();
|
||||
|
||||
editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 7); // Use a smaller font to reduce text wrap.
|
||||
editText.setTextSize(14);
|
||||
|
||||
// Create a custom dialog.
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
@@ -550,7 +550,7 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup {
|
||||
| InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
||||
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
editText.setAutofillHints((String) null);
|
||||
editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 8);
|
||||
editText.setTextSize(14);
|
||||
|
||||
// Set preference listeners.
|
||||
importExport.setOnPreferenceClickListener(preference1 -> {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.extension.youtube.sponsorblock.ui;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -15,6 +16,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
|
||||
@@ -62,16 +64,17 @@ public class SponsorBlockViewController {
|
||||
|
||||
Context context = Utils.getContext();
|
||||
RelativeLayout layout = new RelativeLayout(context);
|
||||
layout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
|
||||
layout.setLayoutParams(new RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
|
||||
LayoutInflater.from(context).inflate(getResourceIdentifierOrThrow(
|
||||
"revanced_sb_inline_sponsor_overlay", "layout"), layout);
|
||||
ResourceType.LAYOUT, "revanced_sb_inline_sponsor_overlay"), layout);
|
||||
inlineSponsorOverlayRef = new WeakReference<>(layout);
|
||||
|
||||
viewGroup.addView(layout);
|
||||
viewGroup.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
|
||||
@Override
|
||||
public void onChildViewAdded(View parent, View child) {
|
||||
// ensure SB buttons and controls are always on top, otherwise the endscreen cards can cover the skip button
|
||||
// Ensure SB buttons and controls are always on top, otherwise the end-screen cards can cover the skip button.
|
||||
RelativeLayout layout = inlineSponsorOverlayRef.get();
|
||||
if (layout != null) {
|
||||
layout.bringToFront();
|
||||
@@ -83,14 +86,14 @@ public class SponsorBlockViewController {
|
||||
});
|
||||
youtubeOverlaysLayoutRef = new WeakReference<>(viewGroup);
|
||||
|
||||
skipHighlightButtonRef = new WeakReference<>(layout.findViewById(getResourceIdentifierOrThrow(
|
||||
"revanced_sb_skip_highlight_button", "id")));
|
||||
skipHighlightButtonRef = new WeakReference<>(Objects.requireNonNull(layout.findViewById(
|
||||
getResourceIdentifier(ResourceType.ID, "revanced_sb_skip_highlight_button"))));
|
||||
|
||||
skipSponsorButtonRef = new WeakReference<>(layout.findViewById(getResourceIdentifierOrThrow(
|
||||
"revanced_sb_skip_sponsor_button", "id")));
|
||||
skipSponsorButtonRef = new WeakReference<>(Objects.requireNonNull(layout.findViewById(
|
||||
getResourceIdentifier(ResourceType.ID, "revanced_sb_skip_sponsor_button"))));
|
||||
|
||||
NewSegmentLayout newSegmentLayout = layout.findViewById(getResourceIdentifierOrThrow(
|
||||
"revanced_sb_new_segment_view", "id"));
|
||||
NewSegmentLayout newSegmentLayout = Objects.requireNonNull(layout.findViewById(
|
||||
getResourceIdentifier(ResourceType.ID, "revanced_sb_new_segment_view")));
|
||||
newSegmentLayoutRef = new WeakReference<>(newSegmentLayout);
|
||||
newSegmentLayout.updateLayout();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import app.revanced.extension.shared.Logger.printDebug
|
||||
import app.revanced.extension.shared.Logger.printException
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch
|
||||
import app.revanced.extension.youtube.settings.Settings
|
||||
import app.revanced.extension.youtube.shared.PlayerType
|
||||
import app.revanced.extension.youtube.swipecontrols.controller.AudioVolumeController
|
||||
@@ -237,6 +238,8 @@ class SwipeControlsHostActivity : Activity() {
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
fun allowSwipeChangeVideo(original: Boolean): Boolean = Settings.SWIPE_CHANGE_VIDEO.get()
|
||||
fun allowSwipeChangeVideo(original: Boolean): Boolean =
|
||||
// Feature can cause crashing if forced in newer targets.
|
||||
!VersionCheckPatch.IS_20_22_OR_GREATER && Settings.SWIPE_CHANGE_VIDEO.get()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.extension.youtube.swipecontrols.controller
|
||||
import android.app.Activity
|
||||
import android.util.TypedValue
|
||||
import android.view.ViewGroup
|
||||
import app.revanced.extension.shared.ResourceType
|
||||
import app.revanced.extension.shared.Utils
|
||||
import app.revanced.extension.youtube.swipecontrols.misc.Rectangle
|
||||
import app.revanced.extension.youtube.swipecontrols.misc.applyDimension
|
||||
@@ -56,7 +57,8 @@ class SwipeZonesController(
|
||||
/**
|
||||
* id for R.id.player_view
|
||||
*/
|
||||
private val playerViewId = Utils.getResourceIdentifier(host, "player_view", "id")
|
||||
private val playerViewId = Utils.getResourceIdentifier(
|
||||
host, ResourceType.ID, "player_view")
|
||||
|
||||
/**
|
||||
* current bounding rectangle of the player
|
||||
|
||||
@@ -14,12 +14,13 @@ import android.util.AttributeSet
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import app.revanced.extension.shared.ResourceType
|
||||
import app.revanced.extension.shared.StringRef.str
|
||||
import app.revanced.extension.shared.Utils
|
||||
import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider
|
||||
import app.revanced.extension.youtube.swipecontrols.misc.SwipeControlsOverlay
|
||||
import kotlin.math.min
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.round
|
||||
|
||||
/**
|
||||
@@ -53,7 +54,7 @@ class SwipeControlsOverlayLayout(
|
||||
// Function to retrieve drawable resources by name.
|
||||
private fun getDrawable(name: String): Drawable {
|
||||
val drawable = resources.getDrawable(
|
||||
Utils.getResourceIdentifier(context, name, "drawable"),
|
||||
Utils.getResourceIdentifier(context, ResourceType.DRAWABLE, name),
|
||||
context.theme,
|
||||
)
|
||||
drawable.setTint(config.overlayTextColor)
|
||||
@@ -86,7 +87,7 @@ class SwipeControlsOverlayLayout(
|
||||
|
||||
// Initialize horizontal progress bar.
|
||||
val screenWidth = resources.displayMetrics.widthPixels
|
||||
val layoutWidth = (screenWidth * 4 / 5).toInt() // Cap at ~360dp.
|
||||
val layoutWidth = (screenWidth * 4 / 5) // Cap at ~360dp.
|
||||
horizontalProgressView = HorizontalProgressView(
|
||||
context,
|
||||
config.overlayBackgroundOpacity,
|
||||
@@ -630,7 +631,7 @@ class VerticalProgressView(
|
||||
if (isMinimalStyle) {
|
||||
canvas.drawText(displayText, textX, textStartY, textPaint)
|
||||
} else {
|
||||
val progressStartY = (iconEndY + padding).toFloat()
|
||||
val progressStartY = (iconEndY + padding)
|
||||
val progressEndY = textStartY - textPaint.textSize - padding
|
||||
val progressHeight = progressEndY - progressStartY
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@ package app.revanced.extension.youtube.videoplayer;
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -14,9 +17,9 @@ public class LoopVideoButton {
|
||||
private static PlayerControlButton instance;
|
||||
|
||||
private static final int LOOP_VIDEO_ON = Utils.getResourceIdentifierOrThrow(
|
||||
"revanced_loop_video_button_on", "drawable");
|
||||
ResourceType.DRAWABLE, "revanced_loop_video_button_on");
|
||||
private static final int LOOP_VIDEO_OFF = Utils.getResourceIdentifierOrThrow(
|
||||
"revanced_loop_video_button_off", "drawable");
|
||||
ResourceType.DRAWABLE,"revanced_loop_video_button_off");
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.extension.youtube.videoplayer;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
import static app.revanced.extension.shared.settings.preference.CustomDialogListPreference.*;
|
||||
import static app.revanced.extension.youtube.patches.VideoInformation.AUTOMATIC_VIDEO_QUALITY_VALUE;
|
||||
import static app.revanced.extension.youtube.patches.VideoInformation.VIDEO_QUALITY_PREMIUM_NAME;
|
||||
@@ -21,6 +20,7 @@ import android.widget.*;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.shared.ui.SheetBottomDialog;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
|
||||
@@ -30,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch;
|
||||
@@ -214,11 +215,6 @@ public class VideoQualityDialogButton {
|
||||
}
|
||||
}
|
||||
|
||||
// Preset size constants.
|
||||
final int dip8 = dipToPixels(8);
|
||||
final int dip12 = dipToPixels(12);
|
||||
final int dip16 = dipToPixels(16);
|
||||
|
||||
// Create main layout.
|
||||
SheetBottomDialog.DraggableLinearLayout mainLayout =
|
||||
SheetBottomDialog.createMainLayout(context, getDialogBackgroundColor());
|
||||
@@ -269,7 +265,7 @@ public class VideoQualityDialogButton {
|
||||
LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
titleParams.setMargins(dip12, dip16, 0, dip16);
|
||||
titleParams.setMargins(Dim.dp12, Dim.dp16, 0, Dim.dp16);
|
||||
titleView.setLayoutParams(titleParams);
|
||||
mainLayout.addView(titleView);
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.45.0-dev.5
|
||||
version = liso-6.0.0-dev.1
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
[versions]
|
||||
revanced-patcher = "21.0.0"
|
||||
revanced-patcher = "22.0.0"
|
||||
# Tracking https://github.com/google/smali/issues/64.
|
||||
#noinspection GradleDependency
|
||||
smali = "3.0.5"
|
||||
smali = "3.0.8"
|
||||
# 8.3.0 causes java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818.
|
||||
#noinspection GradleDependency
|
||||
agp = "8.2.2"
|
||||
annotation = "1.9.1"
|
||||
appcompat = "1.7.0"
|
||||
okhttp = "5.0.0-alpha.14"
|
||||
retrofit = "2.11.0"
|
||||
appcompat = "1.7.1"
|
||||
okhttp = "5.3.2"
|
||||
retrofit = "3.0.0"
|
||||
guava = "33.5.0-jre"
|
||||
protobuf-javalite = "4.32.0"
|
||||
protoc = "4.32.0"
|
||||
protobuf-javalite = "4.33.1"
|
||||
protoc = "4.33.1"
|
||||
protobuf = "0.9.5"
|
||||
antlr4 = "4.13.2"
|
||||
nanohttpd = "2.3.1"
|
||||
apksig = "8.10.1"
|
||||
apksig = "8.12.3"
|
||||
|
||||
[libraries]
|
||||
annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Mon Jun 16 14:39:32 CEST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -68,10 +68,6 @@ public final class app/revanced/patches/all/misc/debugging/EnableAndroidDebuggin
|
||||
public static final fun getEnableAndroidDebuggingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/misc/directory/ChangeDataDirectoryLocationPatchKt {
|
||||
public static final fun getChangeDataDirectoryLocationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatchKt {
|
||||
public static final fun getExportInternalDataDocumentsProviderPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
@@ -156,10 +152,6 @@ public final class app/revanced/patches/angulus/ads/RemoveAdsPatchKt {
|
||||
public static final fun getAngulusPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/backdrops/misc/pro/ProUnlockPatchKt {
|
||||
public static final fun getProUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/bandcamp/limitations/RemovePlayLimitsPatchKt {
|
||||
public static final fun getRemovePlayLimitsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -240,10 +232,6 @@ public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatc
|
||||
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlephotos/misc/preferences/RestoreHiddenBackUpWhileChargingTogglePatchKt {
|
||||
public static final fun getRestoreHiddenBackUpWhileChargingTogglePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictionsKt {
|
||||
public static final fun getRemoveDeviceRestrictionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -276,6 +264,10 @@ public final class app/revanced/patches/instagram/feed/LimitFeedToFollowedProfil
|
||||
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 static final fun getHideExploreFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -316,6 +308,10 @@ public final class app/revanced/patches/instagram/misc/signature/SignatureCheckP
|
||||
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 static final fun getRemoveAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -348,14 +344,6 @@ public final class app/revanced/patches/messenger/inbox/HideInboxSubtabsPatchKt
|
||||
public static final fun getHideInboxSubtabsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatchKt {
|
||||
public static final fun getDisableSwitchingEmojiToStickerPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatchKt {
|
||||
public static final fun getDisableTypingIndicatorPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/messenger/layout/HideFacebookButtonPatchKt {
|
||||
public static final fun getHideFacebookButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -368,14 +356,6 @@ public final class app/revanced/patches/messenger/misc/extension/ExtensionPatchK
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/messenger/navbar/RemoveMetaAITabPatchKt {
|
||||
public static final fun getRemoveMetaAITabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/meta/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatchKt {
|
||||
public static final fun getForceEnglishLocalePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -396,22 +376,22 @@ public final class app/revanced/patches/music/interaction/permanentrepeat/Perman
|
||||
public static final fun getPermanentRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatchKt {
|
||||
public static final fun getPermanentShufflePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/branding/CustomBrandingPatchKt {
|
||||
public static final fun getCustomBrandingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/castbutton/HideCastButtonKt {
|
||||
public static final fun getHideCastButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public final class app/revanced/patches/music/layout/buttons/HideButtonsKt {
|
||||
public static final fun getHideButtons ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/compactheader/HideCategoryBarKt {
|
||||
public static final fun getHideCategoryBar ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColorKt {
|
||||
public static final fun getChangeMiniplayerColor ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/navigationbar/NavigationBarPatchKt {
|
||||
public static final fun getNavigationBarPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -424,11 +404,6 @@ public final class app/revanced/patches/music/layout/theme/ThemePatchKt {
|
||||
public static final fun getThemePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/upgradebutton/HideUpgradeButtonPatchKt {
|
||||
public static final fun getHideUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getRemoveUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatchKt {
|
||||
public static final fun getBypassCertificateChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -509,10 +484,6 @@ public final class app/revanced/patches/netguard/broadcasts/removerestriction/Re
|
||||
public static final fun getRemoveBroadcastsRestrictionPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/nunl/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -521,10 +492,6 @@ public final class app/revanced/patches/nunl/firebase/SpoofCertificatePatchKt {
|
||||
public static final fun getSpoofCertificatePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/nyx/misc/pro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatchKt {
|
||||
public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -751,16 +718,11 @@ public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/
|
||||
public static final fun getFixVideoDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatchKt {
|
||||
public static final fun getFixVideoDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatchKt {
|
||||
public static final fun getDisableScreenshotPopupPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatchKt {
|
||||
public static final fun getUnlockPremiumIconPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getUnlockPremiumIconsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -798,27 +760,24 @@ public final class app/revanced/patches/shared/misc/extension/ExtensionHook {
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/extension/SharedExtensionPatchKt {
|
||||
public static final fun activityOnCreateExtensionHook (Ljava/lang/String;)Lkotlin/jvm/functions/Function0;
|
||||
public static final fun extensionHook (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lapp/revanced/patcher/Fingerprint;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
|
||||
public static final fun extensionHook (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
|
||||
public static final fun extensionHook (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function0;
|
||||
public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lapp/revanced/patcher/Fingerprint;ILjava/lang/Object;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
|
||||
public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook;
|
||||
public static final fun sharedExtensionPatch (Ljava/lang/String;[Lapp/revanced/patches/shared/misc/extension/ExtensionHook;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun sharedExtensionPatch ([Lapp/revanced/patches/shared/misc/extension/ExtensionHook;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function0;
|
||||
public static final fun sharedExtensionPatch (Ljava/lang/String;[Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun sharedExtensionPatch ([Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatchKt {
|
||||
public static final fun getVerticalScrollPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/gms/FingerprintsKt {
|
||||
public static final field GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/gms/GmsCoreSupportPatchKt {
|
||||
public static final fun gmsCoreSupportPatch (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static synthetic fun gmsCoreSupportPatch$default (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/hex/HexPatchBuilder : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
@@ -857,23 +816,64 @@ public final class app/revanced/patches/shared/misc/hex/Replacement {
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/mapping/ResourceElement {
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;J)V
|
||||
public final fun component1 ()Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()J
|
||||
public final fun copy (Ljava/lang/String;Ljava/lang/String;J)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patches/shared/misc/mapping/ResourceElement;Ljava/lang/String;Ljava/lang/String;JILjava/lang/Object;)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
|
||||
public final fun copy (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;J)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patches/shared/misc/mapping/ResourceElement;Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;JILjava/lang/Object;)Lapp/revanced/patches/shared/misc/mapping/ResourceElement;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getId ()J
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getType ()Ljava/lang/String;
|
||||
public final fun getType ()Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatchKt {
|
||||
public static final fun get (Ljava/util/List;Ljava/lang/String;Ljava/lang/String;)J
|
||||
public static final fun getResourceElements ()Ljava/util/Collection;
|
||||
public static final fun getResourceId (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;)J
|
||||
public static final fun getResourceMappingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun getResourceMappings ()Ljava/util/List;
|
||||
public static final fun hasResourceId (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;)Z
|
||||
public static final fun resourceLiteral (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter;
|
||||
public static synthetic fun resourceLiteral$default (Lapp/revanced/patches/shared/misc/mapping/ResourceType;Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/mapping/ResourceType : java/lang/Enum {
|
||||
public static final field ANIM Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field ANIMATOR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field ARRAY Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field ATTR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field BOOL Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field COLOR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field Companion Lapp/revanced/patches/shared/misc/mapping/ResourceType$Companion;
|
||||
public static final field DIMEN Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field DRAWABLE Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field FONT Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field FRACTION Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field ID Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field INTEGER Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field INTERPOLATOR Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field LAYOUT Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field MENU Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field MIPMAP Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field NAVIGATION Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field PLURALS Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field RAW Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field STRING Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field STYLE Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field STYLEABLE Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field TRANSITION Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field VALUES Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static final field XML Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static fun getEntries ()Lkotlin/enums/EnumEntries;
|
||||
public final fun getValue ()Ljava/lang/String;
|
||||
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
public static fun values ()[Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/mapping/ResourceType$Companion {
|
||||
public final fun fromValue (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/mapping/ResourceType;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatchKt {
|
||||
@@ -883,15 +883,15 @@ public final class app/revanced/patches/shared/misc/pairip/license/DisableLicens
|
||||
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 settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun settingsPatch (Lkotlin/Pair;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static synthetic fun settingsPatch$default (Ljava/util/List;Ljava/util/Set;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public static final field Companion Lapp/revanced/patches/shared/misc/settings/preference/BasePreference$Companion;
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getIcon ()Ljava/lang/String;
|
||||
public final fun getIconBold ()Ljava/lang/String;
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getLayout ()Ljava/lang/String;
|
||||
public final fun getSummaryKey ()Ljava/lang/String;
|
||||
@@ -915,9 +915,10 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
|
||||
|
||||
public abstract class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getIcon ()Ljava/lang/String;
|
||||
public final fun getIconBold ()Ljava/lang/String;
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getLayout ()Ljava/lang/String;
|
||||
public final fun getPreferences ()Ljava/util/Set;
|
||||
@@ -926,8 +927,8 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||
public final fun getCategories ()Ljava/util/Set;
|
||||
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||
@@ -935,8 +936,8 @@ public class app/revanced/patches/shared/misc/settings/preference/BasePreference
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen$Category : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||
public fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/PreferenceCategory;
|
||||
@@ -955,8 +956,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/InputTyp
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/IntentPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getIntent ()Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
|
||||
public fun hashCode ()I
|
||||
@@ -986,22 +987,22 @@ public final class app/revanced/patches/shared/misc/settings/preference/ListPref
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getSelectable ()Z
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/PreferenceCategory : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getPreferences ()Ljava/util/Set;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getPreferences ()Ljava/util/Set;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
@@ -1029,8 +1030,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/SummaryT
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/SwitchPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getSummaryOffKey ()Ljava/lang/String;
|
||||
public final fun getSummaryOnKey ()Ljava/lang/String;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
@@ -1038,8 +1039,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/SwitchPr
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/TextPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getInputType ()Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
@@ -1076,34 +1077,14 @@ public final class app/revanced/patches/soundcloud/offlinesync/EnableOfflineSync
|
||||
public static final fun getEnableOfflineSync ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatchKt {
|
||||
public static final fun getHideCreateButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/layout/theme/CustomThemePatchKt {
|
||||
public static final fun getCustomThemePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt {
|
||||
public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/extension/ExtensionPatchKt {
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/fix/SpoofClientPatchKt {
|
||||
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatchKt {
|
||||
public static final fun getSpoofPackageInfoPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
|
||||
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatchKt {
|
||||
public static final fun getFixFacebookLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1120,10 +1101,6 @@ public final class app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunch
|
||||
public static final fun getFixThirdPartyLaunchersWidgets ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/navbar/PremiumNavbarTabPatchKt {
|
||||
public static final fun getPremiumNavbarTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/stocard/layout/HideOffersTabPatchKt {
|
||||
public static final fun getHideOffersTabPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
@@ -1340,10 +1317,6 @@ public final class app/revanced/patches/twitter/misc/links/ChangeLinkSharingDoma
|
||||
public static final fun getChangeLinkSharingDomainPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatchKt {
|
||||
public static final fun getOpenLinksWithAppChooserPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/twitter/misc/links/SanitizeSharingLinksPatchKt {
|
||||
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1356,10 +1329,6 @@ public final class app/revanced/patches/viber/misc/navbar/HideNavigationButtonsK
|
||||
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/warnwetter/misc/firebasegetcert/FirebaseGetCertPatchKt {
|
||||
public static final fun getFirebaseGetCertPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1368,10 +1337,6 @@ public final class app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnloc
|
||||
public static final fun getPromoCodeUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/ad/general/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1393,7 +1358,6 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/interaction/doubletap/DisableChapterSkipDoubleTapPatchKt {
|
||||
public static final fun getDisableChapterSkipDoubleTapPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getDisableDoubleTapActionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -1470,15 +1434,7 @@ public final class app/revanced/patches/youtube/layout/hide/fullscreenambientmod
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatchKt {
|
||||
public static final fun getAlbumCardId ()J
|
||||
public static final fun getBarContainerHeightId ()J
|
||||
public static final fun getCrowdfundingBoxId ()J
|
||||
public static final fun getExpandButtonDownId ()J
|
||||
public static final fun getFabButtonId ()J
|
||||
public static final fun getFilterBarHeightId ()J
|
||||
public static final fun getHideLayoutComponentsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getRelatedChipCloudMarginId ()J
|
||||
public static final fun getYouTubeLogo ()J
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatchKt {
|
||||
@@ -1497,10 +1453,6 @@ public final class app/revanced/patches/youtube/layout/hide/rollingnumber/Disabl
|
||||
public static final fun getDisableRollingNumberAnimationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatchKt {
|
||||
public static final fun getHideSeekbarPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatchKt {
|
||||
public static final fun getHideShortsComponentsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1509,10 +1461,6 @@ public final class app/revanced/patches/youtube/layout/hide/signintotvpopup/Disa
|
||||
public static final fun getDisableSignInToTvPopupPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatchKt {
|
||||
public static final fun getDisableSuggestedVideoEndScreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/time/HideTimestampPatchKt {
|
||||
public static final fun getHideTimestampPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1525,14 +1473,6 @@ public final class app/revanced/patches/youtube/layout/panels/popup/PlayerPopupP
|
||||
public static final fun getPlayerPopupPanelsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatchKt {
|
||||
public static final fun getPlayerControlsBackgroundPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt {
|
||||
public static final fun getOpenVideosFullscreen ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatchKt {
|
||||
public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1587,15 +1527,6 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl
|
||||
public static final fun getDisableResumingShortsOnStartupPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt {
|
||||
public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/theme/LithoColorHookPatchKt {
|
||||
public static final fun getLithoColorHookPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getLithoColorOverrideHook ()Lkotlin/jvm/functions/Function2;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/theme/ThemePatchKt {
|
||||
public static final fun getThemePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1612,10 +1543,6 @@ public final class app/revanced/patches/youtube/misc/announcements/Announcements
|
||||
public static final fun getAnnouncementsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatchKt {
|
||||
public static final fun getAutoRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatchKt {
|
||||
public static final fun getBackgroundPlaybackPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1636,14 +1563,6 @@ public final class app/revanced/patches/youtube/misc/extension/SharedExtensionPa
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatchKt {
|
||||
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatchKt {
|
||||
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playbackspeed/FIxPlaybackSpeedWhilePlayingPatchKt {
|
||||
public static final fun getFixPlaybackSpeedWhilePlayingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1695,7 +1614,6 @@ public final class app/revanced/patches/youtube/misc/playercontrols/PlayerContro
|
||||
public final class app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatchKt {
|
||||
public static final fun getAddBottomControl ()Lkotlin/jvm/functions/Function1;
|
||||
public static final fun getPlayerControlsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getPlayerControlsResourcePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun initializeBottomControl (Ljava/lang/String;)V
|
||||
public static final fun injectVisibilityCheckCall (Ljava/lang/String;)V
|
||||
}
|
||||
@@ -1706,9 +1624,6 @@ public final class app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPa
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPatchKt {
|
||||
public static final fun getVersionCheckPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun is_19_03_or_greater ()Z
|
||||
public static final fun is_19_04_or_greater ()Z
|
||||
public static final fun is_19_16_or_greater ()Z
|
||||
public static final fun is_19_17_or_greater ()Z
|
||||
public static final fun is_19_18_or_greater ()Z
|
||||
public static final fun is_19_23_or_greater ()Z
|
||||
@@ -1733,10 +1648,20 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat
|
||||
public static final fun is_20_10_or_greater ()Z
|
||||
public static final fun is_20_14_or_greater ()Z
|
||||
public static final fun is_20_15_or_greater ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt {
|
||||
public static final fun getRemoveTrackingQueryParameterPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun is_20_19_or_greater ()Z
|
||||
public static final fun is_20_20_or_greater ()Z
|
||||
public static final fun is_20_21_or_greater ()Z
|
||||
public static final fun is_20_22_or_greater ()Z
|
||||
public static final fun is_20_26_or_greater ()Z
|
||||
public static final fun is_20_28_or_greater ()Z
|
||||
public static final fun is_20_30_or_greater ()Z
|
||||
public static final fun is_20_31_or_greater ()Z
|
||||
public static final fun is_20_34_or_greater ()Z
|
||||
public static final fun is_20_37_or_greater ()Z
|
||||
public static final fun is_20_39_or_greater ()Z
|
||||
public static final fun is_20_41_or_greater ()Z
|
||||
public static final fun is_20_45_or_greater ()Z
|
||||
public static final fun is_20_46_or_greater ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/privacy/SanitizeSharingLinksPatchKt {
|
||||
@@ -1778,10 +1703,6 @@ public final class app/revanced/patches/youtube/misc/spoof/UserAgentClientSpoofP
|
||||
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatchKt {
|
||||
public static final fun getZoomHapticsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatchKt {
|
||||
public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1790,10 +1711,6 @@ public final class app/revanced/patches/youtube/video/codecs/DisableVideoCodecsP
|
||||
public static final fun getDisableVideoCodecsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/hdr/DisableHdrPatchKt {
|
||||
public static final fun getDisableHdrPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/information/VideoInformationPatchKt {
|
||||
public static final fun getVideoInformationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun userSelectedPlaybackSpeedHook (Ljava/lang/String;Ljava/lang/String;)V
|
||||
@@ -1850,14 +1767,6 @@ public final class app/revanced/patches/youtube/video/videoid/VideoIdPatchKt {
|
||||
public static final fun hookVideoId (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatchKt {
|
||||
public static final fun getRestoreOldVideoQualityMenuPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatchKt {
|
||||
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
|
||||
public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/util/smali/ExternalLabel;)V
|
||||
@@ -1907,6 +1816,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 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 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;C)V
|
||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V
|
||||
@@ -1914,9 +1824,9 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
|
||||
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;J)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;Ljava/lang/Void;)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 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;C)V
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V
|
||||
@@ -1924,6 +1834,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;J)V
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Void;)V
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V
|
||||
public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V
|
||||
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
|
||||
|
||||
@@ -12,6 +12,12 @@ patches {
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Required due to smali, or build fails. Can be removed once smali is bumped.
|
||||
implementation(libs.guava)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.all.misc.adb
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user