mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 18:03:55 +01:00
Compare commits
240 Commits
v5.10.1-de
...
v5.20.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e490a422 | ||
|
|
b4e8540bbc | ||
|
|
775c1baec2 | ||
|
|
9419fb8ec4 | ||
|
|
c510931eb0 | ||
|
|
7160699384 | ||
|
|
9db67a6eb2 | ||
|
|
e684d87dd3 | ||
|
|
2d1752a1eb | ||
|
|
c9ff7092fe | ||
|
|
d451bc6d6d | ||
|
|
741fd36872 | ||
|
|
517f8cf59a | ||
|
|
b78fb24435 | ||
|
|
a3faccb21b | ||
|
|
5f0fddc122 | ||
|
|
854a18ff72 | ||
|
|
b994a16bdc | ||
|
|
f68d06dbf3 | ||
|
|
04c6a2e5f4 | ||
|
|
e6ae55fa99 | ||
|
|
fb62474ff4 | ||
|
|
e084f01fd0 | ||
|
|
d573386e0f | ||
|
|
0f3aeb35e5 | ||
|
|
e30f593af0 | ||
|
|
df965b8a9b | ||
|
|
654587a75e | ||
|
|
9956833781 | ||
|
|
c585b26188 | ||
|
|
de0d11fcfb | ||
|
|
d321504fcf | ||
|
|
6005c97bf5 | ||
|
|
e404d84c83 | ||
|
|
1abed31968 | ||
|
|
a75a88d3c6 | ||
|
|
3d67d90473 | ||
|
|
fa1e137a43 | ||
|
|
ac71a53c73 | ||
|
|
0bff207efc | ||
|
|
e1a8b388a5 | ||
|
|
628d18489c | ||
|
|
36772b8b2e | ||
|
|
49c849979f | ||
|
|
0bdb8cdf2b | ||
|
|
2035c9e2e9 | ||
|
|
7cb38fd3fc | ||
|
|
8ed9d5bf08 | ||
|
|
cd467d6244 | ||
|
|
fdefb67d02 | ||
|
|
5274cd18f0 | ||
|
|
3d68c06146 | ||
|
|
ef3d5bafd5 | ||
|
|
2d7b1b09af | ||
|
|
0572d48fde | ||
|
|
37984b8b99 | ||
|
|
6e63193f06 | ||
|
|
b2384b22a5 | ||
|
|
ccb76983ff | ||
|
|
318b55b8fe | ||
|
|
49ade9efbc | ||
|
|
d77515bd68 | ||
|
|
087bf1e152 | ||
|
|
c2994d583d | ||
|
|
127b0a63fe | ||
|
|
27aafd0ee1 | ||
|
|
49c54c0e54 | ||
|
|
842ba4fc4d | ||
|
|
66ecadce4f | ||
|
|
73ca04da5e | ||
|
|
a5d26208c1 | ||
|
|
497291c478 | ||
|
|
b24278a544 | ||
|
|
135f9ead3c | ||
|
|
ca4f960171 | ||
|
|
7f228cc535 | ||
|
|
bf91e127d8 | ||
|
|
f07fc1ad93 | ||
|
|
c84be120bd | ||
|
|
e67f390e2b | ||
|
|
4d910fea93 | ||
|
|
72adbe5519 | ||
|
|
54d49b774e | ||
|
|
283bb31567 | ||
|
|
2724fcbd27 | ||
|
|
7c28193579 | ||
|
|
cd1ee814c4 | ||
|
|
d9ccd73b5f | ||
|
|
5c5a1e4b8b | ||
|
|
66a2ee2416 | ||
|
|
d8c276cf96 | ||
|
|
d5845abd08 | ||
|
|
54eef22ce7 | ||
|
|
e287bdc59d | ||
|
|
20a82ef956 | ||
|
|
1e29da9e06 | ||
|
|
56e6a90a90 | ||
|
|
76d32e21c2 | ||
|
|
54a7afa540 | ||
|
|
ef86438bac | ||
|
|
0683cedac0 | ||
|
|
35753410aa | ||
|
|
df838ed91d | ||
|
|
8e494d26d4 | ||
|
|
7d834e5421 | ||
|
|
60a31cf4e1 | ||
|
|
edb8bd66bc | ||
|
|
04a170054e | ||
|
|
79e6349a69 | ||
|
|
bbf3a34a2f | ||
|
|
1db7c49514 | ||
|
|
ef0506a4f8 | ||
|
|
9b38da35ff | ||
|
|
afdb771066 | ||
|
|
1b2b536d2e | ||
|
|
f39e70c648 | ||
|
|
556acdd9c1 | ||
|
|
7adfc637dc | ||
|
|
9cc0c075ad | ||
|
|
ead11e7f46 | ||
|
|
e9bc201641 | ||
|
|
99baedf355 | ||
|
|
0338d0acd3 | ||
|
|
99879f6e0a | ||
|
|
f0c70de602 | ||
|
|
737ae07a06 | ||
|
|
2c51de59de | ||
|
|
df3dc1c0b2 | ||
|
|
074c948581 | ||
|
|
2a88b1f895 | ||
|
|
ee5c830df8 | ||
|
|
e63a4b31f3 | ||
|
|
8d0bca3b03 | ||
|
|
c162d65d5b | ||
|
|
67dcd091c4 | ||
|
|
ac5ce2d67f | ||
|
|
4b78d056fd | ||
|
|
f8c901b2c1 | ||
|
|
2a67c312e1 | ||
|
|
a7eed30f46 | ||
|
|
e2de2d8d44 | ||
|
|
7ebbf356c0 | ||
|
|
2ced5c6e2a | ||
|
|
4a090ba659 | ||
|
|
cb609a6d9d | ||
|
|
42e6de9e8f | ||
|
|
c4a5b9a28c | ||
|
|
c86c85947f | ||
|
|
cbbf474c50 | ||
|
|
f147b7b73d | ||
|
|
fb8dbb4723 | ||
|
|
1e0d27e689 | ||
|
|
a2185bce09 | ||
|
|
1b60a72ede | ||
|
|
12b4ee04ad | ||
|
|
f9a6cc96de | ||
|
|
93ea250bf3 | ||
|
|
fdb946a2cc | ||
|
|
7cc939ab03 | ||
|
|
228d72428d | ||
|
|
4db7ab4207 | ||
|
|
329f993024 | ||
|
|
7cd1fb22d8 | ||
|
|
ae111bc0b9 | ||
|
|
79f1dfd3e8 | ||
|
|
f5dd902915 | ||
|
|
10e2b08eb2 | ||
|
|
4ae1155e51 | ||
|
|
69fbfaea19 | ||
|
|
f44fede67c | ||
|
|
3c52ab8017 | ||
|
|
d1641a6e3d | ||
|
|
09773e8934 | ||
|
|
d77d5bfbdd | ||
|
|
a84bded9e7 | ||
|
|
e664a24f73 | ||
|
|
5bf964fff6 | ||
|
|
0c0bbb8713 | ||
|
|
8afe48cd92 | ||
|
|
dde8ea31cb | ||
|
|
d3abbe3e93 | ||
|
|
c8179776ed | ||
|
|
c6c6516b12 | ||
|
|
d6eae01e12 | ||
|
|
ba88603f4b | ||
|
|
d5aab3d464 | ||
|
|
fca2f70c0e | ||
|
|
348f7e12cb | ||
|
|
b6b7208eeb | ||
|
|
a2c79f1349 | ||
|
|
4f5bb3c915 | ||
|
|
4b77d27c77 | ||
|
|
7991c80129 | ||
|
|
6baf4ea2ac | ||
|
|
c89538c8f5 | ||
|
|
94fb367618 | ||
|
|
354835966d | ||
|
|
168f9b769e | ||
|
|
e4c4b3a73a | ||
|
|
fce98b4960 | ||
|
|
839aa81e9c | ||
|
|
905bb0ea5f | ||
|
|
a94a663859 | ||
|
|
04b37dd55a | ||
|
|
2382e9d09e | ||
|
|
97f504976a | ||
|
|
0a6c5158e0 | ||
|
|
a959d798e8 | ||
|
|
39a0b9bda6 | ||
|
|
92c38b2cb4 | ||
|
|
4732210d4b | ||
|
|
f30a49f1cb | ||
|
|
bcd157dd2b | ||
|
|
d299ea5973 | ||
|
|
a20021e290 | ||
|
|
373ca966f3 | ||
|
|
12de922afa | ||
|
|
580bb3cf6c | ||
|
|
421af92f4c | ||
|
|
4d03e1b5a1 | ||
|
|
24d68df6cd | ||
|
|
e9aee17746 | ||
|
|
7c4285e3e6 | ||
|
|
e3110271a7 | ||
|
|
0079eceb87 | ||
|
|
af2a97cb16 | ||
|
|
aeb552e8f2 | ||
|
|
6e936fea42 | ||
|
|
f63769f39f | ||
|
|
1c9ab20a63 | ||
|
|
cdeccad908 | ||
|
|
399889c6fa | ||
|
|
ec77861410 | ||
|
|
b5afc6d827 | ||
|
|
b7ebfddf65 | ||
|
|
2742aca48b | ||
|
|
14ca4d3288 | ||
|
|
a06c0318bf | ||
|
|
7f9f668435 | ||
|
|
76fd33ca54 |
2
.github/workflows/pull_strings.yml
vendored
2
.github/workflows/pull_strings.yml
vendored
@@ -2,7 +2,7 @@ name: Pull strings
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 */6 * * *"
|
||||
- cron: "0 */12 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
758
CHANGELOG.md
758
CHANGELOG.md
@@ -1,3 +1,761 @@
|
||||
# [5.20.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.2...v5.20.0-dev.3) (2025-04-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Remove background playback restrictions:** Restore PiP button functionality after screen is unlocked ([6837348](https://github.com/ReVanced/revanced-patches/commit/6837348c45156d6743a63fef8b6e045087afbda8))
|
||||
|
||||
# [5.20.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.1...v5.20.0-dev.2) (2025-04-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify - Custom theme:** Add option to use unmodified player background gradient ([#4741](https://github.com/ReVanced/revanced-patches/issues/4741)) ([0ee3693](https://github.com/ReVanced/revanced-patches/commit/0ee36939f43f325afca37119db1cf1af3b63be27))
|
||||
|
||||
# [5.20.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.19.1...v5.20.0-dev.1) (2025-04-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Set target SDK version 34` patch (Disable edge-to-edge display) ([#4780](https://github.com/ReVanced/revanced-patches/issues/4780)) ([dcf6178](https://github.com/ReVanced/revanced-patches/commit/dcf6178f19f86dd1b57d54c855b8c47b086dd33a))
|
||||
|
||||
## [5.19.1](https://github.com/ReVanced/revanced-patches/compare/v5.19.0...v5.19.1) (2025-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos:** Restore patching with ReVanced Manager ([#4773](https://github.com/ReVanced/revanced-patches/issues/4773)) ([3e18e86](https://github.com/ReVanced/revanced-patches/commit/3e18e868bbd9fd0600fe81a7fe8767b4bd89a00e))
|
||||
* **Spotify:** Restore patching with ReVanced Manager ([#4769](https://github.com/ReVanced/revanced-patches/issues/4769)) ([89d44da](https://github.com/ReVanced/revanced-patches/commit/89d44da171c3f56f13112d1d82bc4ea4a56c7c06))
|
||||
|
||||
## [5.19.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.19.1-dev.1...v5.19.1-dev.2) (2025-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos:** Restore patching with ReVanced Manager ([#4773](https://github.com/ReVanced/revanced-patches/issues/4773)) ([3e18e86](https://github.com/ReVanced/revanced-patches/commit/3e18e868bbd9fd0600fe81a7fe8767b4bd89a00e))
|
||||
|
||||
## [5.19.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.19.0...v5.19.1-dev.1) (2025-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify:** Restore patching with ReVanced Manager ([#4769](https://github.com/ReVanced/revanced-patches/issues/4769)) ([89d44da](https://github.com/ReVanced/revanced-patches/commit/89d44da171c3f56f13112d1d82bc4ea4a56c7c06))
|
||||
|
||||
# [5.19.0](https://github.com/ReVanced/revanced-patches/compare/v5.18.0...v5.19.0) (2025-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos - Restore hidden 'Back up while charging' toggle:** Constrain to last working app target ([#4761](https://github.com/ReVanced/revanced-patches/issues/4761)) ([152bb7c](https://github.com/ReVanced/revanced-patches/commit/152bb7c3ee7cf36bc07460e7a3444631ec540441))
|
||||
* **Google Photos:** Remove obsolete non functional patch `Restore hidden 'Back up while charging' toggle` ([#4764](https://github.com/ReVanced/revanced-patches/issues/4764)) ([56e48f4](https://github.com/ReVanced/revanced-patches/commit/56e48f4c89da51f81ff11a79a164eaa5b440690e))
|
||||
* **Spotify - Custom theme:** Override more color resources ([#4690](https://github.com/ReVanced/revanced-patches/issues/4690)) ([d7a7a0b](https://github.com/ReVanced/revanced-patches/commit/d7a7a0b982dbafa181b04f984a5f7618fb067c2a))
|
||||
* **Spotify - Unlock Spotify Premium:** Remove restrictions for Google voice assistant ([#4702](https://github.com/ReVanced/revanced-patches/issues/4702)) ([106202f](https://github.com/ReVanced/revanced-patches/commit/106202f9ebb7699c4ba4ae46b82133e35f1ac6b9))
|
||||
* **Spotify:** Remove ads sections from home ([#4722](https://github.com/ReVanced/revanced-patches/issues/4722)) ([0b9a5e7](https://github.com/ReVanced/revanced-patches/commit/0b9a5e7f89a89d971762b3539166d4f145111481))
|
||||
* **Twitter - Hide recommended users:** Make hiding work again by filtering for new entryId prefix ([#4456](https://github.com/ReVanced/revanced-patches/issues/4456)) ([ff846b0](https://github.com/ReVanced/revanced-patches/commit/ff846b0b7ef5060caaffedb08c1f901172f5b2d1))
|
||||
* **YouTube - Hide layout components:** Do not hide video description music/game links if hide horizontal shelves is enabled ([3864f35](https://github.com/ReVanced/revanced-patches/commit/3864f3550153617e23ad9979fb543d8a7fb4dc0a))
|
||||
* **YouTube - Hide player flyout menu items:** Show more detailed summary text for 'Hide Audio track' if using Android spoof client ([#4756](https://github.com/ReVanced/revanced-patches/issues/4756)) ([b67bbb2](https://github.com/ReVanced/revanced-patches/commit/b67bbb299669336addb68cf52a8ce5b39c68cec0))
|
||||
* **YouTube - Remove background playback restrictions:** Do not show media controls when playing Shorts from the feed ([2ed675c](https://github.com/ReVanced/revanced-patches/commit/2ed675cdd058fb5876381a9d30dee5263f6b2e26))
|
||||
* **YouTube - Return YouTube Dislike:** Correctly update label after disliking a Short with 20.07 ([0bb3e32](https://github.com/ReVanced/revanced-patches/commit/0bb3e32244fa10809aee5c4e549f77ed4054537e))
|
||||
* **YouTube - Return YouTube Dislike:** Fix inconsistent label after disliking a Short ([ea92a2e](https://github.com/ReVanced/revanced-patches/commit/ea92a2e36c7aab3bd115f7d0ec40467179485b32))
|
||||
* **YouTube - Seekbar:** Correctly hide the feed seekbar with target 20.07 ([ddc6e4c](https://github.com/ReVanced/revanced-patches/commit/ddc6e4c34fe35fa34bd859bf34e25645a23dbdc9))
|
||||
* **YouTube:** Combine multiple seekbar patches into a single patch ([#4705](https://github.com/ReVanced/revanced-patches/issues/4705)) ([503b7eb](https://github.com/ReVanced/revanced-patches/commit/503b7eb8d413ef7f248394f128f3b2a6f3192ba6))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Angulus:** Add `Hide ads` patch ([#4604](https://github.com/ReVanced/revanced-patches/issues/4604)) ([87c86b5](https://github.com/ReVanced/revanced-patches/commit/87c86b53a91b0054ac892a3f02bbe7bf83bbf813))
|
||||
* **Messenger:** Add `Remove Meta AI tab` patch ([#4726](https://github.com/ReVanced/revanced-patches/issues/4726)) ([e3fad97](https://github.com/ReVanced/revanced-patches/commit/e3fad97484d7eb962aeb53d44a0047b34a881071))
|
||||
* **Photomath:** Support latest version ([#4672](https://github.com/ReVanced/revanced-patches/issues/4672)) ([8e16483](https://github.com/ReVanced/revanced-patches/commit/8e1648322948151e4565fb0d86e0f37d0a02d73f))
|
||||
* **Proton Mail:** Add `Remove 'Sent from' signature` patch ([#4514](https://github.com/ReVanced/revanced-patches/issues/4514)) ([34c14c9](https://github.com/ReVanced/revanced-patches/commit/34c14c9b443092824d035afd77adb678c6f89e3e))
|
||||
* **Spotify:** Add `Check environment` patch ([#4765](https://github.com/ReVanced/revanced-patches/issues/4765)) ([6d7101c](https://github.com/ReVanced/revanced-patches/commit/6d7101cb2e546e01a934eff9cad1264367aeafe3))
|
||||
* **Spotify:** Add limited support for version `8.6.98.900` (last version that supports Kenwood and Pioneer car stereos) ([#4750](https://github.com/ReVanced/revanced-patches/issues/4750)) ([a3fde87](https://github.com/ReVanced/revanced-patches/commit/a3fde874af993125ba7a741820e7bd48e3641b84))
|
||||
* **Strava - Disable subscription suggestions:** Make compatible with latest version ([#4739](https://github.com/ReVanced/revanced-patches/issues/4739)) ([649a2c0](https://github.com/ReVanced/revanced-patches/commit/649a2c06161c72a2040b179dbed5b415847d7527))
|
||||
* **YouTube - Settings:** Add icons to the ReVanced settings ([#4496](https://github.com/ReVanced/revanced-patches/issues/4496)) ([d0c85f0](https://github.com/ReVanced/revanced-patches/commit/d0c85f044083d720c63a8ea4ff15d42eefeb9db7))
|
||||
|
||||
# [5.19.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.16...v5.19.0-dev.17) (2025-04-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add `Check environment` patch ([#4765](https://github.com/ReVanced/revanced-patches/issues/4765)) ([6d7101c](https://github.com/ReVanced/revanced-patches/commit/6d7101cb2e546e01a934eff9cad1264367aeafe3))
|
||||
|
||||
# [5.19.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.15...v5.19.0-dev.16) (2025-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos:** Remove obsolete non functional patch `Restore hidden 'Back up while charging' toggle` ([#4764](https://github.com/ReVanced/revanced-patches/issues/4764)) ([56e48f4](https://github.com/ReVanced/revanced-patches/commit/56e48f4c89da51f81ff11a79a164eaa5b440690e))
|
||||
|
||||
# [5.19.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.14...v5.19.0-dev.15) (2025-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos - Restore hidden 'Back up while charging' toggle:** Constrain to last working app target ([#4761](https://github.com/ReVanced/revanced-patches/issues/4761)) ([152bb7c](https://github.com/ReVanced/revanced-patches/commit/152bb7c3ee7cf36bc07460e7a3444631ec540441))
|
||||
|
||||
# [5.19.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.13...v5.19.0-dev.14) (2025-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Unlock Spotify Premium:** Remove restrictions for Google voice assistant ([#4702](https://github.com/ReVanced/revanced-patches/issues/4702)) ([106202f](https://github.com/ReVanced/revanced-patches/commit/106202f9ebb7699c4ba4ae46b82133e35f1ac6b9))
|
||||
|
||||
# [5.19.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.12...v5.19.0-dev.13) (2025-04-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add limited support for version `8.6.98.900` (last version that supports Kenwood and Pioneer car stereos) ([#4750](https://github.com/ReVanced/revanced-patches/issues/4750)) ([a3fde87](https://github.com/ReVanced/revanced-patches/commit/a3fde874af993125ba7a741820e7bd48e3641b84))
|
||||
|
||||
# [5.19.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.11...v5.19.0-dev.12) (2025-04-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Strava - Disable subscription suggestions:** Make compatible with latest version ([#4739](https://github.com/ReVanced/revanced-patches/issues/4739)) ([649a2c0](https://github.com/ReVanced/revanced-patches/commit/649a2c06161c72a2040b179dbed5b415847d7527))
|
||||
|
||||
# [5.19.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.10...v5.19.0-dev.11) (2025-04-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Messenger:** Add `Remove Meta AI tab` patch ([#4726](https://github.com/ReVanced/revanced-patches/issues/4726)) ([e3fad97](https://github.com/ReVanced/revanced-patches/commit/e3fad97484d7eb962aeb53d44a0047b34a881071))
|
||||
|
||||
# [5.19.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.9...v5.19.0-dev.10) (2025-04-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Do not hide video description music/game links if hide horizontal shelves is enabled ([3864f35](https://github.com/ReVanced/revanced-patches/commit/3864f3550153617e23ad9979fb543d8a7fb4dc0a))
|
||||
|
||||
# [5.19.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.8...v5.19.0-dev.9) (2025-04-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide player flyout menu items:** Show more detailed summary text for 'Hide Audio track' if using Android spoof client ([#4756](https://github.com/ReVanced/revanced-patches/issues/4756)) ([b67bbb2](https://github.com/ReVanced/revanced-patches/commit/b67bbb299669336addb68cf52a8ce5b39c68cec0))
|
||||
|
||||
# [5.19.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.7...v5.19.0-dev.8) (2025-04-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Return YouTube Dislike:** Fix inconsistent label after disliking a Short ([ea92a2e](https://github.com/ReVanced/revanced-patches/commit/ea92a2e36c7aab3bd115f7d0ec40467179485b32))
|
||||
|
||||
# [5.19.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.6...v5.19.0-dev.7) (2025-04-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Return YouTube Dislike:** Correctly update label after disliking a Short with 20.07 ([0bb3e32](https://github.com/ReVanced/revanced-patches/commit/0bb3e32244fa10809aee5c4e549f77ed4054537e))
|
||||
|
||||
# [5.19.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.5...v5.19.0-dev.6) (2025-04-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify:** Remove ads sections from home ([#4722](https://github.com/ReVanced/revanced-patches/issues/4722)) ([0b9a5e7](https://github.com/ReVanced/revanced-patches/commit/0b9a5e7f89a89d971762b3539166d4f145111481))
|
||||
|
||||
# [5.19.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.4...v5.19.0-dev.5) (2025-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Custom theme:** Override more color resources ([#4690](https://github.com/ReVanced/revanced-patches/issues/4690)) ([d7a7a0b](https://github.com/ReVanced/revanced-patches/commit/d7a7a0b982dbafa181b04f984a5f7618fb067c2a))
|
||||
|
||||
# [5.19.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.3...v5.19.0-dev.4) (2025-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Seekbar:** Correctly hide the feed seekbar with target 20.07 ([ddc6e4c](https://github.com/ReVanced/revanced-patches/commit/ddc6e4c34fe35fa34bd859bf34e25645a23dbdc9))
|
||||
|
||||
# [5.19.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.2...v5.19.0-dev.3) (2025-04-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Proton Mail:** Add `Remove 'Sent from' signature` patch ([#4514](https://github.com/ReVanced/revanced-patches/issues/4514)) ([34c14c9](https://github.com/ReVanced/revanced-patches/commit/34c14c9b443092824d035afd77adb678c6f89e3e))
|
||||
|
||||
# [5.19.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.1...v5.19.0-dev.2) (2025-04-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Settings:** Add icons to the ReVanced settings ([#4496](https://github.com/ReVanced/revanced-patches/issues/4496)) ([d0c85f0](https://github.com/ReVanced/revanced-patches/commit/d0c85f044083d720c63a8ea4ff15d42eefeb9db7))
|
||||
|
||||
# [5.19.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.18.1-dev.2...v5.19.0-dev.1) (2025-04-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Twitter - Hide recommended users:** Make hiding work again by filtering for new entryId prefix ([#4456](https://github.com/ReVanced/revanced-patches/issues/4456)) ([ff846b0](https://github.com/ReVanced/revanced-patches/commit/ff846b0b7ef5060caaffedb08c1f901172f5b2d1))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Angulus:** Add `Hide ads` patch ([#4604](https://github.com/ReVanced/revanced-patches/issues/4604)) ([87c86b5](https://github.com/ReVanced/revanced-patches/commit/87c86b53a91b0054ac892a3f02bbe7bf83bbf813))
|
||||
* **Photomath:** Support latest version ([#4672](https://github.com/ReVanced/revanced-patches/issues/4672)) ([8e16483](https://github.com/ReVanced/revanced-patches/commit/8e1648322948151e4565fb0d86e0f37d0a02d73f))
|
||||
|
||||
## [5.18.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.18.1-dev.1...v5.18.1-dev.2) (2025-04-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Combine multiple seekbar patches into a single patch ([#4705](https://github.com/ReVanced/revanced-patches/issues/4705)) ([503b7eb](https://github.com/ReVanced/revanced-patches/commit/503b7eb8d413ef7f248394f128f3b2a6f3192ba6))
|
||||
|
||||
## [5.18.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.18.0...v5.18.1-dev.1) (2025-03-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Remove background playback restrictions:** Do not show media controls when playing Shorts from the feed ([2ed675c](https://github.com/ReVanced/revanced-patches/commit/2ed675cdd058fb5876381a9d30dee5263f6b2e26))
|
||||
|
||||
# [5.18.0](https://github.com/ReVanced/revanced-patches/compare/v5.17.0...v5.18.0) (2025-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify:** Ignore optional attributes if not present ([#4688](https://github.com/ReVanced/revanced-patches/issues/4688)) ([84f5854](https://github.com/ReVanced/revanced-patches/commit/84f585492e4be3604c6c7680ffb3bebcea5a675f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `20.07.39` ([#4677](https://github.com/ReVanced/revanced-patches/issues/4677)) ([c1379f6](https://github.com/ReVanced/revanced-patches/commit/c1379f6e520c683d2c9d6a490a69ca542168b3b3))
|
||||
|
||||
# [5.18.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.18.0-dev.1...v5.18.0-dev.2) (2025-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify:** Ignore optional attributes if not present ([#4688](https://github.com/ReVanced/revanced-patches/issues/4688)) ([84f5854](https://github.com/ReVanced/revanced-patches/commit/84f585492e4be3604c6c7680ffb3bebcea5a675f))
|
||||
|
||||
# [5.18.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.17.0...v5.18.0-dev.1) (2025-03-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `20.07.39` ([#4677](https://github.com/ReVanced/revanced-patches/issues/4677)) ([c1379f6](https://github.com/ReVanced/revanced-patches/commit/c1379f6e520c683d2c9d6a490a69ca542168b3b3))
|
||||
|
||||
# [5.17.0](https://github.com/ReVanced/revanced-patches/compare/v5.16.1...v5.17.0) (2025-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Facebook - Hide 'Sponsored Stories':** Constrain patch to latest compatible version ([#4657](https://github.com/ReVanced/revanced-patches/issues/4657)) ([46bd1c8](https://github.com/ReVanced/revanced-patches/commit/46bd1c829acd5f83600025e0ceb7d482ae80be69))
|
||||
* **Spotify - Unlock Premium:** Override additional attributes ([#4651](https://github.com/ReVanced/revanced-patches/issues/4651)) ([568b40d](https://github.com/ReVanced/revanced-patches/commit/568b40da9692eae9039bbb3cec513a61ca627c24))
|
||||
* **Spotify - Unlock Premium:** Use correct patch description convention ([a486522](https://github.com/ReVanced/revanced-patches/commit/a4865228f8481d2efc8fbf4e90902a03289d9a3f))
|
||||
* **X / Twitter:** Constrain patches to latest compatible versions ([#4683](https://github.com/ReVanced/revanced-patches/issues/4683)) ([f579728](https://github.com/ReVanced/revanced-patches/commit/f5797289f45186052537982c7f5db6f2b0769aee))
|
||||
* **YouTube - Navigation buttons:** Add user dialog message to 'Disable translucent status bar' ([a4a0e68](https://github.com/ReVanced/revanced-patches/commit/a4a0e6869e23d15ee09262460f4e290c90629eeb))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify - Unlock Premium:** Disable the "Spotify Premium" upsell experiment in context menus ([9a10ee4](https://github.com/ReVanced/revanced-patches/commit/9a10ee4d22fb53da2012a182e038749d3ad72377))
|
||||
|
||||
# [5.17.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.17.0-dev.3...v5.17.0-dev.4) (2025-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **X / Twitter:** Constrain patches to latest compatible versions ([#4683](https://github.com/ReVanced/revanced-patches/issues/4683)) ([f579728](https://github.com/ReVanced/revanced-patches/commit/f5797289f45186052537982c7f5db6f2b0769aee))
|
||||
|
||||
# [5.17.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.17.0-dev.2...v5.17.0-dev.3) (2025-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Unlock Premium:** Override additional attributes ([#4651](https://github.com/ReVanced/revanced-patches/issues/4651)) ([568b40d](https://github.com/ReVanced/revanced-patches/commit/568b40da9692eae9039bbb3cec513a61ca627c24))
|
||||
|
||||
# [5.17.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.17.0-dev.1...v5.17.0-dev.2) (2025-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Navigation buttons:** Add user dialog message to 'Disable translucent status bar' ([a4a0e68](https://github.com/ReVanced/revanced-patches/commit/a4a0e6869e23d15ee09262460f4e290c90629eeb))
|
||||
|
||||
# [5.17.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.16.2-dev.1...v5.17.0-dev.1) (2025-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Unlock Premium:** Use correct patch description convention ([a486522](https://github.com/ReVanced/revanced-patches/commit/a4865228f8481d2efc8fbf4e90902a03289d9a3f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify - Unlock Premium:** Disable the "Spotify Premium" upsell experiment in context menus ([9a10ee4](https://github.com/ReVanced/revanced-patches/commit/9a10ee4d22fb53da2012a182e038749d3ad72377))
|
||||
|
||||
## [5.16.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.16.1...v5.16.2-dev.1) (2025-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Facebook - Hide 'Sponsored Stories':** Constrain patch to latest compatible version ([#4657](https://github.com/ReVanced/revanced-patches/issues/4657)) ([46bd1c8](https://github.com/ReVanced/revanced-patches/commit/46bd1c829acd5f83600025e0ceb7d482ae80be69))
|
||||
|
||||
## [5.16.1](https://github.com/ReVanced/revanced-patches/compare/v5.16.0...v5.16.1) (2025-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Unlock Premium:** Override streaming attribute attempting to fix streaming issues ([06be36c](https://github.com/ReVanced/revanced-patches/commit/06be36cddf3430b4179dff696b3d15718cd6963b))
|
||||
|
||||
## [5.16.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.16.0...v5.16.1-dev.1) (2025-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Unlock Premium:** Override streaming attribute attempting to fix streaming issues ([06be36c](https://github.com/ReVanced/revanced-patches/commit/06be36cddf3430b4179dff696b3d15718cd6963b))
|
||||
|
||||
# [5.16.0](https://github.com/ReVanced/revanced-patches/compare/v5.15.0...v5.16.0) (2025-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Settings:** System navigation bar is located above the settings ui on Android 15+ ([f7497be](https://github.com/ReVanced/revanced-patches/commit/f7497be2c5e4abcde6eb55b84955124a28f55cae))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add `Unlock premium` patch ([#4644](https://github.com/ReVanced/revanced-patches/issues/4644)) ([f048c50](https://github.com/ReVanced/revanced-patches/commit/f048c50e56fc1f5a5c607860be4206ef83b528fe))
|
||||
* **YouTube - Comments:** Add `Hide AI Comments summary` ([#4634](https://github.com/ReVanced/revanced-patches/issues/4634)) ([e9b7f26](https://github.com/ReVanced/revanced-patches/commit/e9b7f263f739bd130f6ea79913851a52355977c5))
|
||||
* **YouTube - Video description:** Add `Hide AI-generated video summary` ([#4636](https://github.com/ReVanced/revanced-patches/issues/4636)) ([521fd48](https://github.com/ReVanced/revanced-patches/commit/521fd48602432ab436d8711c19d7130b2b05af12))
|
||||
|
||||
# [5.16.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.16.0-dev.1...v5.16.0-dev.2) (2025-03-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add `Unlock premium` patch ([#4644](https://github.com/ReVanced/revanced-patches/issues/4644)) ([f048c50](https://github.com/ReVanced/revanced-patches/commit/f048c50e56fc1f5a5c607860be4206ef83b528fe))
|
||||
|
||||
# [5.16.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.15.0...v5.16.0-dev.1) (2025-03-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Settings:** System navigation bar is located above the settings ui on Android 15+ ([f7497be](https://github.com/ReVanced/revanced-patches/commit/f7497be2c5e4abcde6eb55b84955124a28f55cae))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Comments:** Add `Hide AI Comments summary` ([#4634](https://github.com/ReVanced/revanced-patches/issues/4634)) ([e9b7f26](https://github.com/ReVanced/revanced-patches/commit/e9b7f263f739bd130f6ea79913851a52355977c5))
|
||||
* **YouTube - Video description:** Add `Hide AI-generated video summary` ([#4636](https://github.com/ReVanced/revanced-patches/issues/4636)) ([521fd48](https://github.com/ReVanced/revanced-patches/commit/521fd48602432ab436d8711c19d7130b2b05af12))
|
||||
|
||||
# [5.15.0](https://github.com/ReVanced/revanced-patches/compare/v5.14.0...v5.15.0) (2025-03-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof app version:** Change oldest spoof target to 19.01.34 ([5012439](https://github.com/ReVanced/revanced-patches/commit/5012439a8e53b2a4ab5e85c47976e1ab28a51208))
|
||||
* **YouTube - Spoof app version:** Remove broken spoof targets that YouTube no longer supports ([#4610](https://github.com/ReVanced/revanced-patches/issues/4610)) ([883fbe7](https://github.com/ReVanced/revanced-patches/commit/883fbe71233c57cb1241e57c122b43f40722acc7))
|
||||
* **YouTube:** Do not show restart prompt more than once if setting change is canceled ([49797fe](https://github.com/ReVanced/revanced-patches/commit/49797fe8d0c4a0981ef621a31356c4315ae3777b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add opacity setting to category segment colors ([#4582](https://github.com/ReVanced/revanced-patches/issues/4582)) ([6e8ffba](https://github.com/ReVanced/revanced-patches/commit/6e8ffbade9e03658f725622631e44dabf2995861))
|
||||
|
||||
# [5.15.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.15.0-dev.3...v5.15.0-dev.4) (2025-03-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof app version:** Change oldest spoof target to 19.01.34 ([5012439](https://github.com/ReVanced/revanced-patches/commit/5012439a8e53b2a4ab5e85c47976e1ab28a51208))
|
||||
|
||||
# [5.15.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.15.0-dev.2...v5.15.0-dev.3) (2025-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Do not show restart prompt more than once if setting change is canceled ([49797fe](https://github.com/ReVanced/revanced-patches/commit/49797fe8d0c4a0981ef621a31356c4315ae3777b))
|
||||
|
||||
# [5.15.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.15.0-dev.1...v5.15.0-dev.2) (2025-03-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof app version:** Remove broken spoof targets that YouTube no longer supports ([#4610](https://github.com/ReVanced/revanced-patches/issues/4610)) ([883fbe7](https://github.com/ReVanced/revanced-patches/commit/883fbe71233c57cb1241e57c122b43f40722acc7))
|
||||
|
||||
# [5.15.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.14.0...v5.15.0-dev.1) (2025-03-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add opacity setting to category segment colors ([#4582](https://github.com/ReVanced/revanced-patches/issues/4582)) ([6e8ffba](https://github.com/ReVanced/revanced-patches/commit/6e8ffbade9e03658f725622631e44dabf2995861))
|
||||
|
||||
# [5.14.0](https://github.com/ReVanced/revanced-patches/compare/v5.13.0...v5.14.0) (2025-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Boost for reddit - Client spoof:** Use a different user agent to combat Reddit's API issues ([5d3c817](https://github.com/ReVanced/revanced-patches/commit/5d3c8175b34a3f6ae2732b25db0851773a8c000d))
|
||||
* **YouTube - Change form factor:** Restore Automotive form factor watch history menu, channel pages, and community posts ([#4541](https://github.com/ReVanced/revanced-patches/issues/4541)) ([aa5c001](https://github.com/ReVanced/revanced-patches/commit/aa5c001968446e5270c756256724e917009612cd))
|
||||
* **YouTube - Hide ads:** Hide new type of buttoned ad ([#4528](https://github.com/ReVanced/revanced-patches/issues/4528)) ([4387a7b](https://github.com/ReVanced/revanced-patches/commit/4387a7b131f49729e902e008bb4cec073635c040))
|
||||
* **YouTube - Hide layout components:** Do not hide Movie/Courses start page content if 'Hide horizontal shelves' is enabled ([62a6164](https://github.com/ReVanced/revanced-patches/commit/62a6164b88b64200b517a5ba6b800d8214dbbad8))
|
||||
* **YouTube - Theme:** Resolve dark mode startup crash with Android 9.0 ([741c2d5](https://github.com/ReVanced/revanced-patches/commit/741c2d59406f5d602554bb3a3c0b8982f42848b4))
|
||||
* **YouTube:** Change language settings menu to use native language names ([#4568](https://github.com/ReVanced/revanced-patches/issues/4568)) ([6f3f8fd](https://github.com/ReVanced/revanced-patches/commit/6f3f8fdce05501e4fa4423c2170a916fbea3b199))
|
||||
* **YouTube:** Combine `Restore old video quality menu` and `Remember video quality` into `Video quality` patch ([#4552](https://github.com/ReVanced/revanced-patches/issues/4552)) ([ee67b76](https://github.com/ReVanced/revanced-patches/commit/ee67b763d5c5947a5b1ef4420b1efa820ed6af83))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Infinity for Reddit:** Add support for package name on IzzyOnDroid ([#4554](https://github.com/ReVanced/revanced-patches/issues/4554)) ([cf9f959](https://github.com/ReVanced/revanced-patches/commit/cf9f959923076c10a7f0a29f6ba277f5a055ec07))
|
||||
* **Spotify:** Add `Spoof signature` patch ([#4576](https://github.com/ReVanced/revanced-patches/issues/4576)) ([3646c70](https://github.com/ReVanced/revanced-patches/commit/3646c70556b67a6b7ecf9b86869ebf03c3611333))
|
||||
* **YouTube - Remember video quality:** Add separate Shorts default quality settings ([#4543](https://github.com/ReVanced/revanced-patches/issues/4543)) ([88142ab](https://github.com/ReVanced/revanced-patches/commit/88142ab464192b564b1b8d56a6b45663f77f5e00))
|
||||
|
||||
# [5.14.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.8...v5.14.0-dev.9) (2025-03-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add `Spoof signature` patch ([#4576](https://github.com/ReVanced/revanced-patches/issues/4576)) ([3646c70](https://github.com/ReVanced/revanced-patches/commit/3646c70556b67a6b7ecf9b86869ebf03c3611333))
|
||||
|
||||
# [5.14.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.7...v5.14.0-dev.8) (2025-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Theme:** Resolve dark mode startup crash with Android 9.0 ([741c2d5](https://github.com/ReVanced/revanced-patches/commit/741c2d59406f5d602554bb3a3c0b8982f42848b4))
|
||||
|
||||
# [5.14.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.6...v5.14.0-dev.7) (2025-03-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Change language settings menu to use native language names ([#4568](https://github.com/ReVanced/revanced-patches/issues/4568)) ([6f3f8fd](https://github.com/ReVanced/revanced-patches/commit/6f3f8fdce05501e4fa4423c2170a916fbea3b199))
|
||||
|
||||
# [5.14.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.5...v5.14.0-dev.6) (2025-03-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Do not hide Movie/Courses start page content if 'Hide horizontal shelves' is enabled ([62a6164](https://github.com/ReVanced/revanced-patches/commit/62a6164b88b64200b517a5ba6b800d8214dbbad8))
|
||||
|
||||
# [5.14.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.4...v5.14.0-dev.5) (2025-03-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Infinity for Reddit:** Add support for package name on IzzyOnDroid ([#4554](https://github.com/ReVanced/revanced-patches/issues/4554)) ([cf9f959](https://github.com/ReVanced/revanced-patches/commit/cf9f959923076c10a7f0a29f6ba277f5a055ec07))
|
||||
|
||||
# [5.14.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.3...v5.14.0-dev.4) (2025-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Combine `Restore old video quality menu` and `Remember video quality` into `Video quality` patch ([#4552](https://github.com/ReVanced/revanced-patches/issues/4552)) ([ee67b76](https://github.com/ReVanced/revanced-patches/commit/ee67b763d5c5947a5b1ef4420b1efa820ed6af83))
|
||||
|
||||
# [5.14.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.2...v5.14.0-dev.3) (2025-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Boost for reddit - Client spoof:** Use a different user agent to combat Reddit's API issues ([5d3c817](https://github.com/ReVanced/revanced-patches/commit/5d3c8175b34a3f6ae2732b25db0851773a8c000d))
|
||||
|
||||
# [5.14.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.14.0-dev.1...v5.14.0-dev.2) (2025-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide ads:** Hide new type of buttoned ad ([#4528](https://github.com/ReVanced/revanced-patches/issues/4528)) ([4387a7b](https://github.com/ReVanced/revanced-patches/commit/4387a7b131f49729e902e008bb4cec073635c040))
|
||||
|
||||
# [5.14.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.13.1-dev.1...v5.14.0-dev.1) (2025-03-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Remember video quality:** Add separate Shorts default quality settings ([#4543](https://github.com/ReVanced/revanced-patches/issues/4543)) ([88142ab](https://github.com/ReVanced/revanced-patches/commit/88142ab464192b564b1b8d56a6b45663f77f5e00))
|
||||
|
||||
## [5.13.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.13.0...v5.13.1-dev.1) (2025-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Change form factor:** Restore Automotive form factor watch history menu, channel pages, and community posts ([#4541](https://github.com/ReVanced/revanced-patches/issues/4541)) ([aa5c001](https://github.com/ReVanced/revanced-patches/commit/aa5c001968446e5270c756256724e917009612cd))
|
||||
|
||||
# [5.13.0](https://github.com/ReVanced/revanced-patches/compare/v5.12.0...v5.13.0) (2025-03-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Resolve startup app crash ([18c0fc2](https://github.com/ReVanced/revanced-patches/commit/18c0fc2a7f186f50a904fd25dbaa739abdd24993))
|
||||
* **TikTok:** Resolve startup app crash ([6466398](https://github.com/ReVanced/revanced-patches/commit/64663983b84de1f28636205f61bf0a24c83968d1))
|
||||
* **TikTok:** Resolve startup app crash ([c14bc24](https://github.com/ReVanced/revanced-patches/commit/c14bc244550de30eca975ca7c09e8eb0c47534b5))
|
||||
* **TikTok:** Resolve startup app crash ([d700076](https://github.com/ReVanced/revanced-patches/commit/d7000768a5e5a688c9f4e48858ac34e352222c1e))
|
||||
* **YouTube - Copy video URL:** Use correct button ordering ([5e622cc](https://github.com/ReVanced/revanced-patches/commit/5e622ccf66d34af31c6026fa7f4d332460c6ecb0))
|
||||
* **YouTube - Hide filter bar:** Fix `Hide in feed` not working in subscriptions feed ([#4512](https://github.com/ReVanced/revanced-patches/issues/4512)) ([634d0ee](https://github.com/ReVanced/revanced-patches/commit/634d0ee12e31491c7ee1d4ceb002daf8366a3c15))
|
||||
* **YouTube - Hide layout components:** Do not hide 'Show anyway' button in search results ([4ac8854](https://github.com/ReVanced/revanced-patches/commit/4ac8854b99808a8957f3b0b7438e1e0cdedffbaf))
|
||||
* **YouTube - Hide player components:** Show correct end video thumbnail if `Hide end screen suggested video` is enabled ([#4502](https://github.com/ReVanced/revanced-patches/issues/4502)) ([6c4885a](https://github.com/ReVanced/revanced-patches/commit/6c4885a1d5dfff50100b01840b5552d92e83ee4a))
|
||||
* **YouTube - Hide video action buttons:** Move 'Disable Like and Subscribe glow' to action buttons settings menu ([29b265d](https://github.com/ReVanced/revanced-patches/commit/29b265d8fdaa48502650be9623bfc518a57a0bb1))
|
||||
* **YouTube - Return YouTube Dislike:** Use correct number formatting if using a different ReVanced language ([edf66f4](https://github.com/ReVanced/revanced-patches/commit/edf66f4e16d46156cb8b8e31d18cb8dbcb87737e))
|
||||
* **YouTube - Spoof app version:** Force old settings menus if spoofing to older app targets ([#4490](https://github.com/ReVanced/revanced-patches/issues/4490)) ([45e7c46](https://github.com/ReVanced/revanced-patches/commit/45e7c46dd9c70c926b8b1a97ada668f90f5f6f8c))
|
||||
* **YouTube - Spoof video streams:** Resolve playback issues with dynamic player config ([#4521](https://github.com/ReVanced/revanced-patches/issues/4521)) ([647e764](https://github.com/ReVanced/revanced-patches/commit/647e7642efc0c00db17ccb6a620d1c96ccf4afed))
|
||||
* **YouTube - Swipe controls:** Adjust the overlay text size ([#4503](https://github.com/ReVanced/revanced-patches/issues/4503)) ([6dc4bf7](https://github.com/ReVanced/revanced-patches/commit/6dc4bf75e09ed6f05534919d7b769b720043abce))
|
||||
* **YouTube:** Do not hide player controls when using double tap to skip forward ([#4487](https://github.com/ReVanced/revanced-patches/issues/4487)) ([63fe870](https://github.com/ReVanced/revanced-patches/commit/63fe870d48ca2217327b952bde241b7f16ced850))
|
||||
* **YouTube:** Fix player button fade out animations ([#4469](https://github.com/ReVanced/revanced-patches/issues/4469)) ([bf8e775](https://github.com/ReVanced/revanced-patches/commit/bf8e7759f9bdbdfef419a879fb3dd7cf0dff0098))
|
||||
* **YouTube:** Resolve button flickering when taping seekbar ([#4500](https://github.com/ReVanced/revanced-patches/issues/4500)) ([1f08047](https://github.com/ReVanced/revanced-patches/commit/1f08047b48cc9555a4887d16ec7219a55a77251f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Infinity for Reddit:** Add support for Infinity for Reddit Plus ([#4511](https://github.com/ReVanced/revanced-patches/issues/4511)) ([d74732b](https://github.com/ReVanced/revanced-patches/commit/d74732b7596104321bde263201d95649e4bd0eee))
|
||||
* **NU.nl:** Add `Hide ads` and `Spoof Certificate` patch ([#4368](https://github.com/ReVanced/revanced-patches/issues/4368)) ([f3268fb](https://github.com/ReVanced/revanced-patches/commit/f3268fb03ca25fb5465e36015b6c9dec2c84a655))
|
||||
* **YouTube - Navigation buttons:** Add 'Hide notifications' setting ([#4485](https://github.com/ReVanced/revanced-patches/issues/4485)) ([506d241](https://github.com/ReVanced/revanced-patches/commit/506d2414bbc760e764e5a514b32926083d6ecb6b))
|
||||
* **YouTube - Swipe controls:** Swipe controls UI improvements ([#4422](https://github.com/ReVanced/revanced-patches/issues/4422)) ([198e4d2](https://github.com/ReVanced/revanced-patches/commit/198e4d2a2315c24a09eb9ecfefbd131a75384d2c))
|
||||
|
||||
# [5.13.0-dev.19](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.18...v5.13.0-dev.19) (2025-03-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Resolve playback issues with dynamic player config ([#4521](https://github.com/ReVanced/revanced-patches/issues/4521)) ([647e764](https://github.com/ReVanced/revanced-patches/commit/647e7642efc0c00db17ccb6a620d1c96ccf4afed))
|
||||
|
||||
# [5.13.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.17...v5.13.0-dev.18) (2025-02-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Infinity for Reddit:** Add support for Infinity for Reddit Plus ([#4511](https://github.com/ReVanced/revanced-patches/issues/4511)) ([d74732b](https://github.com/ReVanced/revanced-patches/commit/d74732b7596104321bde263201d95649e4bd0eee))
|
||||
|
||||
# [5.13.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.16...v5.13.0-dev.17) (2025-02-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide filter bar:** Fix `Hide in feed` not working in subscriptions feed ([#4512](https://github.com/ReVanced/revanced-patches/issues/4512)) ([634d0ee](https://github.com/ReVanced/revanced-patches/commit/634d0ee12e31491c7ee1d4ceb002daf8366a3c15))
|
||||
|
||||
# [5.13.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.15...v5.13.0-dev.16) (2025-02-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **NU.nl:** Add `Hide ads` and `Spoof Certificate` patch ([#4368](https://github.com/ReVanced/revanced-patches/issues/4368)) ([f3268fb](https://github.com/ReVanced/revanced-patches/commit/f3268fb03ca25fb5465e36015b6c9dec2c84a655))
|
||||
|
||||
# [5.13.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.14...v5.13.0-dev.15) (2025-02-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide player components:** Show correct end video thumbnail if `Hide end screen suggested video` is enabled ([#4502](https://github.com/ReVanced/revanced-patches/issues/4502)) ([6c4885a](https://github.com/ReVanced/revanced-patches/commit/6c4885a1d5dfff50100b01840b5552d92e83ee4a))
|
||||
|
||||
# [5.13.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.13...v5.13.0-dev.14) (2025-02-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Swipe controls:** Adjust the overlay text size ([#4503](https://github.com/ReVanced/revanced-patches/issues/4503)) ([6dc4bf7](https://github.com/ReVanced/revanced-patches/commit/6dc4bf75e09ed6f05534919d7b769b720043abce))
|
||||
|
||||
# [5.13.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.12...v5.13.0-dev.13) (2025-02-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Resolve button flickering when taping seekbar ([#4500](https://github.com/ReVanced/revanced-patches/issues/4500)) ([1f08047](https://github.com/ReVanced/revanced-patches/commit/1f08047b48cc9555a4887d16ec7219a55a77251f))
|
||||
|
||||
# [5.13.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.11...v5.13.0-dev.12) (2025-02-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Return YouTube Dislike:** Use correct number formatting if using a different ReVanced language ([edf66f4](https://github.com/ReVanced/revanced-patches/commit/edf66f4e16d46156cb8b8e31d18cb8dbcb87737e))
|
||||
|
||||
# [5.13.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.10...v5.13.0-dev.11) (2025-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Resolve startup app crash ([18c0fc2](https://github.com/ReVanced/revanced-patches/commit/18c0fc2a7f186f50a904fd25dbaa739abdd24993))
|
||||
|
||||
# [5.13.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.9...v5.13.0-dev.10) (2025-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Copy video URL:** Use correct button ordering ([5e622cc](https://github.com/ReVanced/revanced-patches/commit/5e622ccf66d34af31c6026fa7f4d332460c6ecb0))
|
||||
|
||||
# [5.13.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.8...v5.13.0-dev.9) (2025-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Do not hide player controls when using double tap to skip forward ([#4487](https://github.com/ReVanced/revanced-patches/issues/4487)) ([63fe870](https://github.com/ReVanced/revanced-patches/commit/63fe870d48ca2217327b952bde241b7f16ced850))
|
||||
|
||||
# [5.13.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.7...v5.13.0-dev.8) (2025-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof app version:** Force old settings menus if spoofing to older app targets ([#4490](https://github.com/ReVanced/revanced-patches/issues/4490)) ([45e7c46](https://github.com/ReVanced/revanced-patches/commit/45e7c46dd9c70c926b8b1a97ada668f90f5f6f8c))
|
||||
|
||||
# [5.13.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.6...v5.13.0-dev.7) (2025-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Resolve startup app crash ([6466398](https://github.com/ReVanced/revanced-patches/commit/64663983b84de1f28636205f61bf0a24c83968d1))
|
||||
|
||||
# [5.13.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.5...v5.13.0-dev.6) (2025-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Navigation buttons:** Add 'Hide notifications' setting ([#4485](https://github.com/ReVanced/revanced-patches/issues/4485)) ([506d241](https://github.com/ReVanced/revanced-patches/commit/506d2414bbc760e764e5a514b32926083d6ecb6b))
|
||||
|
||||
# [5.13.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.4...v5.13.0-dev.5) (2025-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Resolve startup app crash ([c14bc24](https://github.com/ReVanced/revanced-patches/commit/c14bc244550de30eca975ca7c09e8eb0c47534b5))
|
||||
|
||||
# [5.13.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.3...v5.13.0-dev.4) (2025-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok:** Resolve startup app crash ([d700076](https://github.com/ReVanced/revanced-patches/commit/d7000768a5e5a688c9f4e48858ac34e352222c1e))
|
||||
|
||||
# [5.13.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.2...v5.13.0-dev.3) (2025-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Fix player button fade out animations ([#4469](https://github.com/ReVanced/revanced-patches/issues/4469)) ([bf8e775](https://github.com/ReVanced/revanced-patches/commit/bf8e7759f9bdbdfef419a879fb3dd7cf0dff0098))
|
||||
|
||||
# [5.13.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.13.0-dev.1...v5.13.0-dev.2) (2025-02-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide video action buttons:** Move 'Disable Like and Subscribe glow' to action buttons settings menu ([29b265d](https://github.com/ReVanced/revanced-patches/commit/29b265d8fdaa48502650be9623bfc518a57a0bb1))
|
||||
|
||||
# [5.13.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.12.0...v5.13.0-dev.1) (2025-02-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Do not hide 'Show anyway' button in search results ([4ac8854](https://github.com/ReVanced/revanced-patches/commit/4ac8854b99808a8957f3b0b7438e1e0cdedffbaf))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Swipe controls:** Swipe controls UI improvements ([#4422](https://github.com/ReVanced/revanced-patches/issues/4422)) ([198e4d2](https://github.com/ReVanced/revanced-patches/commit/198e4d2a2315c24a09eb9ecfefbd131a75384d2c))
|
||||
|
||||
# [5.12.0](https://github.com/ReVanced/revanced-patches/compare/v5.11.0...v5.12.0) (2025-02-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Allow changing default settings for existing app installs ([#4464](https://github.com/ReVanced/revanced-patches/issues/4464)) ([1bd7986](https://github.com/ReVanced/revanced-patches/commit/1bd7986823e774a929c8a9102a7cc96e245d5274))
|
||||
* **Windy.app:** Remove obsolete `Unlock pro` patch ([#4428](https://github.com/ReVanced/revanced-patches/issues/4428)) ([83d116e](https://github.com/ReVanced/revanced-patches/commit/83d116e8fd3935ee431cfdf0b8e095d04ee77259))
|
||||
* **YouTube - Spoof video streams:** Change default client to `Android TV` ([#4465](https://github.com/ReVanced/revanced-patches/issues/4465)) ([0412c79](https://github.com/ReVanced/revanced-patches/commit/0412c7901dc8599b6079d9c3ba26452f88af642b))
|
||||
* **YouTube:** Remove obsolete 18.x targets ([#4454](https://github.com/ReVanced/revanced-patches/issues/4454)) ([a006758](https://github.com/ReVanced/revanced-patches/commit/a0067581d0f877e1b4eb1f888a25786f09676b2e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Return YouTube Dislike:** add `Show estimated likes` setting ([#4443](https://github.com/ReVanced/revanced-patches/issues/4443)) ([9a88b42](https://github.com/ReVanced/revanced-patches/commit/9a88b4239fd63d5f91105fec8e7d59d318a5d09a))
|
||||
* **YouTube - SponsorBlock:** Redesign skip buttons ([#4427](https://github.com/ReVanced/revanced-patches/issues/4427)) ([8f4883f](https://github.com/ReVanced/revanced-patches/commit/8f4883fc002420bfb4056401e23445c99e1d3fce))
|
||||
* **YouTube Music:** Support version `8.05.50` ([#4439](https://github.com/ReVanced/revanced-patches/issues/4439)) ([b31fed9](https://github.com/ReVanced/revanced-patches/commit/b31fed98901fcda1bce6f05eb0de63280c689fa0))
|
||||
* **YouTube Music:** Support version `8.05.51` ([128441e](https://github.com/ReVanced/revanced-patches/commit/128441e78bc0d096c3fc2f57782ab90c39c3ae4b))
|
||||
|
||||
# [5.12.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.12.0-dev.6...v5.12.0-dev.7) (2025-02-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Change default client to `Android TV` ([#4465](https://github.com/ReVanced/revanced-patches/issues/4465)) ([0412c79](https://github.com/ReVanced/revanced-patches/commit/0412c7901dc8599b6079d9c3ba26452f88af642b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Support version `8.05.51` ([128441e](https://github.com/ReVanced/revanced-patches/commit/128441e78bc0d096c3fc2f57782ab90c39c3ae4b))
|
||||
|
||||
# [5.12.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.12.0-dev.5...v5.12.0-dev.6) (2025-02-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Allow changing default settings for existing app installs ([#4464](https://github.com/ReVanced/revanced-patches/issues/4464)) ([1bd7986](https://github.com/ReVanced/revanced-patches/commit/1bd7986823e774a929c8a9102a7cc96e245d5274))
|
||||
|
||||
# [5.12.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.12.0-dev.4...v5.12.0-dev.5) (2025-02-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Remove obsolete 18.x targets ([#4454](https://github.com/ReVanced/revanced-patches/issues/4454)) ([a006758](https://github.com/ReVanced/revanced-patches/commit/a0067581d0f877e1b4eb1f888a25786f09676b2e))
|
||||
|
||||
# [5.12.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.12.0-dev.3...v5.12.0-dev.4) (2025-02-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Support version `8.05.50` ([#4439](https://github.com/ReVanced/revanced-patches/issues/4439)) ([b31fed9](https://github.com/ReVanced/revanced-patches/commit/b31fed98901fcda1bce6f05eb0de63280c689fa0))
|
||||
|
||||
# [5.12.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.12.0-dev.2...v5.12.0-dev.3) (2025-02-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Windy.app:** Remove obsolete `Unlock pro` patch ([#4428](https://github.com/ReVanced/revanced-patches/issues/4428)) ([83d116e](https://github.com/ReVanced/revanced-patches/commit/83d116e8fd3935ee431cfdf0b8e095d04ee77259))
|
||||
|
||||
# [5.12.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.12.0-dev.1...v5.12.0-dev.2) (2025-02-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Return YouTube Dislike:** add `Show estimated likes` setting ([#4443](https://github.com/ReVanced/revanced-patches/issues/4443)) ([9a88b42](https://github.com/ReVanced/revanced-patches/commit/9a88b4239fd63d5f91105fec8e7d59d318a5d09a))
|
||||
|
||||
# [5.12.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.11.0...v5.12.0-dev.1) (2025-02-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Redesign skip buttons ([#4427](https://github.com/ReVanced/revanced-patches/issues/4427)) ([8f4883f](https://github.com/ReVanced/revanced-patches/commit/8f4883fc002420bfb4056401e23445c99e1d3fce))
|
||||
|
||||
# [5.11.0](https://github.com/ReVanced/revanced-patches/compare/v5.10.0...v5.11.0) (2025-02-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix broken `Remove screen capture restriction`, `Remove screenshot restriction`, `Spoof Wi-Fi connection`, and `Export internal data documents provider` patch ([#4405](https://github.com/ReVanced/revanced-patches/issues/4405)) ([1d52b74](https://github.com/ReVanced/revanced-patches/commit/1d52b7478d34e699d8c629eeaa9fdbb470b7d5c8))
|
||||
* **YouTube - Enable slide to seek:** Change patch to default include ([50358cd](https://github.com/ReVanced/revanced-patches/commit/50358cddea3eef4051d248040d23f774521dce00))
|
||||
* **YouTube - Hide layout components:** Hide new type of community post ([#4404](https://github.com/ReVanced/revanced-patches/issues/4404)) ([f67ab2b](https://github.com/ReVanced/revanced-patches/commit/f67ab2baf25d543ceb55fcec48bda441ebf2b998))
|
||||
* **YouTube - Theme:** Use custom seekbar color for cairo startup animation ([#4399](https://github.com/ReVanced/revanced-patches/issues/4399)) ([1cba294](https://github.com/ReVanced/revanced-patches/commit/1cba2948a6787118eb380ffcec35ee4fb99447ea))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Change start page:** Add additional start pages ([#4413](https://github.com/ReVanced/revanced-patches/issues/4413)) ([b434182](https://github.com/ReVanced/revanced-patches/commit/b434182df69313c4eb5f0dfd98101cb80e46ead2))
|
||||
|
||||
# [5.11.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.11.0-dev.1...v5.11.0-dev.2) (2025-02-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix broken `Remove screen capture restriction`, `Remove screenshot restriction`, `Spoof Wi-Fi connection`, and `Export internal data documents provider` patch ([#4405](https://github.com/ReVanced/revanced-patches/issues/4405)) ([1d52b74](https://github.com/ReVanced/revanced-patches/commit/1d52b7478d34e699d8c629eeaa9fdbb470b7d5c8))
|
||||
|
||||
# [5.11.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.10.1-dev.3...v5.11.0-dev.1) (2025-02-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Change start page:** Add additional start pages ([#4413](https://github.com/ReVanced/revanced-patches/issues/4413)) ([b434182](https://github.com/ReVanced/revanced-patches/commit/b434182df69313c4eb5f0dfd98101cb80e46ead2))
|
||||
|
||||
## [5.10.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.10.1-dev.2...v5.10.1-dev.3) (2025-02-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Hide new type of community post ([#4404](https://github.com/ReVanced/revanced-patches/issues/4404)) ([f67ab2b](https://github.com/ReVanced/revanced-patches/commit/f67ab2baf25d543ceb55fcec48bda441ebf2b998))
|
||||
|
||||
## [5.10.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.10.1-dev.1...v5.10.1-dev.2) (2025-02-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Enable slide to seek:** Change patch to default include ([50358cd](https://github.com/ReVanced/revanced-patches/commit/50358cddea3eef4051d248040d23f774521dce00))
|
||||
|
||||
## [5.10.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.10.0...v5.10.1-dev.1) (2025-02-02)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
android.namespace = "app.revanced.extension"
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
|
||||
@@ -12,7 +12,7 @@ import android.os.Handler;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
/** @noinspection deprecation, unused */
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class SpoofWifiPatch {
|
||||
|
||||
// Used to check what the (real or fake) active network is (take a look at `hasTransport`).
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.extension.all.misc.directory.documentsprovider;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ProviderInfo;
|
||||
@@ -23,6 +24,7 @@ import java.util.Objects;
|
||||
/**
|
||||
* A DocumentsProvider that allows access to the app's internal data directory.
|
||||
*/
|
||||
@SuppressLint("LongLogTag")
|
||||
public class InternalDataDocumentsProvider extends DocumentsProvider {
|
||||
private static final String[] rootColumns =
|
||||
{"root_id", "mime_types", "flags", "icon", "title", "summary", "document_id"};
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
android.namespace = "app.revanced.extension"
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
|
||||
@@ -5,7 +5,8 @@ import android.os.Build;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
public final class RemoveScreencaptureRestrictionPatch {
|
||||
@SuppressWarnings("unused")
|
||||
public final class RemoveScreenCaptureRestrictionPatch {
|
||||
// Member of AudioAttributes.Builder
|
||||
@RequiresApi(api = Build.VERSION_CODES.Q)
|
||||
public static AudioAttributes.Builder setAllowedCapturePolicy(final AudioAttributes.Builder builder, final int capturePolicy) {
|
||||
@@ -1 +1,16 @@
|
||||
android.namespace = "app.revanced.extension"
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.extension.all.screenshot.removerestriction;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class RemoveScreenshotRestrictionPatch {
|
||||
|
||||
public static void addFlags(Window window, int flags) {
|
||||
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
// Do not remove. Necessary for the extension plugin to be applied to the project.
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
}
|
||||
}
|
||||
|
||||
4
extensions/nunl/build.gradle.kts
Normal file
4
extensions/nunl/build.gradle.kts
Normal file
@@ -0,0 +1,4 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:nunl:stub"))
|
||||
}
|
||||
1
extensions/nunl/src/main/AndroidManifest.xml
Normal file
1
extensions/nunl/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,114 @@
|
||||
package app.revanced.extension.nunl.ads;
|
||||
|
||||
import nl.nu.performance.api.client.interfaces.Block;
|
||||
import nl.nu.performance.api.client.unions.SmallArticleLinkFlavor;
|
||||
import nl.nu.performance.api.client.objects.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideAdsPatch {
|
||||
private static final String[] blockedHeaderBlocks = {
|
||||
"Aanbiedingen (Adverteerders)",
|
||||
"Aangeboden door NUshop"
|
||||
};
|
||||
|
||||
// "Rubrieken" menu links to ads.
|
||||
private static final String[] blockedLinkBlocks = {
|
||||
"Van onze adverteerders"
|
||||
};
|
||||
|
||||
public static void filterAds(List<Block> blocks) {
|
||||
try {
|
||||
ArrayList<Block> cleanedList = new ArrayList<>();
|
||||
|
||||
boolean skipFullHeader = false;
|
||||
boolean skipUntilDivider = false;
|
||||
|
||||
int index = 0;
|
||||
while (index < blocks.size()) {
|
||||
Block currentBlock = blocks.get(index);
|
||||
|
||||
// Because of pagination, we might not see the Divider in front of it.
|
||||
// Just remove it as is and leave potential extra spacing visible on the screen.
|
||||
if (currentBlock instanceof DpgBannerBlock) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index + 1 < blocks.size()) {
|
||||
// Filter Divider -> DpgMediaBanner -> Divider.
|
||||
if (currentBlock instanceof DividerBlock
|
||||
&& blocks.get(index + 1) instanceof DpgBannerBlock) {
|
||||
index += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter Divider -> LinkBlock (... -> LinkBlock -> LinkBlock-> LinkBlock -> Divider).
|
||||
if (currentBlock instanceof DividerBlock
|
||||
&& blocks.get(index + 1) instanceof LinkBlock linkBlock) {
|
||||
Link link = linkBlock.getLink();
|
||||
if (link != null && link.getTitle() != null) {
|
||||
for (String blockedLinkBlock : blockedLinkBlocks) {
|
||||
if (blockedLinkBlock.equals(link.getTitle().getText())) {
|
||||
skipUntilDivider = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skipUntilDivider) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip LinkBlocks with a "flavor" claiming to be "isPartner" (sponsored inline ads).
|
||||
if (currentBlock instanceof LinkBlock linkBlock
|
||||
&& linkBlock.getLink() != null
|
||||
&& linkBlock.getLink().getLinkFlavor() instanceof SmallArticleLinkFlavor smallArticleLinkFlavor
|
||||
&& smallArticleLinkFlavor.isPartner() != null
|
||||
&& smallArticleLinkFlavor.isPartner()) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentBlock instanceof DividerBlock) {
|
||||
skipUntilDivider = false;
|
||||
}
|
||||
|
||||
// Filter HeaderBlock with known ads until next HeaderBlock.
|
||||
if (currentBlock instanceof HeaderBlock headerBlock) {
|
||||
StyledText headerText = headerBlock.component20();
|
||||
if (headerText != null) {
|
||||
skipFullHeader = false;
|
||||
for (String blockedHeaderBlock : blockedHeaderBlocks) {
|
||||
if (blockedHeaderBlock.equals(headerText.getText())) {
|
||||
skipFullHeader = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skipFullHeader) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skipFullHeader && !skipUntilDivider) {
|
||||
cleanedList.add(currentBlock);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// Replace list in-place to not deal with moving the result to the correct register in smali.
|
||||
blocks.clear();
|
||||
blocks.addAll(cleanedList);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "filterAds failure", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
extensions/nunl/stub/build.gradle.kts
Normal file
17
extensions/nunl/stub/build.gradle.kts
Normal file
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
id(libs.plugins.android.library.get().pluginId)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
1
extensions/nunl/stub/src/main/AndroidManifest.xml
Normal file
1
extensions/nunl/stub/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,5 @@
|
||||
package nl.nu.performance.api.client.interfaces;
|
||||
|
||||
public class Block {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package nl.nu.performance.api.client.objects;
|
||||
|
||||
import nl.nu.performance.api.client.interfaces.Block;
|
||||
|
||||
public class DividerBlock extends Block {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package nl.nu.performance.api.client.objects;
|
||||
|
||||
import nl.nu.performance.api.client.interfaces.Block;
|
||||
|
||||
public class DpgBannerBlock extends Block {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package nl.nu.performance.api.client.objects;
|
||||
|
||||
import nl.nu.performance.api.client.interfaces.Block;
|
||||
|
||||
public class HeaderBlock extends Block {
|
||||
// returns title
|
||||
public final StyledText component20() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package nl.nu.performance.api.client.objects;
|
||||
|
||||
import nl.nu.performance.api.client.unions.LinkFlavor;
|
||||
|
||||
public class Link {
|
||||
public final StyledText getTitle() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
|
||||
public final LinkFlavor getLinkFlavor() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package nl.nu.performance.api.client.objects;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import nl.nu.performance.api.client.interfaces.Block;
|
||||
|
||||
public abstract class LinkBlock extends Block implements Parcelable {
|
||||
public final Link getLink() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package nl.nu.performance.api.client.objects;
|
||||
|
||||
public class StyledText {
|
||||
public final String getText() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package nl.nu.performance.api.client.unions;
|
||||
|
||||
public interface LinkFlavor {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package nl.nu.performance.api.client.unions;
|
||||
|
||||
public class SmallArticleLinkFlavor implements LinkFlavor {
|
||||
public final Boolean isPartner() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -356,33 +357,24 @@ public class Utils {
|
||||
|
||||
public static Context getContext() {
|
||||
if (context == null) {
|
||||
Logger.initializationException(Utils.class, "Context is null, returning null!", null);
|
||||
Logger.initializationException(Utils.class, "Context is not set by extension hook, returning null", null);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
public static void setContext(Context appContext) {
|
||||
// Must initially set context as the language settings needs it.
|
||||
// Must initially set context to check the app language.
|
||||
context = appContext;
|
||||
Logger.initializationInfo(Utils.class, "Set context: " + appContext);
|
||||
|
||||
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
|
||||
if (language != AppLanguage.DEFAULT) {
|
||||
// Create a new context with the desired language.
|
||||
Logger.printDebug(() -> "Using app language: " + language);
|
||||
Configuration config = appContext.getResources().getConfiguration();
|
||||
config.setLocale(language.getLocale());
|
||||
context = appContext.createConfigurationContext(config);
|
||||
}
|
||||
|
||||
// In some apps like TikTok, the Setting classes can load in weird orders due to cyclic class dependencies.
|
||||
// Calling the regular printDebug method here can cause a Settings context null pointer exception,
|
||||
// even though the context is already set before the call.
|
||||
//
|
||||
// The initialization logger methods do not directly or indirectly
|
||||
// reference the Context or any Settings and are unaffected by this problem.
|
||||
//
|
||||
// Info level also helps debug if a patch hook is called before
|
||||
// the context is set since debug logging is off by default.
|
||||
Logger.initializationInfo(Utils.class, "Set context: " + appContext);
|
||||
}
|
||||
|
||||
public static void setClipboard(@NonNull String text) {
|
||||
@@ -808,4 +800,14 @@ public class Utils {
|
||||
builder.getContext().setTheme(editTextDialogStyle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a color resource or hex code to an int representation of the color.
|
||||
*/
|
||||
public static int getColorFromString(String colorString) throws IllegalArgumentException, Resources.NotFoundException {
|
||||
if (colorString.startsWith("#")) {
|
||||
return Color.parseColor(colorString);
|
||||
}
|
||||
return getResourceColor(colorString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ public enum AppLanguage {
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
// Languages codes not included with YouTube, but are translated on Crowdin
|
||||
GA,
|
||||
|
||||
// Language codes found in locale_config.xml
|
||||
// All region specific variants have been removed.
|
||||
AF,
|
||||
|
||||
@@ -23,12 +23,17 @@ public class BaseSettings {
|
||||
|
||||
public static final EnumSetting<AppLanguage> REVANCED_LANGUAGE = new EnumSetting<>("revanced_language", AppLanguage.DEFAULT, true, "revanced_language_user_dialog_message");
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
|
||||
public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
|
||||
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));
|
||||
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
|
||||
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability());
|
||||
// Client type must be last spoof setting due to cyclic references.
|
||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS));
|
||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_UNPLUGGED, true, parent(SPOOF_VIDEO_STREAMS));
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ public class BooleanSetting extends Setting<Boolean> {
|
||||
*/
|
||||
public static void privateSetValue(@NonNull BooleanSetting setting, @NonNull Boolean newValue) {
|
||||
setting.value = Objects.requireNonNull(newValue);
|
||||
|
||||
if (setting.isSetToDefault()) {
|
||||
setting.removeFromPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,10 +69,8 @@ public class BooleanSetting extends Setting<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NonNull Boolean newValue) {
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
preferences.saveBoolean(key, newValue);
|
||||
public void saveToPreferences() {
|
||||
preferences.saveBoolean(key, value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -89,10 +89,8 @@ public class EnumSetting<T extends Enum<?>> extends Setting<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NonNull T newValue) {
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
preferences.saveEnumAsString(key, newValue);
|
||||
public void saveToPreferences() {
|
||||
preferences.saveEnumAsString(key, value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -55,10 +55,8 @@ public class FloatSetting extends Setting<Float> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NonNull Float newValue) {
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
preferences.saveFloatString(key, newValue);
|
||||
public void saveToPreferences() {
|
||||
preferences.saveFloatString(key, value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -55,10 +55,8 @@ public class IntegerSetting extends Setting<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NonNull Integer newValue) {
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
preferences.saveIntegerString(key, newValue);
|
||||
public void saveToPreferences() {
|
||||
preferences.saveIntegerString(key, value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -55,10 +55,8 @@ public class LongSetting extends Setting<Long> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NonNull Long newValue) {
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
preferences.saveLongString(key, newValue);
|
||||
public void saveToPreferences() {
|
||||
preferences.saveLongString(key, value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.util.*;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class Setting<T> {
|
||||
|
||||
/**
|
||||
@@ -288,6 +287,13 @@ public abstract class Setting<T> {
|
||||
*/
|
||||
public static void privateSetValueFromString(@NonNull Setting<?> setting, @NonNull String newValue) {
|
||||
setting.setValueFromString(newValue);
|
||||
|
||||
// Clear the preference value since default is used, to allow changing
|
||||
// the changing the default for a future release. Without this after upgrading
|
||||
// the saved value will be whatever was the default when the app was first installed.
|
||||
if (setting.isSetToDefault()) {
|
||||
setting.removeFromPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +309,33 @@ public abstract class Setting<T> {
|
||||
/**
|
||||
* Persistently saves the value.
|
||||
*/
|
||||
public abstract void save(@NonNull T newValue);
|
||||
public final void save(@NonNull T newValue) {
|
||||
if (value.equals(newValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
|
||||
if (defaultValue.equals(newValue)) {
|
||||
removeFromPreferences();
|
||||
} else {
|
||||
saveToPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save {@link #value} to {@link #preferences}.
|
||||
*/
|
||||
protected abstract void saveToPreferences();
|
||||
|
||||
/**
|
||||
* Remove {@link #value} from {@link #preferences}.
|
||||
*/
|
||||
protected final void removeFromPreferences() {
|
||||
Logger.printDebug(() -> "Clearing stored preference value (reset to default): " + key);
|
||||
preferences.removeKey(key);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public abstract T get();
|
||||
|
||||
@@ -55,10 +55,8 @@ public class StringSetting extends Setting<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NonNull String newValue) {
|
||||
// Must set before saving to preferences (otherwise importing fails to update UI correctly).
|
||||
value = Objects.requireNonNull(newValue);
|
||||
preferences.saveString(key, newValue);
|
||||
public void saveToPreferences() {
|
||||
preferences.saveString(key, value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -22,12 +22,23 @@ import app.revanced.extension.shared.settings.Setting;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
/**
|
||||
* Indicates that if a preference changes,
|
||||
* to apply the change from the Setting to the UI component.
|
||||
*/
|
||||
public static boolean settingImportInProgress;
|
||||
|
||||
/**
|
||||
* Prevents recursive calls during preference <-> UI syncing from showing extra dialogs.
|
||||
*/
|
||||
private static boolean updatingPreference;
|
||||
|
||||
/**
|
||||
* Used to prevent showing reboot dialog, if user cancels a setting user dialog.
|
||||
*/
|
||||
private static boolean showingUserDialogMessage;
|
||||
|
||||
/**
|
||||
* Confirm and restart dialog button text and title.
|
||||
* Set by subclasses if Strings cannot be added as a resource.
|
||||
@@ -35,13 +46,13 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
@Nullable
|
||||
protected static String restartDialogButtonText, restartDialogTitle, confirmDialogTitle;
|
||||
|
||||
/**
|
||||
* Used to prevent showing reboot dialog, if user cancels a setting user dialog.
|
||||
*/
|
||||
private boolean showingUserDialogMessage;
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||
try {
|
||||
if (updatingPreference) {
|
||||
Logger.printDebug(() -> "Ignoring preference change as sync is in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
Setting<?> setting = Setting.getSettingFromPath(Objects.requireNonNull(str));
|
||||
if (setting == null) {
|
||||
return;
|
||||
@@ -63,16 +74,18 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
updatingPreference = true;
|
||||
// Apply 'Setting <- Preference', unless during importing when it needs to be 'Setting -> Preference'.
|
||||
// Updating here can can cause a recursive call back into this same method.
|
||||
updatePreference(pref, setting, true, settingImportInProgress);
|
||||
// Update any other preference availability that may now be different.
|
||||
updateUIAvailability();
|
||||
updatingPreference = false;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "OnSharedPreferenceChangeListener failure", ex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize this instance, and do any custom behavior.
|
||||
* <p>
|
||||
@@ -81,7 +94,10 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
* so all app specific {@link Setting} instances are loaded before this method returns.
|
||||
*/
|
||||
protected void initialize() {
|
||||
final var identifier = Utils.getResourceIdentifier("revanced_prefs", "xml");
|
||||
String preferenceResourceName = BaseSettings.SHOW_MENU_ICONS.get()
|
||||
? "revanced_prefs_icons"
|
||||
: "revanced_prefs";
|
||||
final var identifier = Utils.getResourceIdentifier(preferenceResourceName, "xml");
|
||||
if (identifier == 0) return;
|
||||
addPreferencesFromResource(identifier);
|
||||
|
||||
@@ -97,7 +113,9 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
if (confirmDialogTitle == null) {
|
||||
confirmDialogTitle = str("revanced_settings_confirm_user_dialog_title");
|
||||
}
|
||||
|
||||
showingUserDialogMessage = true;
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(confirmDialogTitle)
|
||||
.setMessage(Objects.requireNonNull(setting.userDialogMessage).toString())
|
||||
@@ -141,14 +159,16 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
* @return If the preference is currently set to the default value of the Setting.
|
||||
*/
|
||||
protected boolean prefIsSetToDefault(Preference pref, Setting<?> setting) {
|
||||
Object defaultValue = setting.defaultValue;
|
||||
if (pref instanceof SwitchPreference switchPref) {
|
||||
return switchPref.isChecked() == (Boolean) setting.defaultValue;
|
||||
return switchPref.isChecked() == (Boolean) defaultValue;
|
||||
}
|
||||
String defaultValueString = defaultValue.toString();
|
||||
if (pref instanceof EditTextPreference editPreference) {
|
||||
return editPreference.getText().equals(setting.defaultValue.toString());
|
||||
return editPreference.getText().equals(defaultValueString);
|
||||
}
|
||||
if (pref instanceof ListPreference listPref) {
|
||||
return listPref.getValue().equals(setting.defaultValue.toString());
|
||||
return listPref.getValue().equals(defaultValueString);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Must override method to handle "
|
||||
@@ -158,16 +178,16 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
/**
|
||||
* Syncs all UI Preferences to any {@link Setting} they represent.
|
||||
*/
|
||||
private void updatePreferenceScreen(@NonNull PreferenceScreen screen,
|
||||
private void updatePreferenceScreen(@NonNull PreferenceGroup group,
|
||||
boolean syncSettingValue,
|
||||
boolean applySettingToPreference) {
|
||||
// Alternatively this could iterate thru all Settings and check for any matching Preferences,
|
||||
// but there are many more Settings than UI preferences so it's more efficient to only check
|
||||
// the Preferences.
|
||||
for (int i = 0, prefCount = screen.getPreferenceCount(); i < prefCount; i++) {
|
||||
Preference pref = screen.getPreference(i);
|
||||
if (pref instanceof PreferenceScreen) {
|
||||
updatePreferenceScreen((PreferenceScreen) pref, syncSettingValue, applySettingToPreference);
|
||||
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
|
||||
Preference pref = group.getPreference(i);
|
||||
if (pref instanceof PreferenceGroup subGroup) {
|
||||
updatePreferenceScreen(subGroup, syncSettingValue, applySettingToPreference);
|
||||
} else if (pref.hasKey()) {
|
||||
String key = pref.getKey();
|
||||
Setting<?> setting = Setting.getSettingFromPath(key);
|
||||
@@ -255,7 +275,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showRestartDialog(@NonNull final Context context) {
|
||||
public static void showRestartDialog(Context context) {
|
||||
Utils.verifyOnMainThread();
|
||||
if (restartDialogTitle == null) {
|
||||
restartDialogTitle = str("revanced_settings_restart_title");
|
||||
@@ -263,6 +283,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
if (restartDialogButtonText == null) {
|
||||
restartDialogButtonText = str("revanced_settings_restart");
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(restartDialogTitle)
|
||||
.setPositiveButton(restartDialogButtonText, (dialog, id)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* Empty preference category with no title, used to organize and group related preferences together.
|
||||
*/
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class NoTitlePreferenceCategory extends PreferenceCategory {
|
||||
|
||||
public NoTitlePreferenceCategory(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public NoTitlePreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public NoTitlePreferenceCategory(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("MissingSuperCall")
|
||||
protected View onCreateView(ViewGroup parent) {
|
||||
// Return an zero-height view to eliminate empty title space.
|
||||
return new View(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle() {
|
||||
// Title can be used for sorting. Return the first sub preference title.
|
||||
if (getPreferenceCount() > 0) {
|
||||
return getPreference(0).getTitle();
|
||||
}
|
||||
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTitleRes() {
|
||||
if (getPreferenceCount() > 0) {
|
||||
return getPreference(0).getTitleRes();
|
||||
}
|
||||
|
||||
return super.getTitleRes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
@@ -8,17 +10,23 @@ import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class ResettableEditTextPreference extends EditTextPreference {
|
||||
|
||||
/**
|
||||
* Setting to reset.
|
||||
*/
|
||||
@Nullable
|
||||
private Setting<?> setting;
|
||||
|
||||
public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
@@ -32,12 +40,22 @@ public class ResettableEditTextPreference extends EditTextPreference {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setSetting(@Nullable Setting<?> setting) {
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||
super.onPrepareDialogBuilder(builder);
|
||||
Utils.setEditTextDialogTheme(builder);
|
||||
|
||||
Setting<?> setting = Setting.getSettingFromPath(getKey());
|
||||
if (setting == null) {
|
||||
String key = getKey();
|
||||
if (key != null) {
|
||||
setting = Setting.getSettingFromPath(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (setting != null) {
|
||||
builder.setNeutralButton(str("revanced_settings_reset"), null);
|
||||
}
|
||||
@@ -54,8 +72,7 @@ public class ResettableEditTextPreference extends EditTextPreference {
|
||||
}
|
||||
button.setOnClickListener(v -> {
|
||||
try {
|
||||
Setting<?> setting = Objects.requireNonNull(Setting.getSettingFromPath(getKey()));
|
||||
String defaultStringValue = setting.defaultValue.toString();
|
||||
String defaultStringValue = Objects.requireNonNull(setting).defaultValue.toString();
|
||||
EditText editText = getEditText();
|
||||
editText.setText(defaultStringValue);
|
||||
editText.setSelection(defaultStringValue.length()); // move cursor to end of text
|
||||
|
||||
@@ -66,22 +66,6 @@ public enum ClientType {
|
||||
true,
|
||||
"Android Creator"
|
||||
),
|
||||
ANDROID_VR(
|
||||
ANDROID_VR_NO_AUTH.id,
|
||||
ANDROID_VR_NO_AUTH.clientName,
|
||||
ANDROID_VR_NO_AUTH.packageName,
|
||||
ANDROID_VR_NO_AUTH.deviceMake,
|
||||
ANDROID_VR_NO_AUTH.deviceModel,
|
||||
ANDROID_VR_NO_AUTH.osName,
|
||||
ANDROID_VR_NO_AUTH.osVersion,
|
||||
ANDROID_VR_NO_AUTH.androidSdkVersion,
|
||||
ANDROID_VR_NO_AUTH.buildId,
|
||||
ANDROID_VR_NO_AUTH.cronetVersion,
|
||||
ANDROID_VR_NO_AUTH.clientVersion,
|
||||
ANDROID_VR_NO_AUTH.requiresAuth,
|
||||
true,
|
||||
"Android VR"
|
||||
),
|
||||
IOS_UNPLUGGED(
|
||||
33,
|
||||
"IOS_UNPLUGGED",
|
||||
@@ -112,6 +96,22 @@ public enum ClientType {
|
||||
forceAVC()
|
||||
? "iOS TV Force AVC"
|
||||
: "iOS TV"
|
||||
),
|
||||
ANDROID_VR_AUTH(
|
||||
ANDROID_VR_NO_AUTH.id,
|
||||
ANDROID_VR_NO_AUTH.clientName,
|
||||
ANDROID_VR_NO_AUTH.packageName,
|
||||
ANDROID_VR_NO_AUTH.deviceMake,
|
||||
ANDROID_VR_NO_AUTH.deviceModel,
|
||||
ANDROID_VR_NO_AUTH.osName,
|
||||
ANDROID_VR_NO_AUTH.osVersion,
|
||||
ANDROID_VR_NO_AUTH.androidSdkVersion,
|
||||
ANDROID_VR_NO_AUTH.buildId,
|
||||
ANDROID_VR_NO_AUTH.cronetVersion,
|
||||
ANDROID_VR_NO_AUTH.clientVersion,
|
||||
ANDROID_VR_NO_AUTH.requiresAuth,
|
||||
true,
|
||||
"Android VR Auth"
|
||||
);
|
||||
|
||||
private static boolean forceAVC() {
|
||||
|
||||
@@ -107,6 +107,36 @@ public class SpoofVideoStreamsPatch {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Turns off a feature flag that interferes with spoofing.
|
||||
*/
|
||||
public static boolean useMediaFetchHotConfigReplacement(boolean original) {
|
||||
if (original) {
|
||||
Logger.printDebug(() -> "useMediaFetchHotConfigReplacement is set on");
|
||||
}
|
||||
|
||||
if (!SPOOF_STREAMING_DATA) {
|
||||
return original;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Turns off a feature flag that interferes with video playback.
|
||||
*/
|
||||
public static boolean usePlaybackStartFeatureFlag(boolean original) {
|
||||
if (original) {
|
||||
Logger.printDebug(() -> "usePlaybackStartFeatureFlag is set on");
|
||||
}
|
||||
|
||||
if (!SPOOF_STREAMING_DATA) {
|
||||
return original;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
|
||||
16
extensions/spotify/build.gradle.kts
Normal file
16
extensions/spotify/build.gradle.kts
Normal file
@@ -0,0 +1,16 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:spotify:stub"))
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
1
extensions/spotify/src/main/AndroidManifest.xml
Normal file
1
extensions/spotify/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.extension.spotify.layout.theme;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class CustomThemePatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static long getThemeColor(String colorString) {
|
||||
try {
|
||||
return Utils.getColorFromString(colorString);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Invalid custom color: " + colorString, ex);
|
||||
return Color.BLACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
extensions/spotify/stub/build.gradle.kts
Normal file
17
extensions/spotify/stub/build.gradle.kts
Normal file
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
id(libs.plugins.android.library.get().pluginId)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
1
extensions/spotify/stub/src/main/AndroidManifest.xml
Normal file
1
extensions/spotify/stub/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.spotify.home.evopage.homeapi.proto;
|
||||
|
||||
public final class Section {
|
||||
public static final int VIDEO_BRAND_AD_FIELD_NUMBER = 20;
|
||||
public static final int IMAGE_BRAND_AD_FIELD_NUMBER = 21;
|
||||
public int featureTypeCase_;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.spotify.remoteconfig.internal;
|
||||
|
||||
public final class AccountAttribute {
|
||||
public Object value_;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.spotify.useraccount.v1;
|
||||
|
||||
/**
|
||||
* Used for target 8.6.98.900. Class is still present in newer app targets.
|
||||
*/
|
||||
public class AccountAttribute {
|
||||
public Object value_;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
|
||||
@@ -3,3 +3,14 @@ dependencies {
|
||||
compileOnly(project(":extensions:tiktok:stub"))
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 22
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import app.revanced.extension.tiktok.settings.preference.categories.DownloadsPre
|
||||
import app.revanced.extension.tiktok.settings.preference.categories.FeedFilterPreferenceCategory;
|
||||
import app.revanced.extension.tiktok.settings.preference.categories.ExtensionPreferenceCategory;
|
||||
import app.revanced.extension.tiktok.settings.preference.categories.SimSpoofPreferenceCategory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Preference fragment for ReVanced settings
|
||||
@@ -21,9 +20,11 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
protected void syncSettingWithPreference(@NonNull Preference pref,
|
||||
@NonNull Setting<?> setting,
|
||||
boolean applySettingToPreference) {
|
||||
if (pref instanceof RangeValuePreference rangeValuePref) {
|
||||
if (pref instanceof RangeValuePreference) {
|
||||
RangeValuePreference rangeValuePref = (RangeValuePreference) pref;
|
||||
Setting.privateSetValueFromString(setting, rangeValuePref.getValue());
|
||||
} else if (pref instanceof DownloadPathPreference downloadPathPref) {
|
||||
} else if (pref instanceof DownloadPathPreference) {
|
||||
DownloadPathPreference downloadPathPref = (DownloadPathPreference) pref;
|
||||
Setting.privateSetValueFromString(setting, downloadPathPref.getValue());
|
||||
} else {
|
||||
super.syncSettingWithPreference(pref, setting, applySettingToPreference);
|
||||
@@ -32,7 +33,7 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
final var context = getContext();
|
||||
final var context = getActivity();
|
||||
|
||||
// Currently no resources can be compiled for TikTok (fails with aapt error).
|
||||
// So all TikTok Strings are hard coded in the extension.
|
||||
|
||||
@@ -1,37 +1,60 @@
|
||||
package app.revanced.extension.tiktok.spoof.sim;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.tiktok.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class SpoofSimPatch {
|
||||
|
||||
private static final boolean ENABLED = Settings.SIM_SPOOF.get();
|
||||
/**
|
||||
* During app startup native code can be called with no obvious way to set the context.
|
||||
* Cannot check if sim spoofing is enabled or the app will crash since no context is set.
|
||||
*/
|
||||
private static boolean isContextNotSet(String fieldSpoofed) {
|
||||
if (Utils.getContext() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.initializationException(SpoofSimPatch.class,
|
||||
"Context is not yet set, cannot spoof: " + fieldSpoofed, null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getCountryIso(String value) {
|
||||
if (ENABLED) {
|
||||
if (isContextNotSet("countryIso")) return value;
|
||||
|
||||
if (Settings.SIM_SPOOF.get()) {
|
||||
String iso = Settings.SIM_SPOOF_ISO.get();
|
||||
Logger.printDebug(() -> "Spoofing sim ISO from: " + value + " to: " + iso);
|
||||
Logger.printDebug(() -> "Spoofing countryIso from: " + value + " to: " + iso);
|
||||
return iso;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String getOperator(String value) {
|
||||
if (ENABLED) {
|
||||
if (isContextNotSet("MCC-MNC")) return value;
|
||||
|
||||
if (Settings.SIM_SPOOF.get()) {
|
||||
String mcc_mnc = Settings.SIMSPOOF_MCCMNC.get();
|
||||
Logger.printDebug(() -> "Spoofing sim MCC-MNC from: " + value + " to: " + mcc_mnc);
|
||||
return mcc_mnc;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String getOperatorName(String value) {
|
||||
if (ENABLED) {
|
||||
if (isContextNotSet("operatorName")) return value;
|
||||
|
||||
if (Settings.SIM_SPOOF.get()) {
|
||||
String operator = Settings.SIMSPOOF_OP_NAME.get();
|
||||
Logger.printDebug(() -> "Spoofing sim operator from: " + value + " to: " + operator);
|
||||
Logger.printDebug(() -> "Spoofing sim operatorName from: " + value + " to: " + operator);
|
||||
return operator;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,9 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
minSdk = 22
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:tumblr:stub"))
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
android.namespace = "app.revanced.extension"
|
||||
|
||||
plugins {
|
||||
id(libs.plugins.android.library.get().pluginId)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
minSdk = 26
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,3 +6,14 @@ dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
compileOnly(libs.appcompat)
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,9 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
minSdk = 21
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ internal object TwiFucker {
|
||||
|
||||
private fun JSONObject.entryIsWhoToFollow(): Boolean =
|
||||
optString("entryId").let {
|
||||
it.startsWith("whoToFollow-") || it.startsWith("who-to-follow-") || it.startsWith("connect-module-")
|
||||
it.startsWith("whoToFollow-") || it.startsWith("who-to-follow-") || it.startsWith("connect-module-") || it.startsWith("who-to-subscribe-")
|
||||
}
|
||||
|
||||
private fun JSONObject.itemContainsPromotedUser(): Boolean =
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
//noinspection GradleDependency
|
||||
android.compileSdk = 33
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:youtube:stub"))
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,13 +45,24 @@ public class ThemeHelper {
|
||||
return "@color/yt_black3";
|
||||
}
|
||||
|
||||
private static int getThemeColor(String resourceName, int defaultColor) {
|
||||
try {
|
||||
return Utils.getColorFromString(resourceName);
|
||||
} catch (Exception ex) {
|
||||
// User entered an invalid custom theme color.
|
||||
// Normally this should never be reached, and no localized strings are needed.
|
||||
Utils.showToastLong("Invalid custom theme color: " + resourceName);
|
||||
return defaultColor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The dark theme color as specified by the Theme patch (if included),
|
||||
* or the dark mode background color unpatched YT uses.
|
||||
*/
|
||||
public static int getDarkThemeColor() {
|
||||
if (darkThemeColor == null) {
|
||||
darkThemeColor = getColorInt(darkThemeResourceName());
|
||||
darkThemeColor = getThemeColor(darkThemeResourceName(), Color.BLACK);
|
||||
}
|
||||
return darkThemeColor;
|
||||
}
|
||||
@@ -71,18 +82,11 @@ public class ThemeHelper {
|
||||
*/
|
||||
public static int getLightThemeColor() {
|
||||
if (lightThemeColor == null) {
|
||||
lightThemeColor = getColorInt(lightThemeResourceName());
|
||||
lightThemeColor = getThemeColor(lightThemeResourceName(), Color.WHITE);
|
||||
}
|
||||
return lightThemeColor;
|
||||
}
|
||||
|
||||
private static int getColorInt(String colorString) {
|
||||
if (colorString.startsWith("#")) {
|
||||
return Color.parseColor(colorString);
|
||||
}
|
||||
return Utils.getResourceColor(colorString);
|
||||
}
|
||||
|
||||
public static int getBackgroundColor() {
|
||||
return isDarkTheme() ? getDarkThemeColor() : getLightThemeColor();
|
||||
}
|
||||
@@ -96,6 +100,6 @@ public class ThemeHelper {
|
||||
? "yt_black3"
|
||||
: "yt_white1";
|
||||
|
||||
return getColorInt(colorName);
|
||||
return Utils.getColorFromString(colorName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class BackgroundPlaybackPatch {
|
||||
@@ -23,16 +24,13 @@ public class BackgroundPlaybackPatch {
|
||||
// 7. Close the Short
|
||||
// 8. Resume playing the regular video
|
||||
// 9. Minimize the app (PIP should appear)
|
||||
if (!VideoInformation.lastVideoIdIsShort()) {
|
||||
return true; // Definitely is not a Short.
|
||||
if (ShortsPlayerState.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add better hook.
|
||||
// Might be a Shorts, or might be a prior regular video on screen again after a Shorts was closed.
|
||||
// This incorrectly prevents PIP if player is in WATCH_WHILE_MINIMIZED after closing a Shorts,
|
||||
// But there's no way around this unless an additional hook is added to definitively detect
|
||||
// the Shorts player is on screen. This use case is unusual anyways so it's not a huge concern.
|
||||
return !PlayerType.getCurrent().isNoneHiddenOrMinimized();
|
||||
// Check if the video player is opened and it's not playing in the feed.
|
||||
PlayerType current = PlayerType.getCurrent();
|
||||
return !current.isNoneOrHidden() && current != PlayerType.INLINE_MINIMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.NavigationBar;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ChangeFormFactorPatch {
|
||||
@@ -41,14 +49,57 @@ public class ChangeFormFactorPatch {
|
||||
|
||||
@Nullable
|
||||
private static final Integer FORM_FACTOR_TYPE = Settings.CHANGE_FORM_FACTOR.get().formFactorType;
|
||||
private static final boolean USING_AUTOMOTIVE_TYPE = Objects.requireNonNull(
|
||||
FormFactor.AUTOMOTIVE.formFactorType).equals(FORM_FACTOR_TYPE);
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int getFormFactor(int original) {
|
||||
return FORM_FACTOR_TYPE == null
|
||||
? original
|
||||
: FORM_FACTOR_TYPE;
|
||||
if (FORM_FACTOR_TYPE == null) return original;
|
||||
|
||||
if (USING_AUTOMOTIVE_TYPE) {
|
||||
// Do not change if the player is opening or is opened,
|
||||
// otherwise the video description cannot be opened.
|
||||
PlayerType current = PlayerType.getCurrent();
|
||||
if (current.isMaximizedOrFullscreen() || current == PlayerType.WATCH_WHILE_SLIDING_MINIMIZED_MAXIMIZED) {
|
||||
Logger.printDebug(() -> "Using original form factor for player");
|
||||
return original;
|
||||
}
|
||||
|
||||
if (!NavigationBar.isSearchBarActive()) {
|
||||
// Automotive type shows error 400 when opening a channel page and using some explore tab.
|
||||
// This is a bug in unpatched YouTube that occurs on actual Android Automotive devices.
|
||||
// Work around the issue by using the original form factor if not in search and the
|
||||
// navigation back button is present.
|
||||
if (NavigationBar.isBackButtonVisible()) {
|
||||
Logger.printDebug(() -> "Using original form factor, as back button is visible without search present");
|
||||
return original;
|
||||
}
|
||||
|
||||
// Do not change library tab otherwise watch history is hidden.
|
||||
// Do this check last since the current navigation button is required.
|
||||
if (NavigationButton.getSelectedNavigationButton() == NavigationButton.LIBRARY) {
|
||||
return original;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FORM_FACTOR_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void navigationTabCreated(NavigationButton button, View tabView) {
|
||||
// On first startup of the app the navigation buttons are fetched and updated.
|
||||
// If the user immediately opens the 'You' or opens a video, then the call to
|
||||
// update the navigtation buttons will use the non automotive form factor
|
||||
// and the explore tab is missing.
|
||||
// Fixing this is not so simple because of the concurrent calls for the player and You tab.
|
||||
// For now, always hide the explore tab.
|
||||
if (USING_AUTOMOTIVE_TYPE && button == NavigationButton.EXPLORE) {
|
||||
tabView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,21 +23,30 @@ public final class ChangeStartPagePatch {
|
||||
/**
|
||||
* Browse id.
|
||||
*/
|
||||
ALL_SUBSCRIPTIONS("FEchannels", TRUE),
|
||||
BROWSE("FEguide_builder", TRUE),
|
||||
EXPLORE("FEexplore", TRUE),
|
||||
HISTORY("FEhistory", TRUE),
|
||||
LIBRARY("FElibrary", TRUE),
|
||||
MOVIE("FEstorefront", TRUE),
|
||||
NOTIFICATIONS("FEactivity", TRUE),
|
||||
PLAYLISTS("FEplaylist_aggregation", TRUE),
|
||||
SUBSCRIPTIONS("FEsubscriptions", TRUE),
|
||||
TRENDING("FEtrending", TRUE),
|
||||
YOUR_CLIPS("FEclips", TRUE),
|
||||
|
||||
/**
|
||||
* Channel id, this can be used as a browseId.
|
||||
*/
|
||||
COURSES("UCtFRv9O2AHqOZjjynzrv-xg", TRUE),
|
||||
FASHION("UCrpQ4p1Ql_hG8rKXIKM1MOQ", TRUE),
|
||||
GAMING("UCOpNcN46UbXVtpKMrmU4Abg", TRUE),
|
||||
LIVE("UC4R8DWoMoI7CAwX8_LjQHig", TRUE),
|
||||
MUSIC("UC-9-kyTW8ZkZNDHQJ6FgpwQ", TRUE),
|
||||
NEWS("UCYfdidRxbB8Qhf0Nx7ioOYw", TRUE),
|
||||
SHOPPING("UCkYQyvc_i9hXEo4xic9Hh2g", TRUE),
|
||||
SPORTS("UCEgdi0XIXXZ-qJOFPf4JSKw", TRUE),
|
||||
VIRTUAL_REALITY("UCzuqhhs6NWbgTzMuM09WKDQ", TRUE),
|
||||
|
||||
/**
|
||||
* Playlist id, this can be used as a browseId.
|
||||
@@ -51,12 +60,12 @@ public final class ChangeStartPagePatch {
|
||||
SEARCH("com.google.android.youtube.action.open.search", FALSE),
|
||||
SHORTS("com.google.android.youtube.action.open.shorts", FALSE);
|
||||
|
||||
@Nullable
|
||||
final Boolean isBrowseId;
|
||||
|
||||
@NonNull
|
||||
final String id;
|
||||
|
||||
@Nullable
|
||||
final Boolean isBrowseId;
|
||||
|
||||
StartPage(@NonNull String id, @Nullable Boolean isBrowseId) {
|
||||
this.id = id;
|
||||
this.isBrowseId = isBrowseId;
|
||||
@@ -122,7 +131,7 @@ public final class ChangeStartPagePatch {
|
||||
}
|
||||
appLaunched = true;
|
||||
|
||||
final String intentAction = START_PAGE.id;
|
||||
String intentAction = START_PAGE.id;
|
||||
Logger.printDebug(() -> "Changing intent action to " + intentAction);
|
||||
intent.setAction(intentAction);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DisableAutoCaptionsPatch {
|
||||
@@ -14,7 +14,7 @@ public class DisableAutoCaptionsPatch {
|
||||
public static boolean autoCaptionsEnabled() {
|
||||
return Settings.AUTO_CAPTIONS.get()
|
||||
// Do not use auto captions for Shorts.
|
||||
&& !PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized();
|
||||
&& ShortsPlayerState.isOpen();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/** @noinspection unused*/
|
||||
@SuppressWarnings("unused")
|
||||
public class DisableResumingStartupShortsPlayerPatch {
|
||||
|
||||
/**
|
||||
@@ -11,4 +11,11 @@ public class DisableResumingStartupShortsPlayerPatch {
|
||||
public static boolean disableResumingStartupShortsPlayer() {
|
||||
return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean disableResumingStartupShortsPlayer(boolean original) {
|
||||
return original && !Settings.DISABLE_RESUMING_SHORTS_PLAYER.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/** @noinspection unused*/
|
||||
public final class DisableSuggestedVideoEndScreenPatch {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static ImageView lastView;
|
||||
|
||||
public static void closeEndScreen(final ImageView imageView) {
|
||||
if (!Settings.DISABLE_SUGGESTED_VIDEO_END_SCREEN.get()) return;
|
||||
|
||||
// Prevent adding the listener multiple times.
|
||||
if (lastView == imageView) return;
|
||||
lastView = imageView;
|
||||
|
||||
imageView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
|
||||
if (imageView.isShown()) imageView.callOnClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public final class EnableDebuggingPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isBooleanFeatureFlagEnabled(boolean value, long flag) {
|
||||
public static boolean isBooleanFeatureFlagEnabled(boolean value, Long flag) {
|
||||
if (LOG_FEATURE_FLAGS && value) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
Logger.printDebug(() -> "boolean feature is enabled: " + flag);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class HideEndScreenSuggestedVideoPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean hideEndScreenSuggestedVideo() {
|
||||
return Settings.HIDE_END_SCREEN_SUGGESTED_VIDEO.get();
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,13 @@ public final class MiniplayerPatch {
|
||||
MODERN_2(null, 2),
|
||||
MODERN_3(null, 3),
|
||||
/**
|
||||
* Half broken miniplayer, that might be work in progress or left over abandoned code.
|
||||
* Can force this type by editing the import/export settings.
|
||||
* Works and is functional with 20.03+
|
||||
*/
|
||||
MODERN_4(null, 4);
|
||||
MODERN_4(null, 4),
|
||||
/**
|
||||
* Half broken miniplayer, and in 20.02 and earlier is declared as type 4.
|
||||
*/
|
||||
MODERN_5(null, 5);
|
||||
|
||||
/**
|
||||
* Legacy tablet hook value.
|
||||
@@ -126,12 +129,13 @@ public final class MiniplayerPatch {
|
||||
private static final boolean DRAG_AND_DROP_ENABLED =
|
||||
CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DRAG_AND_DROP.get();
|
||||
|
||||
private static final boolean HIDE_EXPAND_CLOSE_ENABLED =
|
||||
Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.get()
|
||||
&& Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.isAvailable();
|
||||
private static final boolean HIDE_OVERLAY_BUTTONS_ENABLED =
|
||||
Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.get()
|
||||
&& Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.isAvailable();
|
||||
|
||||
private static final boolean HIDE_SUBTEXT_ENABLED =
|
||||
(CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3) && Settings.MINIPLAYER_HIDE_SUBTEXT.get();
|
||||
(CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3 || CURRENT_TYPE == MODERN_4)
|
||||
&& Settings.MINIPLAYER_HIDE_SUBTEXT.get();
|
||||
|
||||
// 19.25 is last version that has forward/back buttons for phones,
|
||||
// but buttons still show for tablets/foldable devices and they don't work well so always hide.
|
||||
@@ -139,7 +143,7 @@ public final class MiniplayerPatch {
|
||||
&& (VersionCheckPatch.IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get());
|
||||
|
||||
private static final boolean MINIPLAYER_ROUNDED_CORNERS_ENABLED =
|
||||
Settings.MINIPLAYER_ROUNDED_CORNERS.get();
|
||||
CURRENT_TYPE.isModern() && Settings.MINIPLAYER_ROUNDED_CORNERS.get();
|
||||
|
||||
private static final boolean MINIPLAYER_HORIZONTAL_DRAG_ENABLED =
|
||||
DRAG_AND_DROP_ENABLED && Settings.MINIPLAYER_HORIZONTAL_DRAG.get();
|
||||
@@ -172,11 +176,12 @@ public final class MiniplayerPatch {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class MiniplayerHideExpandCloseAvailability implements Setting.Availability {
|
||||
public static final class MiniplayerHideOverlayButtonsAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
MiniplayerType type = Settings.MINIPLAYER_TYPE.get();
|
||||
return (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3))
|
||||
return type == MODERN_4
|
||||
|| (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3))
|
||||
|| (!IS_19_26_OR_GREATER && type == MODERN_1
|
||||
&& !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && !Settings.MINIPLAYER_DRAG_AND_DROP.get())
|
||||
|| (IS_19_29_OR_GREATER && type == MODERN_3);
|
||||
@@ -227,9 +232,13 @@ public final class MiniplayerPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void adjustMiniplayerOpacity(ImageView view) {
|
||||
public static void adjustMiniplayerOpacity(View view) {
|
||||
if (CURRENT_TYPE == MODERN_1) {
|
||||
view.setImageAlpha(OPACITY_LEVEL);
|
||||
if (view instanceof ImageView imageView) {
|
||||
imageView.setImageAlpha(OPACITY_LEVEL);
|
||||
} else {
|
||||
Logger.printException(() -> "Unknown miniplayer overlay view: " + view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +256,7 @@ public final class MiniplayerPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean enableMiniplayerDoubleTapAction(boolean original) {
|
||||
public static boolean getMiniplayerDoubleTapAction(boolean original) {
|
||||
if (CURRENT_TYPE == DEFAULT) {
|
||||
return original;
|
||||
}
|
||||
@@ -258,7 +267,7 @@ public final class MiniplayerPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean enableMiniplayerDragAndDrop(boolean original) {
|
||||
public static boolean getMiniplayerDragAndDrop(boolean original) {
|
||||
if (CURRENT_TYPE == DEFAULT) {
|
||||
return original;
|
||||
}
|
||||
@@ -266,13 +275,36 @@ public final class MiniplayerPatch {
|
||||
return DRAG_AND_DROP_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getRoundedCorners(boolean original) {
|
||||
if (CURRENT_TYPE == DEFAULT) {
|
||||
return original;
|
||||
}
|
||||
|
||||
return MINIPLAYER_ROUNDED_CORNERS_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean setRoundedCorners(boolean original) {
|
||||
if (CURRENT_TYPE.isModern()) {
|
||||
return MINIPLAYER_ROUNDED_CORNERS_ENABLED;
|
||||
public static boolean getHorizontalDrag(boolean original) {
|
||||
if (CURRENT_TYPE == DEFAULT) {
|
||||
return original;
|
||||
}
|
||||
|
||||
return MINIPLAYER_HORIZONTAL_DRAG_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getMaximizeAnimation(boolean original) {
|
||||
// This must be forced on if horizontal drag is enabled,
|
||||
// otherwise the UI has visual glitches when maximizing the miniplayer.
|
||||
if (MINIPLAYER_HORIZONTAL_DRAG_ENABLED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return original;
|
||||
@@ -281,7 +313,7 @@ public final class MiniplayerPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int setMiniplayerDefaultSize(int original) {
|
||||
public static int getMiniplayerDefaultSize(int original) {
|
||||
if (CURRENT_TYPE.isModern()) {
|
||||
return MINIPLAYER_SIZE;
|
||||
}
|
||||
@@ -289,29 +321,26 @@ public final class MiniplayerPatch {
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideMiniplayerExpandClose(View view) {
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_OVERLAY_BUTTONS_ENABLED, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean setHorizontalDrag(boolean original) {
|
||||
if (CURRENT_TYPE.isModern()) {
|
||||
return MINIPLAYER_HORIZONTAL_DRAG_ENABLED;
|
||||
public static void hideMiniplayerActionButton(View view) {
|
||||
if (CURRENT_TYPE == MODERN_4) {
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_OVERLAY_BUTTONS_ENABLED, view);
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideMiniplayerExpandClose(ImageView view) {
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_EXPAND_CLOSE_ENABLED, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideMiniplayerRewindForward(ImageView view) {
|
||||
public static void hideMiniplayerRewindForward(View view) {
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_REWIND_FORWARD_ENABLED, view);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ public final class NavigationButtonsPatch {
|
||||
{
|
||||
put(NavigationButton.HOME, Settings.HIDE_HOME_BUTTON.get());
|
||||
put(NavigationButton.CREATE, Settings.HIDE_CREATE_BUTTON.get());
|
||||
put(NavigationButton.NOTIFICATIONS, Settings.HIDE_NOTIFICATIONS_BUTTON.get());
|
||||
put(NavigationButton.SHORTS, Settings.HIDE_SHORTS_BUTTON.get());
|
||||
put(NavigationButton.SUBSCRIPTIONS, Settings.HIDE_SUBSCRIPTIONS_BUTTON.get());
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
import app.revanced.extension.youtube.shared.VideoState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -24,4 +27,26 @@ public class PlayerTypeHookPatch {
|
||||
|
||||
VideoState.setFromString(youTubeVideoState.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Add a listener to the shorts player overlay View.
|
||||
* Triggered when a shorts player is attached or detached to Windows.
|
||||
*
|
||||
* @param view shorts player overlay (R.id.reel_watch_player).
|
||||
*/
|
||||
public static void onShortsCreate(View view) {
|
||||
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(@Nullable View v) {
|
||||
ShortsPlayerState.setOpen(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(@Nullable View v) {
|
||||
ShortsPlayerState.setOpen(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,27 +2,21 @@ package app.revanced.extension.youtube.patches;
|
||||
|
||||
import static app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike.Vote;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilterPatch;
|
||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -48,9 +42,6 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@SuppressWarnings("unused")
|
||||
public class ReturnYouTubeDislikePatch {
|
||||
|
||||
public static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER =
|
||||
SpoofAppVersionPatch.isSpoofingToLessThan("18.34.00");
|
||||
|
||||
/**
|
||||
* RYD data for the current video on screen.
|
||||
*/
|
||||
@@ -65,12 +56,12 @@ public class ReturnYouTubeDislikePatch {
|
||||
private static volatile ReturnYouTubeDislike lastLithoShortsVideoData;
|
||||
|
||||
/**
|
||||
* Because the litho Shorts spans are created after {@link ReturnYouTubeDislikeFilterPatch}
|
||||
* detects the video ids, after the user votes the litho will update
|
||||
* but {@link #lastLithoShortsVideoData} is not the correct data to use.
|
||||
* If this is true, then instead use {@link #currentVideoData}.
|
||||
* Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilterPatch}
|
||||
* detects the video ids, but the current Short can arbitrarily reload the same span,
|
||||
* then use the {@link #lastLithoShortsVideoData} if this value is greater than zero.
|
||||
*/
|
||||
private static volatile boolean lithoShortsShouldUseCurrentData;
|
||||
@GuardedBy("ReturnYouTubeDislikePatch.class")
|
||||
private static int useLithoShortsVideoDataCount;
|
||||
|
||||
/**
|
||||
* Last video id prefetched. Field is to prevent prefetching the same video id multiple times in a row.
|
||||
@@ -88,12 +79,28 @@ public class ReturnYouTubeDislikePatch {
|
||||
private static void clearData() {
|
||||
currentVideoData = null;
|
||||
lastLithoShortsVideoData = null;
|
||||
lithoShortsShouldUseCurrentData = false;
|
||||
synchronized (ReturnYouTubeDislike.class) {
|
||||
useLithoShortsVideoDataCount = 0;
|
||||
}
|
||||
|
||||
// Rolling number text should not be cleared,
|
||||
// as it's used if incognito Short is opened/closed
|
||||
// while a regular video is on screen.
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If {@link #useLithoShortsVideoDataCount} was greater than zero.
|
||||
*/
|
||||
private static boolean decrementUseLithoDataIfNeeded() {
|
||||
synchronized (ReturnYouTubeDislikePatch.class) {
|
||||
if (useLithoShortsVideoDataCount > 0) {
|
||||
useLithoShortsVideoDataCount--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Litho player for both regular videos and Shorts.
|
||||
@@ -157,10 +164,13 @@ public class ReturnYouTubeDislikePatch {
|
||||
return getShortsSpan(original, true);
|
||||
}
|
||||
|
||||
if (conversionContextString.contains("|shorts_like_button.eml")
|
||||
&& !Utils.containsNumber(original)) {
|
||||
Logger.printDebug(() -> "Replacing hidden likes count");
|
||||
return getShortsSpan(original, false);
|
||||
if (conversionContextString.contains("|shorts_like_button.eml")) {
|
||||
if (!Utils.containsNumber(original)) {
|
||||
Logger.printDebug(() -> "Replacing hidden likes count");
|
||||
return getShortsSpan(original, false);
|
||||
} else {
|
||||
decrementUseLithoDataIfNeeded();
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "onLithoTextLoaded failure", ex);
|
||||
@@ -175,7 +185,14 @@ public class ReturnYouTubeDislikePatch {
|
||||
return original;
|
||||
}
|
||||
|
||||
ReturnYouTubeDislike videoData = lastLithoShortsVideoData;
|
||||
final ReturnYouTubeDislike videoData;
|
||||
if (decrementUseLithoDataIfNeeded()) {
|
||||
// New Short is loading off screen.
|
||||
videoData = lastLithoShortsVideoData;
|
||||
} else {
|
||||
videoData = currentVideoData;
|
||||
}
|
||||
|
||||
if (videoData == null) {
|
||||
// The Shorts litho video id filter did not detect the video id.
|
||||
// This is normal in incognito mode, but otherwise is abnormal.
|
||||
@@ -183,19 +200,6 @@ public class ReturnYouTubeDislikePatch {
|
||||
return original;
|
||||
}
|
||||
|
||||
// Use the correct dislikes data after voting.
|
||||
if (lithoShortsShouldUseCurrentData) {
|
||||
if (isDislikesSpan) {
|
||||
lithoShortsShouldUseCurrentData = false;
|
||||
}
|
||||
videoData = currentVideoData;
|
||||
if (videoData == null) {
|
||||
Logger.printException(() -> "currentVideoData is null"); // Should never happen
|
||||
return original;
|
||||
}
|
||||
Logger.printDebug(() -> "Using current video data for litho span");
|
||||
}
|
||||
|
||||
return isDislikesSpan
|
||||
? videoData.getDislikeSpanForShort((Spanned) original)
|
||||
: videoData.getLikeSpanForShort((Spanned) original);
|
||||
@@ -348,139 +352,6 @@ public class ReturnYouTubeDislikePatch {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Non litho Shorts player.
|
||||
//
|
||||
|
||||
/**
|
||||
* Replacement text to use for "Dislikes" while RYD is fetching.
|
||||
*/
|
||||
private static final Spannable SHORTS_LOADING_SPAN = new SpannableString("-");
|
||||
|
||||
/**
|
||||
* Dislikes TextViews used by Shorts.
|
||||
*
|
||||
* Multiple TextViews are loaded at once (for the prior and next videos to swipe to).
|
||||
* Keep track of all of them, and later pick out the correct one based on their on screen position.
|
||||
*/
|
||||
private static final List<WeakReference<TextView>> shortsTextViewRefs = new ArrayList<>();
|
||||
|
||||
private static void clearRemovedShortsTextViews() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // YouTube requires Android N or greater
|
||||
shortsTextViewRefs.removeIf(ref -> ref.get() == null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. Called when a Shorts dislike is updated. Always on main thread.
|
||||
* Handles update asynchronously, otherwise Shorts video will be frozen while the UI thread is blocked.
|
||||
*
|
||||
* @return if RYD is enabled and the TextView was updated.
|
||||
*/
|
||||
public static boolean setShortsDislikes(@NonNull View likeDislikeView) {
|
||||
try {
|
||||
if (!Settings.RYD_ENABLED.get()) {
|
||||
return false;
|
||||
}
|
||||
if (!Settings.RYD_SHORTS.get() || Settings.HIDE_SHORTS_DISLIKE_BUTTON.get()) {
|
||||
// Must clear the data here, in case a new video was loaded while PlayerType
|
||||
// suggested the video was not a short (can happen when spoofing to an old app version).
|
||||
clearData();
|
||||
return false;
|
||||
}
|
||||
Logger.printDebug(() -> "setShortsDislikes");
|
||||
|
||||
TextView textView = (TextView) likeDislikeView;
|
||||
textView.setText(SHORTS_LOADING_SPAN); // Change 'Dislike' text to the loading text.
|
||||
shortsTextViewRefs.add(new WeakReference<>(textView));
|
||||
|
||||
if (likeDislikeView.isSelected() && isShortTextViewOnScreen(textView)) {
|
||||
Logger.printDebug(() -> "Shorts dislike is already selected");
|
||||
ReturnYouTubeDislike videoData = currentVideoData;
|
||||
if (videoData != null) videoData.setUserVote(Vote.DISLIKE);
|
||||
}
|
||||
|
||||
// For the first short played, the Shorts dislike hook is called after the video id hook.
|
||||
// But for most other times this hook is called before the video id (which is not ideal).
|
||||
// Must update the TextViews here, and also after the videoId changes.
|
||||
updateOnScreenShortsTextViews(false);
|
||||
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "setShortsDislikes failure", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forceUpdate if false, then only update the 'loading text views.
|
||||
* If true, update all on screen text views.
|
||||
*/
|
||||
private static void updateOnScreenShortsTextViews(boolean forceUpdate) {
|
||||
try {
|
||||
clearRemovedShortsTextViews();
|
||||
if (shortsTextViewRefs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ReturnYouTubeDislike videoData = currentVideoData;
|
||||
if (videoData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "updateShortsTextViews");
|
||||
|
||||
Runnable update = () -> {
|
||||
Spanned shortsDislikesSpan = videoData.getDislikeSpanForShort(SHORTS_LOADING_SPAN);
|
||||
Utils.runOnMainThreadNowOrLater(() -> {
|
||||
String videoId = videoData.getVideoId();
|
||||
if (!videoId.equals(VideoInformation.getVideoId())) {
|
||||
// User swiped to new video before fetch completed
|
||||
Logger.printDebug(() -> "Ignoring stale dislikes data for short: " + videoId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update text views that appear to be visible on screen.
|
||||
// Only 1 will be the actual textview for the current Short,
|
||||
// but discarded and not yet garbage collected views can remain.
|
||||
// So must set the dislike span on all views that match.
|
||||
for (WeakReference<TextView> textViewRef : shortsTextViewRefs) {
|
||||
TextView textView = textViewRef.get();
|
||||
if (textView == null) {
|
||||
continue;
|
||||
}
|
||||
if (isShortTextViewOnScreen(textView)
|
||||
&& (forceUpdate || textView.getText().toString().equals(SHORTS_LOADING_SPAN.toString()))) {
|
||||
Logger.printDebug(() -> "Setting Shorts TextView to: " + shortsDislikesSpan);
|
||||
textView.setText(shortsDislikesSpan);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
if (videoData.fetchCompleted()) {
|
||||
update.run(); // Network call is completed, no need to wait on background thread.
|
||||
} else {
|
||||
Utils.runOnBackgroundThread(update);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "updateOnScreenShortsTextViews failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a view is within the screen bounds.
|
||||
*/
|
||||
private static boolean isShortTextViewOnScreen(@NonNull View view) {
|
||||
final int[] location = new int[2];
|
||||
view.getLocationInWindow(location);
|
||||
if (location[0] <= 0 && location[1] <= 0) { // Lower bound
|
||||
return false;
|
||||
}
|
||||
Rect windowRect = new Rect();
|
||||
view.getWindowVisibleDisplayFrame(windowRect); // Upper bound
|
||||
return location[0] < windowRect.width() && location[1] < windowRect.height();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Video Id and voting hooks (all players).
|
||||
//
|
||||
@@ -506,8 +377,7 @@ public class ReturnYouTubeDislikePatch {
|
||||
if (videoIdIsShort && (!isShortAndOpeningOrPlaying || !Settings.RYD_SHORTS.get())) {
|
||||
return;
|
||||
}
|
||||
final boolean waitForFetchToComplete = !IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER
|
||||
&& videoIdIsShort && !lastPlayerResponseWasShort;
|
||||
final boolean waitForFetchToComplete = videoIdIsShort && !lastPlayerResponseWasShort;
|
||||
|
||||
Logger.printDebug(() -> "Prefetching RYD for video: " + videoId);
|
||||
ReturnYouTubeDislike fetch = ReturnYouTubeDislike.getFetchForVideoId(videoId);
|
||||
@@ -560,12 +430,6 @@ public class ReturnYouTubeDislikePatch {
|
||||
data.setVideoIdIsShort(true);
|
||||
}
|
||||
currentVideoData = data;
|
||||
|
||||
// Current video id hook can be called out of order with the non litho Shorts text view hook.
|
||||
// Must manually update again here.
|
||||
if (isNoneHiddenOrSlidingMinimized) {
|
||||
updateOnScreenShortsTextViews(true);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "newVideoLoaded failure", ex);
|
||||
}
|
||||
@@ -590,7 +454,10 @@ public class ReturnYouTubeDislikePatch {
|
||||
ReturnYouTubeDislike videoData = ReturnYouTubeDislike.getFetchForVideoId(videoId);
|
||||
videoData.setVideoIdIsShort(true);
|
||||
lastLithoShortsVideoData = videoData;
|
||||
lithoShortsShouldUseCurrentData = false;
|
||||
synchronized (ReturnYouTubeDislikePatch.class) {
|
||||
// Use litho Shorts data for the next like and dislike spans.
|
||||
useLithoShortsVideoDataCount = 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean videoIdIsSame(@Nullable ReturnYouTubeDislike fetch, @Nullable String videoId) {
|
||||
@@ -625,13 +492,6 @@ public class ReturnYouTubeDislikePatch {
|
||||
for (Vote v : Vote.values()) {
|
||||
if (v.value == vote) {
|
||||
videoData.sendVote(v);
|
||||
|
||||
if (isNoneHiddenOrMinimized) {
|
||||
if (lastLithoShortsVideoData != null) {
|
||||
lithoShortsShouldUseCurrentData = true;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
@@ -58,7 +55,6 @@ public class ShortsAutoplayPatch {
|
||||
/**
|
||||
* @return If the app is currently in background PiP mode.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
private static boolean isAppInBackgroundPiPMode() {
|
||||
Activity activity = mainActivityRef.get();
|
||||
return activity != null && activity.isInPictureInPictureMode();
|
||||
@@ -80,7 +76,6 @@ public class ShortsAutoplayPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public static Enum<?> changeShortsRepeatBehavior(Enum<?> original) {
|
||||
try {
|
||||
final boolean autoplay;
|
||||
|
||||
@@ -3,11 +3,15 @@ package app.revanced.extension.youtube.patches;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
public class VersionCheckPatch {
|
||||
public static final boolean IS_19_17_OR_GREATER = Utils.getAppVersionName().compareTo("19.17.00") >= 0;
|
||||
public static final boolean IS_19_20_OR_GREATER = Utils.getAppVersionName().compareTo("19.20.00") >= 0;
|
||||
public static final boolean IS_19_21_OR_GREATER = Utils.getAppVersionName().compareTo("19.21.00") >= 0;
|
||||
public static final boolean IS_19_26_OR_GREATER = Utils.getAppVersionName().compareTo("19.26.00") >= 0;
|
||||
public static final boolean IS_19_29_OR_GREATER = Utils.getAppVersionName().compareTo("19.29.00") >= 0;
|
||||
public static final boolean IS_19_34_OR_GREATER = Utils.getAppVersionName().compareTo("19.34.00") >= 0;
|
||||
public static final boolean IS_19_46_OR_GREATER = Utils.getAppVersionName().compareTo("19.46.00") >= 0;
|
||||
private static boolean isVersionOrGreater(String version) {
|
||||
return Utils.getAppVersionName().compareTo(version) >= 0;
|
||||
}
|
||||
|
||||
public static final boolean IS_19_17_OR_GREATER = isVersionOrGreater("19.17.00");
|
||||
public static final boolean IS_19_20_OR_GREATER = isVersionOrGreater("19.20.00");
|
||||
public static final boolean IS_19_21_OR_GREATER = isVersionOrGreater("19.21.00");
|
||||
public static final boolean IS_19_26_OR_GREATER = isVersionOrGreater("19.26.00");
|
||||
public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.00");
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -7,13 +7,10 @@ import static app.revanced.extension.youtube.patches.announcements.requests.Anno
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -31,7 +28,6 @@ public final class AnnouncementsPatch {
|
||||
private AnnouncementsPatch() {
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
private static boolean isLatestAlready() throws IOException {
|
||||
HttpURLConnection connection =
|
||||
AnnouncementsRoutes.getAnnouncementsConnectionFromRoute(GET_LATEST_ANNOUNCEMENT_IDS);
|
||||
@@ -70,7 +66,6 @@ public final class AnnouncementsPatch {
|
||||
return Settings.ANNOUNCEMENT_LAST_ID.get() == id;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public static void showAnnouncement(final Activity context) {
|
||||
if (!Settings.ANNOUNCEMENTS.get()) return;
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ public final class AdsFilter extends Filter {
|
||||
"video_display_button_group_layout",
|
||||
"landscape_image_wide_button_layout",
|
||||
"video_display_carousel_button_group_layout",
|
||||
"video_display_full_buttoned_short_dr_layout",
|
||||
"compact_landscape_image_layout", // Tablet layout search results.
|
||||
"text_image_no_button_layout" // Tablet layout search results.
|
||||
);
|
||||
|
||||
@@ -2,20 +2,20 @@ package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.patches.playback.quality.RestoreOldVideoQualityMenuPatch;
|
||||
import app.revanced.extension.youtube.patches.playback.quality.AdvancedVideoQualityMenuPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
* Abuse LithoFilter for {@link RestoreOldVideoQualityMenuPatch}.
|
||||
* Abuse LithoFilter for {@link AdvancedVideoQualityMenuPatch}.
|
||||
*/
|
||||
public final class VideoQualityMenuFilterPatch extends Filter {
|
||||
public final class AdvancedVideoQualityMenuFilter extends Filter {
|
||||
// Must be volatile or synchronized, as litho filtering runs off main thread
|
||||
// and this field is then access from the main thread.
|
||||
public static volatile boolean isVideoQualityMenuVisible;
|
||||
|
||||
public VideoQualityMenuFilterPatch() {
|
||||
public AdvancedVideoQualityMenuFilter() {
|
||||
addPathCallbacks(new StringFilterGroup(
|
||||
Settings.RESTORE_OLD_VIDEO_QUALITY_MENU,
|
||||
Settings.ADVANCED_VIDEO_QUALITY_MENU,
|
||||
"quick_quality_sheet_content.eml-js"
|
||||
));
|
||||
}
|
||||
@@ -6,8 +6,12 @@ import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
final class ButtonsFilter extends Filter {
|
||||
private static final String COMPACT_CHANNEL_BAR_PATH_PREFIX = "compact_channel_bar.eml";
|
||||
private static final String VIDEO_ACTION_BAR_PATH_PREFIX = "video_action_bar.eml";
|
||||
private static final String VIDEO_ACTION_BAR_PATH = "video_action_bar.eml";
|
||||
private static final String ANIMATED_VECTOR_TYPE_PATH = "AnimatedVectorType";
|
||||
|
||||
private final StringFilterGroup likeSubscribeGlow;
|
||||
private final StringFilterGroup actionBarGroup;
|
||||
private final StringFilterGroup bufferFilterPathGroup;
|
||||
private final ByteArrayFilterGroupList bufferButtonsGroupList = new ByteArrayFilterGroupList();
|
||||
@@ -20,11 +24,19 @@ final class ButtonsFilter extends Filter {
|
||||
addIdentifierCallbacks(actionBarGroup);
|
||||
|
||||
|
||||
likeSubscribeGlow = new StringFilterGroup(
|
||||
Settings.DISABLE_LIKE_SUBSCRIBE_GLOW,
|
||||
"animated_button_border.eml"
|
||||
);
|
||||
|
||||
bufferFilterPathGroup = new StringFilterGroup(
|
||||
null,
|
||||
"|ContainerType|button.eml|"
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
likeSubscribeGlow,
|
||||
bufferFilterPathGroup,
|
||||
new StringFilterGroup(
|
||||
Settings.HIDE_LIKE_DISLIKE_BUTTON,
|
||||
"|segmented_like_dislike_button"
|
||||
@@ -40,8 +52,7 @@ final class ButtonsFilter extends Filter {
|
||||
new StringFilterGroup(
|
||||
Settings.HIDE_CLIP_BUTTON,
|
||||
"|clip_button.eml|"
|
||||
),
|
||||
bufferFilterPathGroup
|
||||
)
|
||||
);
|
||||
|
||||
bufferButtonsGroupList.addAll(
|
||||
@@ -83,6 +94,15 @@ final class ButtonsFilter extends Filter {
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (matchedGroup == likeSubscribeGlow) {
|
||||
if ((path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX))
|
||||
&& path.contains(ANIMATED_VECTOR_TYPE_PATH)) {
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the current matched group is the action bar group,
|
||||
// in case every filter group is enabled, hide the action bar.
|
||||
if (matchedGroup == actionBarGroup) {
|
||||
|
||||
@@ -12,10 +12,12 @@ final class CommentsFilter extends Filter {
|
||||
|
||||
private final StringFilterGroup commentComposer;
|
||||
private final ByteArrayFilterGroup emojiPickerBufferGroup;
|
||||
private final StringFilterGroup filterChipBar;
|
||||
private final ByteArrayFilterGroup aiCommentsSummary;
|
||||
|
||||
public CommentsFilter() {
|
||||
var chatSummary = new StringFilterGroup(
|
||||
Settings.HIDE_COMMENTS_CHAT_SUMMARY,
|
||||
Settings.HIDE_COMMENTS_AI_CHAT_SUMMARY,
|
||||
"live_chat_summary_banner.eml"
|
||||
);
|
||||
|
||||
@@ -58,6 +60,16 @@ final class CommentsFilter extends Filter {
|
||||
"id.comment.quick_emoji.button"
|
||||
);
|
||||
|
||||
filterChipBar = new StringFilterGroup(
|
||||
Settings.HIDE_COMMENTS_AI_SUMMARY,
|
||||
"filter_chip_bar.eml"
|
||||
);
|
||||
|
||||
aiCommentsSummary = new ByteArrayFilterGroup(
|
||||
null,
|
||||
"yt_fill_spark_"
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
chatSummary,
|
||||
commentsByMembers,
|
||||
@@ -65,7 +77,8 @@ final class CommentsFilter extends Filter {
|
||||
createAShort,
|
||||
previewComment,
|
||||
thanksButton,
|
||||
commentComposer
|
||||
commentComposer,
|
||||
filterChipBar
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,6 +97,13 @@ final class CommentsFilter extends Filter {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchedGroup == filterChipBar) {
|
||||
if (aiCommentsSummary.check(protobufBufferArray).isFiltered()) {
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,11 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
"metadata"
|
||||
);
|
||||
|
||||
final StringFilterGroup aiGeneratedVideoSummarySection = new StringFilterGroup(
|
||||
Settings.HIDE_AI_GENERATED_VIDEO_SUMMARY_SECTION,
|
||||
"cell_expandable_metadata.eml"
|
||||
);
|
||||
|
||||
final StringFilterGroup attributesSection = new StringFilterGroup(
|
||||
Settings.HIDE_ATTRIBUTES_SECTION,
|
||||
"gaming_section",
|
||||
@@ -67,6 +72,7 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
aiGeneratedVideoSummarySection,
|
||||
attributesSection,
|
||||
infoCardsSection,
|
||||
howThisWasMadeSection,
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
@@ -44,13 +41,11 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
|
||||
return filterGroups.iterator();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public void forEach(@NonNull Consumer<? super T> action) {
|
||||
filterGroups.forEach(action);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@NonNull
|
||||
@Override
|
||||
public Spliterator<T> spliterator() {
|
||||
|
||||
@@ -4,11 +4,8 @@ import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
|
||||
import static java.lang.Character.UnicodeBlock.*;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -44,7 +41,6 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
||||
* - When using whole word syntax, some keywords may need additional pluralized variations.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
final class KeywordContentFilter extends Filter {
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,11 +3,9 @@ package app.revanced.extension.youtube.patches.components;
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
@@ -18,10 +16,6 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class LayoutComponentsFilter extends Filter {
|
||||
private static final String COMPACT_CHANNEL_BAR_PATH_PREFIX = "compact_channel_bar.eml";
|
||||
private static final String VIDEO_ACTION_BAR_PATH_PREFIX = "video_action_bar.eml";
|
||||
private static final String ANIMATED_VECTOR_TYPE_PATH = "AnimatedVectorType";
|
||||
|
||||
private static final StringTrieSearch mixPlaylistsExceptions = new StringTrieSearch(
|
||||
"V.ED", // Playlist browse id.
|
||||
"java.lang.ref.WeakReference"
|
||||
@@ -38,16 +32,15 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
private final StringTrieSearch exceptions = new StringTrieSearch();
|
||||
private final StringFilterGroup inFeedSurvey;
|
||||
private final StringFilterGroup notifyMe;
|
||||
private final StringFilterGroup singleItemInformationPanel;
|
||||
private final StringFilterGroup expandableMetadata;
|
||||
private final ByteArrayFilterGroup searchResultRecommendations;
|
||||
private final StringFilterGroup searchResultVideo;
|
||||
private final StringFilterGroup compactChannelBarInner;
|
||||
private final StringFilterGroup compactChannelBarInnerButton;
|
||||
private final ByteArrayFilterGroup joinMembershipButton;
|
||||
private final StringFilterGroup likeSubscribeGlow;
|
||||
private final StringFilterGroup horizontalShelves;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public LayoutComponentsFilter() {
|
||||
exceptions.addPatterns(
|
||||
"home_video_with_context",
|
||||
@@ -81,7 +74,8 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"text_post_root_slim.eml",
|
||||
"post_base_wrapper_slim.eml",
|
||||
"poll_post_root.eml",
|
||||
"videos_post_root.eml"
|
||||
"videos_post_root.eml",
|
||||
"post_shelf_slim.eml"
|
||||
);
|
||||
|
||||
final var communityGuidelines = new StringFilterGroup(
|
||||
@@ -104,6 +98,11 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"compact_banner"
|
||||
);
|
||||
|
||||
final var subscriptionsChipBar = new StringFilterGroup(
|
||||
Settings.HIDE_FILTER_BAR_FEED_IN_FEED,
|
||||
"subscriptions_chip_bar"
|
||||
);
|
||||
|
||||
inFeedSurvey = new StringFilterGroup(
|
||||
Settings.HIDE_FEED_SURVEY,
|
||||
"in_feed_survey",
|
||||
@@ -122,8 +121,12 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
);
|
||||
|
||||
final var infoPanel = new StringFilterGroup(
|
||||
Settings.HIDE_HIDE_INFO_PANELS,
|
||||
"publisher_transparency_panel",
|
||||
Settings.HIDE_INFO_PANELS,
|
||||
"publisher_transparency_panel"
|
||||
);
|
||||
|
||||
singleItemInformationPanel = new StringFilterGroup(
|
||||
Settings.HIDE_INFO_PANELS,
|
||||
"single_item_information_panel"
|
||||
);
|
||||
|
||||
@@ -216,10 +219,6 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"sponsorships"
|
||||
);
|
||||
|
||||
likeSubscribeGlow = new StringFilterGroup(
|
||||
Settings.DISABLE_LIKE_SUBSCRIBE_GLOW,
|
||||
"animated_button_border.eml"
|
||||
);
|
||||
|
||||
final var channelWatermark = new StringFilterGroup(
|
||||
Settings.HIDE_VIDEO_CHANNEL_WATERMARK,
|
||||
@@ -253,7 +252,6 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
expandableMetadata,
|
||||
inFeedSurvey,
|
||||
notifyMe,
|
||||
likeSubscribeGlow,
|
||||
compactChannelBar,
|
||||
communityPosts,
|
||||
paidPromotion,
|
||||
@@ -268,8 +266,10 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
compactChannelBarInner,
|
||||
medicalPanel,
|
||||
infoPanel,
|
||||
singleItemInformationPanel,
|
||||
emergencyBox,
|
||||
subscribersCommunityGuidelines,
|
||||
subscriptionsChipBar,
|
||||
channelGuidelines,
|
||||
audioTrackButton,
|
||||
artistCard,
|
||||
@@ -284,6 +284,19 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
// This identifier is used not only in players but also in search results:
|
||||
// https://github.com/ReVanced/revanced-patches/issues/3245
|
||||
// Until 2024, medical information panels such as Covid 19 also used this identifier and were shown in the search results.
|
||||
// From 2025, the medical information panel is no longer shown in the search results.
|
||||
// Therefore, this identifier does not filter when the search bar is activated.
|
||||
if (matchedGroup == singleItemInformationPanel) {
|
||||
if (PlayerType.getCurrent().isMaximizedOrFullscreen() || !NavigationBar.isSearchBarActive()) {
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchedGroup == searchResultVideo) {
|
||||
if (searchResultRecommendations.check(protobufBufferArray).isFiltered()) {
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
@@ -291,15 +304,6 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchedGroup == likeSubscribeGlow) {
|
||||
if ((path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX))
|
||||
&& path.contains(ANIMATED_VECTOR_TYPE_PATH)) {
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// The groups are excluded from the filter due to the exceptions list below.
|
||||
// Filter them separately here.
|
||||
if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata)
|
||||
@@ -450,14 +454,24 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
}
|
||||
|
||||
private static boolean hideShelves() {
|
||||
// If the player is opened while library is selected,
|
||||
// then filter any recommendations below the player.
|
||||
if (PlayerType.getCurrent().isMaximizedOrFullscreen()
|
||||
// Or if the search is active while library is selected, then also filter.
|
||||
|| NavigationBar.isSearchBarActive()) {
|
||||
// Horizontal shelves are used for music/game links in video descriptions,
|
||||
// such as https://youtube.com/watch?v=W8kI1na3S2M
|
||||
if (PlayerType.getCurrent().isMaximizedOrFullscreen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must check search bar after player type, since search results
|
||||
// can be in the background behind an open player.
|
||||
if (NavigationBar.isSearchBarActive()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do not hide if the navigation back button is visible,
|
||||
// otherwise the content shelves in the explore/music/courses pages are hidde.
|
||||
if (NavigationBar.isBackButtonVisible()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check navigation button last.
|
||||
// Only filter if the library tab is not selected.
|
||||
// This check is important as the shelf layout is used for the library tab playlists.
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||
|
||||
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
|
||||
private static final boolean AVAILABLE_ON_LAUNCH = SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
|
||||
@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.notSpoofingToAndroid();
|
||||
}
|
||||
}
|
||||
|
||||
private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList();
|
||||
|
||||
private final ByteArrayFilterGroup exception;
|
||||
private final StringFilterGroup videoQualityMenuFooter;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public PlayerFlyoutMenuItemsFilter() {
|
||||
exception = new ByteArrayFilterGroup(
|
||||
// Whitelist Quality menu item when "Hide Additional settings menu" is enabled
|
||||
|
||||
@@ -8,30 +8,30 @@ import android.widget.ListView;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.patches.components.VideoQualityMenuFilterPatch;
|
||||
import app.revanced.extension.youtube.patches.components.AdvancedVideoQualityMenuFilter;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
* This patch contains the logic to show the old video quality menu.
|
||||
* This patch contains the logic to always open the advanced video quality menu.
|
||||
* Two methods are required, because the quality menu is a RecyclerView in the new YouTube version
|
||||
* and a ListView in the old one.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class RestoreOldVideoQualityMenuPatch {
|
||||
public final class AdvancedVideoQualityMenuPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
|
||||
if (!Settings.RESTORE_OLD_VIDEO_QUALITY_MENU.get()) return;
|
||||
if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return;
|
||||
|
||||
recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
|
||||
try {
|
||||
// Check if the current view is the quality menu.
|
||||
if (!VideoQualityMenuFilterPatch.isVideoQualityMenuVisible || recyclerView.getChildCount() == 0) {
|
||||
if (!AdvancedVideoQualityMenuFilter.isVideoQualityMenuVisible || recyclerView.getChildCount() == 0) {
|
||||
return;
|
||||
}
|
||||
VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false;
|
||||
AdvancedVideoQualityMenuFilter.isVideoQualityMenuVisible = false;
|
||||
|
||||
ViewParent quickQualityViewParent = Utils.getParentView(recyclerView, 3);
|
||||
if (!(quickQualityViewParent instanceof ViewGroup)) {
|
||||
@@ -39,16 +39,15 @@ public final class RestoreOldVideoQualityMenuPatch {
|
||||
}
|
||||
|
||||
View firstChild = recyclerView.getChildAt(0);
|
||||
if (!(firstChild instanceof ViewGroup)) {
|
||||
if (!(firstChild instanceof ViewGroup firstChildGroup)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewGroup advancedQualityParentView = (ViewGroup) firstChild;
|
||||
if (advancedQualityParentView.getChildCount() < 4) {
|
||||
if (firstChildGroup.getChildCount() < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
View advancedQualityView = advancedQualityParentView.getChildAt(3);
|
||||
View advancedQualityView = firstChildGroup.getChildAt(3);
|
||||
if (advancedQualityView == null) {
|
||||
return;
|
||||
}
|
||||
@@ -71,7 +70,7 @@ public final class RestoreOldVideoQualityMenuPatch {
|
||||
* Used to force the creation of the advanced menu item for the Shorts quality flyout.
|
||||
*/
|
||||
public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) {
|
||||
return Settings.RESTORE_OLD_VIDEO_QUALITY_MENU.get() || original;
|
||||
return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,8 +78,8 @@ public final class RestoreOldVideoQualityMenuPatch {
|
||||
*
|
||||
* Used if spoofing to an old app version, and also used for the Shorts video quality flyout.
|
||||
*/
|
||||
public static void showOldVideoQualityMenu(final ListView listView) {
|
||||
if (!Settings.RESTORE_OLD_VIDEO_QUALITY_MENU.get()) return;
|
||||
public static void showAdvancedVideoQualityMenu(ListView listView) {
|
||||
if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return;
|
||||
|
||||
listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
|
||||
@Override
|
||||
@@ -12,15 +12,19 @@ import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
import app.revanced.extension.shared.settings.IntegerSetting;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class RememberVideoQualityPatch {
|
||||
private static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
|
||||
private static final IntegerSetting wifiQualitySetting = Settings.VIDEO_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting mobileQualitySetting = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
|
||||
private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
|
||||
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE;
|
||||
|
||||
private static boolean qualityNeedsUpdating;
|
||||
|
||||
@@ -41,17 +45,29 @@ public class RememberVideoQualityPatch {
|
||||
@Nullable
|
||||
private static List<Integer> videoQualities;
|
||||
|
||||
private static boolean shouldRememberVideoQuality() {
|
||||
BooleanSetting preference = ShortsPlayerState.isOpen() ?
|
||||
Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED
|
||||
: Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED;
|
||||
return preference.get();
|
||||
}
|
||||
|
||||
private static void changeDefaultQuality(int defaultQuality) {
|
||||
String networkTypeMessage;
|
||||
boolean useShortsPreference = ShortsPlayerState.isOpen();
|
||||
if (Utils.getNetworkType() == NetworkType.MOBILE) {
|
||||
mobileQualitySetting.save(defaultQuality);
|
||||
if (useShortsPreference) shortsQualityMobile.save(defaultQuality);
|
||||
else videoQualityMobile.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_mobile");
|
||||
} else {
|
||||
wifiQualitySetting.save(defaultQuality);
|
||||
if (useShortsPreference) shortsQualityWifi.save(defaultQuality);
|
||||
else videoQualityWifi.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_wifi");
|
||||
}
|
||||
Utils.showToastShort(
|
||||
str("revanced_remember_video_quality_toast", networkTypeMessage, (defaultQuality + "p")));
|
||||
Utils.showToastShort(str(
|
||||
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast",
|
||||
networkTypeMessage, (defaultQuality + "p")
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,9 +78,10 @@ public class RememberVideoQualityPatch {
|
||||
*/
|
||||
public static int setVideoQuality(Object[] qualities, final int originalQualityIndex, Object qInterface, String qIndexMethod) {
|
||||
try {
|
||||
boolean useShortsPreference = ShortsPlayerState.isOpen();
|
||||
final int preferredQuality = Utils.getNetworkType() == NetworkType.MOBILE
|
||||
? mobileQualitySetting.get()
|
||||
: wifiQualitySetting.get();
|
||||
? (useShortsPreference ? shortsQualityMobile : videoQualityMobile).get()
|
||||
: (useShortsPreference ? shortsQualityWifi : videoQualityWifi).get();
|
||||
|
||||
if (!userChangedDefaultQuality && preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) {
|
||||
return originalQualityIndex; // Nothing to do.
|
||||
@@ -141,17 +158,17 @@ public class RememberVideoQualityPatch {
|
||||
* Injection point. Old quality menu.
|
||||
*/
|
||||
public static void userChangedQuality(int selectedQualityIndex) {
|
||||
if (!Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.get()) return;
|
||||
|
||||
userSelectedQualityIndex = selectedQualityIndex;
|
||||
userChangedDefaultQuality = true;
|
||||
if (shouldRememberVideoQuality()) {
|
||||
userSelectedQualityIndex = selectedQualityIndex;
|
||||
userChangedDefaultQuality = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. New quality menu.
|
||||
*/
|
||||
public static void userChangedQualityInNewFlyout(int selectedQuality) {
|
||||
if (!Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.get()) return;
|
||||
if (!shouldRememberVideoQuality()) return;
|
||||
|
||||
changeDefaultQuality(selectedQuality); // Quality is human readable resolution (ie: 1080).
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ public final class SeekbarColorPatch {
|
||||
}
|
||||
|
||||
private static String loadRawResourceAsString(int resourceId) {
|
||||
//noinspection CharsetObjectCanBeUsed
|
||||
try (InputStream inputStream = Utils.getContext().getResources().openRawResource(resourceId);
|
||||
Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name()).useDelimiter("\\A")) {
|
||||
return scanner.next();
|
||||
@@ -281,6 +282,20 @@ public final class SeekbarColorPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* 19.49+
|
||||
*/
|
||||
public static int[] getPlayerLinearGradient(int[] original, int x0, int y1) {
|
||||
// This hook is used for both the player and the feed.
|
||||
// Feed usage always has x0 and y1 value of zero, and the player is always non zero.
|
||||
if (HIDE_SEEKBAR_THUMBNAIL_ENABLED && x0 == 0 && y1 == 0) {
|
||||
return HIDDEN_SEEKBAR_GRADIENT_COLORS;
|
||||
}
|
||||
return getPlayerLinearGradient(original);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Pre 19.49
|
||||
*/
|
||||
public static int[] getPlayerLinearGradient(int[] original) {
|
||||
return SEEKBAR_CUSTOM_COLOR_ENABLED
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.util.concurrent.*;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.ThemeHelper;
|
||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.RYDVoteData;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -87,9 +86,6 @@ public class ReturnYouTubeDislike {
|
||||
*/
|
||||
private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye'
|
||||
|
||||
private static final boolean IS_SPOOFING_TO_OLD_SEPARATOR_COLOR
|
||||
= SpoofAppVersionPatch.isSpoofingToLessThan("18.10.00");
|
||||
|
||||
/**
|
||||
* Cached lookup of all video ids.
|
||||
*/
|
||||
@@ -118,7 +114,7 @@ public class ReturnYouTubeDislike {
|
||||
private static final Rect middleSeparatorBounds;
|
||||
|
||||
/**
|
||||
* Left separator horizontal padding for Rolling Number layout.
|
||||
* Horizontal padding between the left and middle separator.
|
||||
*/
|
||||
public static final int leftSeparatorShapePaddingPixels;
|
||||
private static final ShapeDrawable leftSeparatorShape;
|
||||
@@ -133,7 +129,7 @@ public class ReturnYouTubeDislike {
|
||||
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp);
|
||||
middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize);
|
||||
|
||||
leftSeparatorShapePaddingPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10.0f, dp);
|
||||
leftSeparatorShapePaddingPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8.4f, dp);
|
||||
|
||||
leftSeparatorShape = new ShapeDrawable(new RectShape());
|
||||
leftSeparatorShape.setBounds(leftSeparatorBounds);
|
||||
@@ -184,17 +180,8 @@ public class ReturnYouTubeDislike {
|
||||
* Color of the left and middle separator, based on the color of the right separator.
|
||||
* It's unknown where YT gets the color from, and the values here are approximated by hand.
|
||||
* Ideally, this would be the actual color YT uses at runtime.
|
||||
*
|
||||
* Older versions before the 'Me' library tab use a slightly different color.
|
||||
* If spoofing was previously used and is now turned off,
|
||||
* or an old version was recently upgraded then the old colors are sometimes still used.
|
||||
*/
|
||||
private static int getSeparatorColor() {
|
||||
if (IS_SPOOFING_TO_OLD_SEPARATOR_COLOR) {
|
||||
return ThemeHelper.isDarkTheme()
|
||||
? 0x29AAAAAA // transparent dark gray
|
||||
: 0xFFD9D9D9; // light gray
|
||||
}
|
||||
return ThemeHelper.isDarkTheme()
|
||||
? 0x33FFFFFF
|
||||
: 0xFFD9D9D9;
|
||||
@@ -234,6 +221,12 @@ public class ReturnYouTubeDislike {
|
||||
// example video: https://www.youtube.com/watch?v=UnrU5vxCHxw
|
||||
// RYD data: https://returnyoutubedislikeapi.com/votes?videoId=UnrU5vxCHxw
|
||||
//
|
||||
if (!Settings.RYD_ESTIMATED_LIKE.get()) {
|
||||
// Change the "Likes" string to show that likes and dislikes are hidden.
|
||||
String hiddenMessageString = str("revanced_ryd_video_likes_hidden_by_video_owner");
|
||||
return newSpanUsingStylingOfAnotherSpan(oldSpannable, hiddenMessageString);
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Using estimated likes");
|
||||
oldLikes = formatDislikeCount(voteData.getLikeCount());
|
||||
}
|
||||
@@ -245,7 +238,7 @@ public class ReturnYouTubeDislike {
|
||||
String leftSeparatorString = getTextDirectionString();
|
||||
final Spannable leftSeparatorSpan;
|
||||
if (isRollingNumber) {
|
||||
leftSeparatorSpan = new SpannableString(leftSeparatorString);
|
||||
leftSeparatorSpan = new SpannableString(leftSeparatorString);
|
||||
} else {
|
||||
leftSeparatorString += " ";
|
||||
leftSeparatorSpan = new SpannableString(leftSeparatorString);
|
||||
@@ -346,56 +339,52 @@ public class ReturnYouTubeDislike {
|
||||
}
|
||||
|
||||
private static String formatDislikeCount(long dislikeCount) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
synchronized (ReturnYouTubeDislike.class) { // number formatter is not thread safe, must synchronize
|
||||
if (dislikeCountFormatter == null) {
|
||||
Locale locale = Objects.requireNonNull(Utils.getContext()).getResources().getConfiguration().locale;
|
||||
dislikeCountFormatter = CompactDecimalFormat.getInstance(locale, CompactDecimalFormat.CompactStyle.SHORT);
|
||||
synchronized (ReturnYouTubeDislike.class) { // Number formatter is not thread safe.
|
||||
if (dislikeCountFormatter == null) {
|
||||
// Must use default locale and not Utils context locale,
|
||||
// otherwise if using a different settings language then the
|
||||
// formatting will use that of the different language.
|
||||
Locale locale = Locale.getDefault();
|
||||
dislikeCountFormatter = CompactDecimalFormat.getInstance(locale, CompactDecimalFormat.CompactStyle.SHORT);
|
||||
|
||||
// YouTube disregards locale specific number characters
|
||||
// and instead shows english number characters everywhere.
|
||||
// To use the same behavior, override the digit characters to use English
|
||||
// so languages such as Arabic will show "1.234" instead of the native "۱,۲۳٤"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
symbols.setDigitStrings(DecimalFormatSymbols.getInstance(Locale.ENGLISH).getDigitStrings());
|
||||
dislikeCountFormatter.setDecimalFormatSymbols(symbols);
|
||||
}
|
||||
// YouTube disregards locale specific number characters
|
||||
// and instead shows English number characters everywhere.
|
||||
// To use the same behavior, override the digit characters to use English
|
||||
// so languages such as Arabic will show "1.234" instead of the native "۱,۲۳٤"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
symbols.setDigitStrings(DecimalFormatSymbols.getInstance(Locale.ENGLISH).getDigitStrings());
|
||||
dislikeCountFormatter.setDecimalFormatSymbols(symbols);
|
||||
}
|
||||
return dislikeCountFormatter.format(dislikeCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Will never be reached, as the oldest supported YouTube app requires Android N or greater.
|
||||
return String.valueOf(dislikeCount);
|
||||
return dislikeCountFormatter.format(dislikeCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDislikePercentage(float dislikePercentage) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
synchronized (ReturnYouTubeDislike.class) { // number formatter is not thread safe, must synchronize
|
||||
if (dislikePercentageFormatter == null) {
|
||||
Locale locale = Objects.requireNonNull(Utils.getContext()).getResources().getConfiguration().locale;
|
||||
dislikePercentageFormatter = NumberFormat.getPercentInstance(locale);
|
||||
synchronized (ReturnYouTubeDislike.class) { // Number formatter is not thread safe, must synchronize.
|
||||
if (dislikePercentageFormatter == null) {
|
||||
Locale locale = Locale.getDefault();
|
||||
dislikePercentageFormatter = NumberFormat.getPercentInstance(locale);
|
||||
|
||||
// Want to set the digit strings, and the simplest way is to cast to the implementation NumberFormat returns.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
|
||||
&& dislikePercentageFormatter instanceof DecimalFormat) {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
symbols.setDigitStrings(DecimalFormatSymbols.getInstance(Locale.ENGLISH).getDigitStrings());
|
||||
((DecimalFormat) dislikePercentageFormatter).setDecimalFormatSymbols(symbols);
|
||||
}
|
||||
// Want to set the digit strings, and the simplest way is to cast to the implementation NumberFormat returns.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
|
||||
&& dislikePercentageFormatter instanceof DecimalFormat decimalFormatter) {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
symbols.setDigitStrings(DecimalFormatSymbols.getInstance(Locale.ENGLISH).getDigitStrings());
|
||||
decimalFormatter.setDecimalFormatSymbols(symbols);
|
||||
}
|
||||
if (dislikePercentage >= 0.01) { // at least 1%
|
||||
dislikePercentageFormatter.setMaximumFractionDigits(0); // show only whole percentage points
|
||||
} else {
|
||||
dislikePercentageFormatter.setMaximumFractionDigits(1); // show up to 1 digit precision
|
||||
}
|
||||
return dislikePercentageFormatter.format(dislikePercentage);
|
||||
}
|
||||
}
|
||||
|
||||
// Will never be reached, as the oldest supported YouTube app requires Android N or greater.
|
||||
return String.valueOf((int) (dislikePercentage * 100));
|
||||
if (dislikePercentage >= 0.01) { // at least 1%
|
||||
dislikePercentageFormatter.setMaximumFractionDigits(0); // show only whole percentage points
|
||||
} else {
|
||||
dislikePercentageFormatter.setMaximumFractionDigits(1); // show up to 1 digit precision
|
||||
}
|
||||
|
||||
return dislikePercentageFormatter.format(dislikePercentage);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -403,15 +392,13 @@ public class ReturnYouTubeDislike {
|
||||
Objects.requireNonNull(videoId);
|
||||
synchronized (fetchCache) {
|
||||
// Remove any expired entries.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
final long now = System.currentTimeMillis();
|
||||
fetchCache.values().removeIf(value -> {
|
||||
final boolean expired = value.isExpired(now);
|
||||
if (expired)
|
||||
Logger.printDebug(() -> "Removing expired fetch: " + value.videoId);
|
||||
return expired;
|
||||
});
|
||||
}
|
||||
final long now = System.currentTimeMillis();
|
||||
fetchCache.values().removeIf(value -> {
|
||||
final boolean expired = value.isExpired(now);
|
||||
if (expired)
|
||||
Logger.printDebug(() -> "Removing expired fetch: " + value.videoId);
|
||||
return expired;
|
||||
});
|
||||
|
||||
ReturnYouTubeDislike fetch = fetchCache.get(videoId);
|
||||
if (fetch == null) {
|
||||
@@ -551,6 +538,15 @@ public class ReturnYouTubeDislike {
|
||||
}
|
||||
|
||||
if (spanIsForLikes) {
|
||||
if (!Utils.containsNumber(original)) {
|
||||
if (!Settings.RYD_ESTIMATED_LIKE.get()) {
|
||||
Logger.printDebug(() -> "Likes are hidden");
|
||||
return original;
|
||||
} else {
|
||||
Logger.printDebug(() -> "Using estimated likes");
|
||||
}
|
||||
}
|
||||
|
||||
// Scrolling Shorts does not cause the Spans to be reloaded,
|
||||
// so there is no need to cache the likes for this situations.
|
||||
Logger.printDebug(() -> "Creating likes span for: " + votingData.videoId);
|
||||
@@ -627,7 +623,7 @@ public class ReturnYouTubeDislike {
|
||||
userVote = vote;
|
||||
clearUICache();
|
||||
}
|
||||
|
||||
|
||||
if (future.isDone()) {
|
||||
// Update the fetched vote data.
|
||||
RYDVoteData voteData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH);
|
||||
|
||||
@@ -5,15 +5,12 @@ import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
@@ -22,6 +19,7 @@ import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.ThemeHelper;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
||||
import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.preference.ReturnYouTubeDislikePreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.preference.SponsorBlockPreferenceFragment;
|
||||
@@ -66,6 +64,10 @@ public class LicenseActivityHook {
|
||||
if (Settings.RESTORE_OLD_SETTINGS_MENUS.get()) {
|
||||
return false;
|
||||
}
|
||||
// Spoofing can cause half broken settings menus of old and new settings.
|
||||
if (SpoofAppVersionPatch.isSpoofingToLessThan("19.35.36")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// On the first launch of a clean install, forcing the cairo menu can give a
|
||||
// half broken appearance because all the preference icons may not be available yet.
|
||||
@@ -79,7 +81,6 @@ public class LicenseActivityHook {
|
||||
* <p>
|
||||
* Hooks LicenseActivity#onCreate in order to inject our own fragment.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public static void initialize(Activity licenseActivity) {
|
||||
try {
|
||||
ThemeHelper.setActivityTheme(licenseActivity);
|
||||
@@ -119,15 +120,13 @@ public class LicenseActivityHook {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private static void createToolbar(Activity activity, String toolbarTitleResourceName) {
|
||||
// Replace dummy placeholder toolbar.
|
||||
// This is required to fix submenu title alignment issue with Android ASOP 15+
|
||||
ViewGroup toolBarParent = activity.findViewById(
|
||||
getResourceIdentifier("revanced_toolbar_parent", "id"));
|
||||
ViewGroup dummyToolbar = toolBarParent.findViewById(getResourceIdentifier(
|
||||
"revanced_toolbar", "id"));
|
||||
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent,"revanced_toolbar");
|
||||
toolbarLayoutParams = dummyToolbar.getLayoutParams();
|
||||
toolBarParent.removeView(dummyToolbar);
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package app.revanced.extension.youtube.settings;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.extension.shared.settings.Setting.Availability;
|
||||
import static app.revanced.extension.shared.settings.Setting.migrateFromOldPreferences;
|
||||
import static app.revanced.extension.shared.settings.Setting.migrateOldSettingToNew;
|
||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||
import static app.revanced.extension.shared.settings.Setting.parentsAny;
|
||||
@@ -11,7 +10,6 @@ import static app.revanced.extension.youtube.patches.ChangeFormFactorPatch.FormF
|
||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
|
||||
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
|
||||
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideExpandCloseAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL;
|
||||
@@ -21,7 +19,7 @@ import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerT
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_4;
|
||||
import static app.revanced.extension.youtube.patches.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
|
||||
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
|
||||
import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_19_17_OR_GREATER;
|
||||
import static app.revanced.extension.youtube.patches.components.PlayerFlyoutMenuItemsFilter.HideAudioFlyoutMenuAvailability;
|
||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.IGNORE;
|
||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.MANUAL_SKIP;
|
||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
|
||||
@@ -38,20 +36,23 @@ import app.revanced.extension.shared.settings.IntegerSetting;
|
||||
import app.revanced.extension.shared.settings.LongSetting;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.StringSetting;
|
||||
import app.revanced.extension.shared.settings.preference.SharedPrefCategory;
|
||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrowAvailability;
|
||||
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.sponsorblock.SponsorBlockSettings;
|
||||
|
||||
public class Settings extends BaseSettings {
|
||||
// Video
|
||||
public static final BooleanSetting DISABLE_HDR_VIDEO = new BooleanSetting("revanced_disable_hdr_video", FALSE);
|
||||
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||
public static final IntegerSetting SHORTS_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_shorts_quality_default_wifi", -2, true);
|
||||
public static final IntegerSetting SHORTS_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_shorts_quality_default_mobile", -2, true);
|
||||
public static final BooleanSetting REMEMBER_SHORTS_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_shorts_quality_last_selected", FALSE);
|
||||
public static final BooleanSetting ADVANCED_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_advanced_video_quality_menu", TRUE);
|
||||
public static final BooleanSetting DISABLE_HDR_VIDEO = new BooleanSetting("revanced_disable_hdr_video", FALSE);
|
||||
// Speed
|
||||
public static final FloatSetting SPEED_TAP_AND_HOLD = new FloatSetting("revanced_speed_tap_and_hold", 2.0f, true);
|
||||
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE);
|
||||
@@ -124,9 +125,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE);
|
||||
public static final BooleanSetting COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_copy_video_url_timestamp", TRUE);
|
||||
public static final BooleanSetting DISABLE_FULLSCREEN_AMBIENT_MODE = new BooleanSetting("revanced_disable_fullscreen_ambient_mode", TRUE, true);
|
||||
public static final BooleanSetting DISABLE_LIKE_SUBSCRIBE_GLOW = new BooleanSetting("revanced_disable_like_subscribe_glow", FALSE);
|
||||
public static final BooleanSetting DISABLE_ROLLING_NUMBER_ANIMATIONS = new BooleanSetting("revanced_disable_rolling_number_animations", FALSE);
|
||||
public static final BooleanSetting DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE, true);
|
||||
public static final EnumSetting<FullscreenMode> EXIT_FULLSCREEN = new EnumSetting<>("revanced_exit_fullscreen", FullscreenMode.DISABLED);
|
||||
public static final BooleanSetting HIDE_AUTOPLAY_BUTTON = new BooleanSetting("revanced_hide_autoplay_button", TRUE, true);
|
||||
public static final BooleanSetting HIDE_CAPTIONS_BUTTON = new BooleanSetting("revanced_hide_captions_button", FALSE);
|
||||
@@ -136,8 +135,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_COMMUNITY_GUIDELINES = new BooleanSetting("revanced_hide_community_guidelines", TRUE);
|
||||
public static final BooleanSetting HIDE_EMERGENCY_BOX = new BooleanSetting("revanced_hide_emergency_box", TRUE);
|
||||
public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", FALSE);
|
||||
public static final BooleanSetting HIDE_END_SCREEN_SUGGESTED_VIDEO = new BooleanSetting("revanced_end_screen_suggested_video", FALSE, true);
|
||||
public static final BooleanSetting HIDE_HIDE_CHANNEL_GUIDELINES = new BooleanSetting("revanced_hide_channel_guidelines", TRUE);
|
||||
public static final BooleanSetting HIDE_HIDE_INFO_PANELS = new BooleanSetting("revanced_hide_info_panels", TRUE);
|
||||
public static final BooleanSetting HIDE_INFO_PANELS = new BooleanSetting("revanced_hide_info_panels", TRUE);
|
||||
public static final BooleanSetting HIDE_INFO_CARDS = new BooleanSetting("revanced_hide_info_cards", FALSE);
|
||||
public static final BooleanSetting HIDE_JOIN_MEMBERSHIP_BUTTON = new BooleanSetting("revanced_hide_join_membership_button", TRUE);
|
||||
public static final BooleanSetting HIDE_MEDICAL_PANELS = new BooleanSetting("revanced_hide_medical_panels", TRUE);
|
||||
@@ -157,7 +157,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, MINIPLAYER_ANY_MODERN);
|
||||
public static final BooleanSetting MINIPLAYER_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_drag_and_drop", TRUE, true, MINIPLAYER_ANY_MODERN);
|
||||
public static final BooleanSetting MINIPLAYER_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_horizontal_drag", FALSE, true, new MiniplayerHorizontalDragAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_EXPAND_CLOSE = new BooleanSetting("revanced_miniplayer_hide_expand_close", FALSE, true, new MiniplayerHideExpandCloseAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3));
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, MINIPLAYER_TYPE.availability(MODERN_1));
|
||||
public static final BooleanSetting MINIPLAYER_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_rounded_corners", TRUE, true, MINIPLAYER_ANY_MODERN);
|
||||
@@ -169,14 +169,16 @@ public class Settings extends BaseSettings {
|
||||
public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name",
|
||||
"org.schabi.newpipe" /* NewPipe */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON));
|
||||
// Comments
|
||||
public static final BooleanSetting HIDE_COMMENTS_CHAT_SUMMARY = new BooleanSetting("revanced_hide_comments_chat_summary", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_AI_CHAT_SUMMARY = new BooleanSetting("revanced_hide_comments_ai_chat_summary", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_AI_SUMMARY = new BooleanSetting("revanced_hide_comments_ai_summary", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_BY_MEMBERS_HEADER = new BooleanSetting("revanced_hide_comments_by_members_header", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_CREATE_A_SHORT_BUTTON = new BooleanSetting("revanced_hide_comments_create_a_short_button", TRUE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_TIMESTAMP_AND_EMOJI_BUTTONS = new BooleanSetting("revanced_hide_comments_timestamp_and_emoji_buttons", TRUE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_PREVIEW_COMMENT = new BooleanSetting("revanced_hide_comments_preview_comment", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_SECTION = new BooleanSetting("revanced_hide_comments_section", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_THANKS_BUTTON = new BooleanSetting("revanced_hide_comments_thanks_button", TRUE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_TIMESTAMP_AND_EMOJI_BUTTONS = new BooleanSetting("revanced_hide_comments_timestamp_and_emoji_buttons", TRUE);
|
||||
// Description
|
||||
public static final BooleanSetting HIDE_AI_GENERATED_VIDEO_SUMMARY_SECTION = new BooleanSetting("revanced_hide_ai_generated_video_summary_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_HOW_THIS_WAS_MADE_SECTION = new BooleanSetting("revanced_hide_how_this_was_made_section", FALSE);
|
||||
@@ -185,6 +187,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_PODCAST_SECTION = new BooleanSetting("revanced_hide_podcast_section", TRUE);
|
||||
public static final BooleanSetting HIDE_TRANSCRIPT_SECTION = new BooleanSetting("revanced_hide_transcript_section", TRUE);
|
||||
// Action buttons
|
||||
public static final BooleanSetting DISABLE_LIKE_SUBSCRIBE_GLOW = new BooleanSetting("revanced_disable_like_subscribe_glow", FALSE);
|
||||
public static final BooleanSetting HIDE_CLIP_BUTTON = new BooleanSetting("revanced_hide_clip_button", TRUE);
|
||||
public static final BooleanSetting HIDE_DOWNLOAD_BUTTON = new BooleanSetting("revanced_hide_download_button", FALSE);
|
||||
public static final BooleanSetting HIDE_LIKE_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_like_dislike_button", FALSE);
|
||||
@@ -196,7 +199,7 @@ public class Settings extends BaseSettings {
|
||||
// Player flyout menu items
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_ADDITIONAL_SETTINGS = new BooleanSetting("revanced_hide_player_flyout_additional_settings", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_AMBIENT_MODE = new BooleanSetting("revanced_hide_player_flyout_ambient_mode", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_AUDIO_TRACK = new BooleanSetting("revanced_hide_player_flyout_audio_track", FALSE);
|
||||
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_LOCK_SCREEN = new BooleanSetting("revanced_hide_player_flyout_lock_screen", FALSE);
|
||||
@@ -218,7 +221,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting SPOOF_APP_VERSION = new BooleanSetting("revanced_spoof_app_version", FALSE, true, "revanced_spoof_app_version_user_dialog_message");
|
||||
public static final BooleanSetting WIDE_SEARCHBAR = new BooleanSetting("revanced_wide_searchbar", FALSE, true);
|
||||
public static final EnumSetting<StartPage> CHANGE_START_PAGE = new EnumSetting<>("revanced_change_start_page", StartPage.DEFAULT, true);
|
||||
public static final StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", IS_19_17_OR_GREATER ? "19.26.42" : "17.33.42", true, parent(SPOOF_APP_VERSION));
|
||||
public static final StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", "19.01.34", true, parent(SPOOF_APP_VERSION));
|
||||
// Custom filter
|
||||
public static final BooleanSetting CUSTOM_FILTER = new BooleanSetting("revanced_custom_filter", FALSE);
|
||||
public static final StringSetting CUSTOM_FILTER_STRINGS = new StringSetting("revanced_custom_filter_strings", "", true, parent(CUSTOM_FILTER));
|
||||
@@ -228,8 +231,11 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_SHORTS_BUTTON = new BooleanSetting("revanced_hide_shorts_button", TRUE, true);
|
||||
public static final BooleanSetting HIDE_SUBSCRIPTIONS_BUTTON = new BooleanSetting("revanced_hide_subscriptions_button", FALSE, true);
|
||||
public static final BooleanSetting HIDE_NAVIGATION_BUTTON_LABELS = new BooleanSetting("revanced_hide_navigation_button_labels", FALSE, true);
|
||||
public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true);
|
||||
public static final BooleanSetting DISABLE_TRANSLUCENT_STATUS_BAR = new BooleanSetting("revanced_disable_translucent_status_bar", FALSE, true);
|
||||
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 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);
|
||||
public static final BooleanSetting DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK = new BooleanSetting("revanced_disable_translucent_navigation_bar_dark", FALSE, true);
|
||||
|
||||
@@ -282,7 +288,6 @@ public class Settings extends BaseSettings {
|
||||
"revanced_seekbar_thumbnails_high_quality_dialog_message", new SeekbarThumbnailsHighQualityAvailability());
|
||||
public static final BooleanSetting SLIDE_TO_SEEK = new BooleanSetting("revanced_slide_to_seek", FALSE, true);
|
||||
public static final BooleanSetting SEEKBAR_CUSTOM_COLOR = new BooleanSetting("revanced_seekbar_custom_color", FALSE, true);
|
||||
private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033");
|
||||
public static final StringSetting SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_primary", "#FF0033", true, parent(SEEKBAR_CUSTOM_COLOR));
|
||||
public static final StringSetting SEEKBAR_CUSTOM_COLOR_ACCENT = new StringSetting("revanced_seekbar_custom_color_accent", "#FF2791", true, parent(SEEKBAR_CUSTOM_COLOR));
|
||||
|
||||
@@ -306,20 +311,19 @@ public class Settings extends BaseSettings {
|
||||
|
||||
// Swipe controls
|
||||
public static final BooleanSetting SWIPE_CHANGE_VIDEO = new BooleanSetting("revanced_swipe_change_video", FALSE, true);
|
||||
public static final BooleanSetting SWIPE_BRIGHTNESS = new BooleanSetting("revanced_swipe_brightness", FALSE);
|
||||
public static final BooleanSetting SWIPE_VOLUME = new BooleanSetting("revanced_swipe_volume", FALSE);
|
||||
public static final BooleanSetting SWIPE_BRIGHTNESS = new BooleanSetting("revanced_swipe_brightness", FALSE, true);
|
||||
public static final BooleanSetting SWIPE_VOLUME = new BooleanSetting("revanced_swipe_volume", FALSE, true);
|
||||
public static final BooleanSetting SWIPE_PRESS_TO_ENGAGE = new BooleanSetting("revanced_swipe_press_to_engage", FALSE, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
public static final BooleanSetting SWIPE_HAPTIC_FEEDBACK = new BooleanSetting("revanced_swipe_haptic_feedback", TRUE, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
public static final IntegerSetting SWIPE_MAGNITUDE_THRESHOLD = new IntegerSetting("revanced_swipe_threshold", 30, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
public static final IntegerSetting SWIPE_OVERLAY_OPACITY = new IntegerSetting("revanced_swipe_overlay_background_opacity", 50, true,
|
||||
public static final BooleanSetting SWIPE_SHOW_CIRCULAR_OVERLAY = new BooleanSetting("revanced_swipe_show_circular_overlay", FALSE, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
private static final IntegerSetting DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127);
|
||||
|
||||
// Debugging
|
||||
public static final IntegerSetting SWIPE_OVERLAY_TEXT_SIZE = new IntegerSetting("revanced_swipe_text_overlay_size", 22, true,
|
||||
public static final BooleanSetting SWIPE_OVERLAY_MINIMAL_STYLE = new BooleanSetting("revanced_swipe_overlay_minimal_style", FALSE, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
public static final IntegerSetting SWIPE_OVERLAY_OPACITY = new IntegerSetting("revanced_swipe_overlay_background_opacity", 60, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
public static final LongSetting SWIPE_OVERLAY_TIMEOUT = new LongSetting("revanced_swipe_overlay_timeout", 500L, true,
|
||||
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
|
||||
@@ -333,6 +337,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting RYD_SHORTS = new BooleanSetting("ryd_shorts", TRUE, parent(RYD_ENABLED));
|
||||
public static final BooleanSetting RYD_DISLIKE_PERCENTAGE = new BooleanSetting("ryd_dislike_percentage", FALSE, parent(RYD_ENABLED));
|
||||
public static final BooleanSetting RYD_COMPACT_LAYOUT = new BooleanSetting("ryd_compact_layout", FALSE, parent(RYD_ENABLED));
|
||||
public static final BooleanSetting RYD_ESTIMATED_LIKE = new BooleanSetting("ryd_estimated_like", TRUE, parent(RYD_ENABLED));
|
||||
public static final BooleanSetting RYD_TOAST_ON_CONNECTION_ERROR = new BooleanSetting("ryd_toast_on_connection_error", TRUE, parent(RYD_ENABLED));
|
||||
|
||||
// SponsorBlock
|
||||
@@ -344,13 +349,14 @@ public class Settings extends BaseSettings {
|
||||
public static final IntegerSetting SB_CREATE_NEW_SEGMENT_STEP = new IntegerSetting("sb_create_new_segment_step", 150, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_VOTING_BUTTON = new BooleanSetting("sb_voting_button", FALSE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_CREATE_NEW_SEGMENT = new BooleanSetting("sb_create_new_segment", FALSE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_SQUARE_LAYOUT = new BooleanSetting("sb_square_layout", FALSE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_COMPACT_SKIP_BUTTON = new BooleanSetting("sb_compact_skip_button", FALSE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_AUTO_HIDE_SKIP_BUTTON = new BooleanSetting("sb_auto_hide_skip_button", TRUE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_TOAST_ON_SKIP = new BooleanSetting("sb_toast_on_skip", TRUE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_TOAST_ON_CONNECTION_ERROR = new BooleanSetting("sb_toast_on_connection_error", TRUE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_TRACK_SKIP_COUNT = new BooleanSetting("sb_track_skip_count", TRUE, parent(SB_ENABLED));
|
||||
public static final FloatSetting SB_SEGMENT_MIN_DURATION = new FloatSetting("sb_min_segment_duration", 0F, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_VIDEO_LENGTH_WITHOUT_SEGMENTS = new BooleanSetting("sb_video_length_without_segments", TRUE, parent(SB_ENABLED));
|
||||
public static final BooleanSetting SB_VIDEO_LENGTH_WITHOUT_SEGMENTS = new BooleanSetting("sb_video_length_without_segments", FALSE, parent(SB_ENABLED));
|
||||
public static final StringSetting SB_API_URL = new StringSetting("sb_api_url", "https://sponsor.ajay.app");
|
||||
public static final BooleanSetting SB_USER_IS_VIP = new BooleanSetting("sb_user_is_vip", FALSE);
|
||||
public static final IntegerSetting SB_LOCAL_TIME_SAVED_NUMBER_SEGMENTS = new IntegerSetting("sb_local_time_saved_number_segments", 0);
|
||||
@@ -360,52 +366,53 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting SB_SEEN_GUIDELINES = new BooleanSetting("sb_seen_guidelines", FALSE, false, false);
|
||||
public static final StringSetting SB_CATEGORY_SPONSOR = new StringSetting("sb_sponsor", SKIP_AUTOMATICALLY_ONCE.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_SPONSOR_COLOR = new StringSetting("sb_sponsor_color", "#00D400");
|
||||
public static final FloatSetting SB_CATEGORY_SPONSOR_OPACITY = new FloatSetting("sb_sponsor_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_SELF_PROMO = new StringSetting("sb_selfpromo", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_SELF_PROMO_COLOR = new StringSetting("sb_selfpromo_color", "#FFFF00");
|
||||
public static final FloatSetting SB_CATEGORY_SELF_PROMO_OPACITY = new FloatSetting("sb_selfpromo_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_INTERACTION = new StringSetting("sb_interaction", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_INTERACTION_COLOR = new StringSetting("sb_interaction_color", "#CC00FF");
|
||||
public static final FloatSetting SB_CATEGORY_INTERACTION_OPACITY = new FloatSetting("sb_interaction_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_HIGHLIGHT = new StringSetting("sb_highlight", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_HIGHLIGHT_COLOR = new StringSetting("sb_highlight_color", "#FF1684");
|
||||
public static final FloatSetting SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_INTRO = new StringSetting("sb_intro", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_INTRO_COLOR = new StringSetting("sb_intro_color", "#00FFFF");
|
||||
public static final FloatSetting SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_OUTRO = new StringSetting("sb_outro", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_OUTRO_COLOR = new StringSetting("sb_outro_color", "#0202ED");
|
||||
public static final FloatSetting SB_CATEGORY_OUTRO_OPACITY = new FloatSetting("sb_outro_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_PREVIEW = new StringSetting("sb_preview", IGNORE.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_PREVIEW_COLOR = new StringSetting("sb_preview_color", "#008FD6");
|
||||
public static final FloatSetting SB_CATEGORY_PREVIEW_OPACITY = new FloatSetting("sb_preview_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_FILLER = new StringSetting("sb_filler", IGNORE.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_FILLER_COLOR = new StringSetting("sb_filler_color", "#7300FF");
|
||||
public static final FloatSetting SB_CATEGORY_FILLER_OPACITY = new FloatSetting("sb_filler_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_MUSIC_OFFTOPIC = new StringSetting("sb_music_offtopic", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_MUSIC_OFFTOPIC_COLOR = new StringSetting("sb_music_offtopic_color", "#FF9900");
|
||||
public static final FloatSetting SB_CATEGORY_MUSIC_OFFTOPIC_OPACITY = new FloatSetting("sb_music_offtopic_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_UNSUBMITTED = new StringSetting("sb_unsubmitted", SKIP_AUTOMATICALLY.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_UNSUBMITTED_COLOR = new StringSetting("sb_unsubmitted_color", "#FFFFFF");
|
||||
public static final FloatSetting SB_CATEGORY_UNSUBMITTED_OPACITY = new FloatSetting("sb_unsubmitted_opacity", 1.0f);
|
||||
|
||||
// Deprecated migrations
|
||||
public static final StringSetting DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING = new StringSetting("uuid", ""); // Delete sometime in 2024
|
||||
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE, true);
|
||||
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE);
|
||||
private static final IntegerSetting DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127);
|
||||
private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033");
|
||||
private static final BooleanSetting DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE);
|
||||
private static final BooleanSetting DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
|
||||
static {
|
||||
// region Migration
|
||||
|
||||
// Do _not_ delete this SB private user id migration property until sometime in early 2025.
|
||||
// This is the only setting that cannot be reconfigured if lost,
|
||||
// and more time should be given for users who rarely upgrade.
|
||||
SharedPrefCategory sbPrefs = new SharedPrefCategory("sponsor-block");
|
||||
// Remove the "sb_" prefix, as old settings are saved without it.
|
||||
String key = DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING.key.substring(3);
|
||||
migrateFromOldPreferences(sbPrefs, DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, key);
|
||||
|
||||
migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID);
|
||||
|
||||
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_BUTTONS, HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS);
|
||||
|
||||
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER, HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER);
|
||||
|
||||
// Old spoof versions that no longer work reliably.
|
||||
if (SPOOF_APP_VERSION_TARGET.get().compareTo(SPOOF_APP_VERSION_TARGET.defaultValue) < 0) {
|
||||
Logger.printInfo(() -> "Resetting spoof app version target");
|
||||
SPOOF_APP_VERSION_TARGET.resetToDefault();
|
||||
}
|
||||
migrateOldSettingToNew(DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN, HIDE_END_SCREEN_SUGGESTED_VIDEO);
|
||||
|
||||
migrateOldSettingToNew(DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU, ADVANCED_VIDEO_QUALITY_MENU);
|
||||
|
||||
// Migrate renamed enum.
|
||||
//noinspection deprecation
|
||||
@@ -442,6 +449,12 @@ public class Settings extends BaseSettings {
|
||||
DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA.resetToDefault();
|
||||
}
|
||||
|
||||
// Old spoof versions that no longer work.
|
||||
if (SPOOF_APP_VERSION_TARGET.get().compareTo(SPOOF_APP_VERSION_TARGET.defaultValue) < 0) {
|
||||
Logger.printInfo(() -> "Resetting spoof app version target");
|
||||
SPOOF_APP_VERSION_TARGET.resetToDefault();
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region SB import/export callbacks
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class HideAudioFlyoutMenuPreference extends SwitchPreference {
|
||||
|
||||
{
|
||||
// Audio menu is not available if spoofing to Android client type.
|
||||
if (!SpoofVideoStreamsPatch.notSpoofingToAndroid()) {
|
||||
String summary = str("revanced_hide_player_flyout_audio_track_not_available");
|
||||
setSummary(summary);
|
||||
setSummaryOn(summary);
|
||||
setSummaryOff(summary);
|
||||
}
|
||||
}
|
||||
|
||||
public HideAudioFlyoutMenuPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
public HideAudioFlyoutMenuPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
public HideAudioFlyoutMenuPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
public HideAudioFlyoutMenuPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,14 @@ package app.revanced.extension.youtube.settings.preference;
|
||||
import static android.text.Html.FROM_HTML_MODE_COMPACT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.preference.Preference;
|
||||
import android.text.Html;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
/**
|
||||
* Allows using basic html for the summary text.
|
||||
*/
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class HtmlPreference extends Preference {
|
||||
{
|
||||
setSummary(Html.fromHtml(getSummary().toString(), FROM_HTML_MODE_COMPACT));
|
||||
|
||||
@@ -17,10 +17,7 @@ import android.view.WindowInsets;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
@@ -76,7 +73,8 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(pairsToSort, (pair1, pair2) -> pair1.first.compareToIgnoreCase(pair2.first));
|
||||
pairsToSort.sort((pair1, pair2)
|
||||
-> pair1.first.compareToIgnoreCase(pair2.first));
|
||||
|
||||
CharSequence[] sortedEntries = new CharSequence[entrySize];
|
||||
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
|
||||
@@ -98,7 +96,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
listPreference.setEntryValues(sortedEntryValues);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
@@ -112,6 +109,7 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
CustomPlaybackSpeedPatch.initializeListPreference(playbackPreference);
|
||||
}
|
||||
|
||||
sortPreferenceListMenu(Settings.CHANGE_START_PAGE);
|
||||
sortPreferenceListMenu(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE);
|
||||
sortPreferenceListMenu(BaseSettings.REVANCED_LANGUAGE);
|
||||
} catch (Exception ex) {
|
||||
@@ -140,11 +138,13 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
.findViewById(android.R.id.content)
|
||||
.getParent();
|
||||
|
||||
// Fix required for Android 15 and YT 19.45+
|
||||
// Fix edge-to-edge screen with Android 15 and YT 19.45+
|
||||
// https://developer.android.com/develop/ui/views/layout/edge-to-edge#system-bars-insets
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
|
||||
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
|
||||
v.setPadding(0, statusInsets.top, 0, 0);
|
||||
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
|
||||
v.setPadding(0, statusInsets.top, 0, navInsets.bottom);
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
@@ -153,13 +153,10 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
toolbar.setTitle(childScreen.getTitle());
|
||||
toolbar.setNavigationIcon(getBackButtonDrawable());
|
||||
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
final int margin = (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()
|
||||
);
|
||||
toolbar.setTitleMargin(margin, 0, margin, 0);
|
||||
}
|
||||
final int margin = (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()
|
||||
);
|
||||
toolbar.setTitleMargin(margin, 0, margin, 0);
|
||||
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar,
|
||||
true, TextView.class::isInstance);
|
||||
|
||||
@@ -14,6 +14,7 @@ import android.preference.PreferenceScreen;
|
||||
import android.preference.SwitchPreference;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.patches.ReturnYouTubeDislikePatch;
|
||||
@@ -39,6 +40,11 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
|
||||
*/
|
||||
private SwitchPreference compactLayoutPreference;
|
||||
|
||||
/**
|
||||
* If hidden likes are replaced with an estimated value.
|
||||
*/
|
||||
private SwitchPreference estimatedLikesPreference;
|
||||
|
||||
/**
|
||||
* If segmented like/dislike button uses smaller compact layout.
|
||||
*/
|
||||
@@ -48,6 +54,7 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
|
||||
shortsPreference.setEnabled(Settings.RYD_SHORTS.isAvailable());
|
||||
percentagePreference.setEnabled(Settings.RYD_DISLIKE_PERCENTAGE.isAvailable());
|
||||
compactLayoutPreference.setEnabled(Settings.RYD_COMPACT_LAYOUT.isAvailable());
|
||||
estimatedLikesPreference.setEnabled(Settings.RYD_ESTIMATED_LIKE.isAvailable());
|
||||
toastOnRYDNotAvailable.setEnabled(Settings.RYD_TOAST_ON_CONNECTION_ERROR.isAvailable());
|
||||
}
|
||||
|
||||
@@ -79,9 +86,7 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
|
||||
shortsPreference = new SwitchPreference(context);
|
||||
shortsPreference.setChecked(Settings.RYD_SHORTS.get());
|
||||
shortsPreference.setTitle(str("revanced_ryd_shorts_title"));
|
||||
String shortsSummary = ReturnYouTubeDislikePatch.IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER
|
||||
? str("revanced_ryd_shorts_summary_on")
|
||||
: str("revanced_ryd_shorts_summary_on_disclaimer");
|
||||
String shortsSummary = str("revanced_ryd_shorts_summary_on_disclaimer");
|
||||
shortsPreference.setSummaryOn(shortsSummary);
|
||||
shortsPreference.setSummaryOff(str("revanced_ryd_shorts_summary_off"));
|
||||
shortsPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
@@ -117,6 +122,19 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
|
||||
});
|
||||
preferenceScreen.addPreference(compactLayoutPreference);
|
||||
|
||||
estimatedLikesPreference = new SwitchPreference(context);
|
||||
estimatedLikesPreference.setChecked(Settings.RYD_ESTIMATED_LIKE.get());
|
||||
estimatedLikesPreference.setTitle(str("revanced_ryd_estimated_like_title"));
|
||||
estimatedLikesPreference.setSummaryOn(str("revanced_ryd_estimated_like_summary_on"));
|
||||
estimatedLikesPreference.setSummaryOff(str("revanced_ryd_estimated_like_summary_off"));
|
||||
estimatedLikesPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
Settings.RYD_ESTIMATED_LIKE.save((Boolean) newValue);
|
||||
ReturnYouTubeDislike.clearAllUICaches();
|
||||
updateUIState();
|
||||
return true;
|
||||
});
|
||||
preferenceScreen.addPreference(estimatedLikesPreference);
|
||||
|
||||
toastOnRYDNotAvailable = new SwitchPreference(context);
|
||||
toastOnRYDNotAvailable.setChecked(Settings.RYD_TOAST_ON_CONNECTION_ERROR.get());
|
||||
toastOnRYDNotAvailable.setTitle(str("revanced_ryd_toast_on_connection_error_title"));
|
||||
@@ -218,6 +236,8 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
|
||||
"revanced_ryd_statistics_getNumberOfRateLimitRequestsEncountered_non_zero_summary"));
|
||||
preferenceScreen.addPreference(statisticPreference);
|
||||
}
|
||||
|
||||
Utils.setPreferenceTitlesToMultiLineIfNeeded(preferenceScreen);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "onCreate failure", ex);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.*;
|
||||
import android.text.Html;
|
||||
@@ -18,6 +17,7 @@ import androidx.annotation.Nullable;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.preference.ResettableEditTextPreference;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
|
||||
@@ -37,15 +37,16 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
private SwitchPreference sbEnabled;
|
||||
private SwitchPreference addNewSegment;
|
||||
private SwitchPreference votingEnabled;
|
||||
private SwitchPreference compactSkipButton;
|
||||
private SwitchPreference autoHideSkipSegmentButton;
|
||||
private SwitchPreference compactSkipButton;
|
||||
private SwitchPreference squareLayout;
|
||||
private SwitchPreference showSkipToast;
|
||||
private SwitchPreference trackSkips;
|
||||
private SwitchPreference showTimeWithoutSegments;
|
||||
private SwitchPreference toastOnConnectionError;
|
||||
|
||||
private EditTextPreference newSegmentStep;
|
||||
private EditTextPreference minSegmentDuration;
|
||||
private ResettableEditTextPreference newSegmentStep;
|
||||
private ResettableEditTextPreference minSegmentDuration;
|
||||
private EditTextPreference privateUserId;
|
||||
private EditTextPreference importExport;
|
||||
private Preference apiUrl;
|
||||
@@ -62,7 +63,9 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
} else if (!Settings.SB_CREATE_NEW_SEGMENT.get()) {
|
||||
SponsorBlockViewController.hideNewSegmentLayout();
|
||||
}
|
||||
// Voting and add new segment buttons automatically shows/hide themselves.
|
||||
// Voting and add new segment buttons automatically show/hide themselves.
|
||||
|
||||
SponsorBlockViewController.updateLayout();
|
||||
|
||||
sbEnabled.setChecked(enabled);
|
||||
|
||||
@@ -72,11 +75,14 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
votingEnabled.setChecked(Settings.SB_VOTING_BUTTON.get());
|
||||
votingEnabled.setEnabled(enabled);
|
||||
|
||||
autoHideSkipSegmentButton.setEnabled(enabled);
|
||||
autoHideSkipSegmentButton.setChecked(Settings.SB_AUTO_HIDE_SKIP_BUTTON.get());
|
||||
|
||||
compactSkipButton.setChecked(Settings.SB_COMPACT_SKIP_BUTTON.get());
|
||||
compactSkipButton.setEnabled(enabled);
|
||||
|
||||
autoHideSkipSegmentButton.setChecked(Settings.SB_AUTO_HIDE_SKIP_BUTTON.get());
|
||||
autoHideSkipSegmentButton.setEnabled(enabled);
|
||||
squareLayout.setChecked(Settings.SB_SQUARE_LAYOUT.get());
|
||||
squareLayout.setEnabled(enabled);
|
||||
|
||||
showSkipToast.setChecked(Settings.SB_TOAST_ON_SKIP.get());
|
||||
showSkipToast.setEnabled(enabled);
|
||||
@@ -154,6 +160,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
addAboutCategory(context, preferenceScreen);
|
||||
|
||||
Utils.setPreferenceTitlesToMultiLineIfNeeded(preferenceScreen);
|
||||
|
||||
updateUI();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "onCreate failure", ex);
|
||||
@@ -176,6 +184,17 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
return true;
|
||||
});
|
||||
|
||||
autoHideSkipSegmentButton = new SwitchPreference(context);
|
||||
autoHideSkipSegmentButton.setTitle(str("revanced_sb_enable_auto_hide_skip_segment_button"));
|
||||
autoHideSkipSegmentButton.setSummaryOn(str("revanced_sb_enable_auto_hide_skip_segment_button_sum_on"));
|
||||
autoHideSkipSegmentButton.setSummaryOff(str("revanced_sb_enable_auto_hide_skip_segment_button_sum_off"));
|
||||
category.addPreference(autoHideSkipSegmentButton);
|
||||
autoHideSkipSegmentButton.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||
Settings.SB_AUTO_HIDE_SKIP_BUTTON.save((Boolean) newValue);
|
||||
updateUI();
|
||||
return true;
|
||||
});
|
||||
|
||||
compactSkipButton = new SwitchPreference(context);
|
||||
compactSkipButton.setTitle(str("revanced_sb_enable_compact_skip_button"));
|
||||
compactSkipButton.setSummaryOn(str("revanced_sb_enable_compact_skip_button_sum_on"));
|
||||
@@ -187,13 +206,13 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
return true;
|
||||
});
|
||||
|
||||
autoHideSkipSegmentButton = new SwitchPreference(context);
|
||||
autoHideSkipSegmentButton.setTitle(str("revanced_sb_enable_auto_hide_skip_segment_button"));
|
||||
autoHideSkipSegmentButton.setSummaryOn(str("revanced_sb_enable_auto_hide_skip_segment_button_sum_on"));
|
||||
autoHideSkipSegmentButton.setSummaryOff(str("revanced_sb_enable_auto_hide_skip_segment_button_sum_off"));
|
||||
category.addPreference(autoHideSkipSegmentButton);
|
||||
autoHideSkipSegmentButton.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||
Settings.SB_AUTO_HIDE_SKIP_BUTTON.save((Boolean) newValue);
|
||||
squareLayout = new SwitchPreference(context);
|
||||
squareLayout.setTitle(str("revanced_sb_square_layout"));
|
||||
squareLayout.setSummaryOn(str("revanced_sb_square_layout_sum_on"));
|
||||
squareLayout.setSummaryOff(str("revanced_sb_square_layout_sum_off"));
|
||||
category.addPreference(squareLayout);
|
||||
squareLayout.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||
Settings.SB_SQUARE_LAYOUT.save((Boolean) newValue);
|
||||
updateUI();
|
||||
return true;
|
||||
});
|
||||
@@ -252,7 +271,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
return true;
|
||||
});
|
||||
|
||||
newSegmentStep = new EditTextPreference(context);
|
||||
newSegmentStep = new ResettableEditTextPreference(context);
|
||||
newSegmentStep.setSetting(Settings.SB_CREATE_NEW_SEGMENT_STEP);
|
||||
newSegmentStep.setTitle(str("revanced_sb_general_adjusting"));
|
||||
newSegmentStep.setSummary(str("revanced_sb_general_adjusting_sum"));
|
||||
newSegmentStep.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
@@ -310,7 +330,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
});
|
||||
category.addPreference(trackSkips);
|
||||
|
||||
minSegmentDuration = new EditTextPreference(context);
|
||||
minSegmentDuration = new ResettableEditTextPreference(context);
|
||||
minSegmentDuration.setSetting(Settings.SB_SEGMENT_MIN_DURATION);
|
||||
minSegmentDuration.setTitle(str("revanced_sb_general_min_duration"));
|
||||
minSegmentDuration.setSummary(str("revanced_sb_general_min_duration_sum"));
|
||||
minSegmentDuration.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||
@@ -329,7 +350,15 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
});
|
||||
category.addPreference(minSegmentDuration);
|
||||
|
||||
privateUserId = new EditTextPreference(context);
|
||||
privateUserId = new EditTextPreference(context) {
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||
Utils.setEditTextDialogTheme(builder);
|
||||
|
||||
builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> {
|
||||
Utils.setClipboard(getEditText().getText().toString());
|
||||
});
|
||||
}
|
||||
};
|
||||
privateUserId.setTitle(str("revanced_sb_general_uuid"));
|
||||
privateUserId.setSummary(str("revanced_sb_general_uuid_sum"));
|
||||
privateUserId.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||
@@ -393,9 +422,7 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
importExport.getEditText().setInputType(InputType.TYPE_CLASS_TEXT
|
||||
| InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
||||
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
importExport.getEditText().setAutofillHints((String) null);
|
||||
}
|
||||
importExport.getEditText().setAutofillHints((String) null);
|
||||
importExport.getEditText().setTextSize(TypedValue.COMPLEX_UNIT_PT, 8);
|
||||
importExport.setOnPreferenceClickListener(preference1 -> {
|
||||
importExport.getEditText().setText(SponsorBlockSettings.exportDesktopSettings());
|
||||
@@ -490,7 +517,7 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
if (stats.totalSegmentCountIncludingIgnored > 0) {
|
||||
// If user has not created any segments, there's no reason to set a username.
|
||||
EditTextPreference preference = new EditTextPreference(context);
|
||||
EditTextPreference preference = new ResettableEditTextPreference(context);
|
||||
statsCategory.addPreference(preference);
|
||||
String userName = stats.userName;
|
||||
preference.setTitle(fromHtml(str("revanced_sb_stats_username", userName)));
|
||||
|
||||
@@ -73,6 +73,7 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
if (currentClientType == clientType) {
|
||||
return;
|
||||
}
|
||||
currentClientType = clientType;
|
||||
|
||||
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
||||
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
||||
@@ -85,7 +86,7 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
String summary = str(key + "_summary");
|
||||
|
||||
// Android VR supports AV1 but all other clients do not.
|
||||
if (clientType != ClientType.ANDROID_VR && clientType != ClientType.ANDROID_VR_NO_AUTH) {
|
||||
if (clientType != ClientType.ANDROID_VR_AUTH && clientType != ClientType.ANDROID_VR_NO_AUTH) {
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ package app.revanced.extension.youtube.shared;
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton.CREATE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
@@ -26,12 +26,22 @@ import app.revanced.extension.youtube.settings.Settings;
|
||||
@SuppressWarnings("unused")
|
||||
public final class NavigationBar {
|
||||
|
||||
/**
|
||||
* Interface to call obfuscated methods in AppCompat Toolbar class.
|
||||
*/
|
||||
public interface AppCompatToolbarPatchInterface {
|
||||
Drawable patch_getNavigationIcon();
|
||||
}
|
||||
|
||||
//
|
||||
// Search bar
|
||||
// Search and toolbar.
|
||||
//
|
||||
|
||||
private static volatile WeakReference<View> searchBarResultsRef = new WeakReference<>(null);
|
||||
|
||||
private static volatile WeakReference<AppCompatToolbarPatchInterface> toolbarResultsRef
|
||||
= new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@@ -39,6 +49,22 @@ public final class NavigationBar {
|
||||
searchBarResultsRef = new WeakReference<>(searchbarResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setToolbar(FrameLayout layout) {
|
||||
AppCompatToolbarPatchInterface toolbar = Utils.getChildView(layout, false, (view) ->
|
||||
view instanceof AppCompatToolbarPatchInterface
|
||||
);
|
||||
|
||||
if (toolbar == null) {
|
||||
Logger.printException(() -> "Could not find navigation toolbar");
|
||||
return;
|
||||
}
|
||||
|
||||
toolbarResultsRef = new WeakReference<>(toolbar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the search bar is on screen. This includes if the player
|
||||
* is on screen and the search results are behind the player (and not visible).
|
||||
@@ -49,8 +75,13 @@ public final class NavigationBar {
|
||||
return searchbarResults != null && searchbarResults.getParent() != null;
|
||||
}
|
||||
|
||||
public static boolean isBackButtonVisible() {
|
||||
AppCompatToolbarPatchInterface toolbar = toolbarResultsRef.get();
|
||||
return toolbar != null && toolbar.patch_getNavigationIcon() != null;
|
||||
}
|
||||
|
||||
//
|
||||
// Navigation bar buttons
|
||||
// Navigation bar buttons.
|
||||
//
|
||||
|
||||
/**
|
||||
@@ -257,7 +288,6 @@ public final class NavigationBar {
|
||||
* Injection point.
|
||||
* Fixes missing drawable.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static void setCairoNotificationFilledIcon(EnumMap enumMap, Enum tabActivityCairo) {
|
||||
if (fillBellCairoBlack != 0) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.extension.youtube.Event
|
||||
import app.revanced.extension.youtube.patches.VideoInformation
|
||||
|
||||
/**
|
||||
* Main player type.
|
||||
* Regular player type.
|
||||
*/
|
||||
enum class PlayerType {
|
||||
/**
|
||||
@@ -21,9 +21,6 @@ enum class PlayerType {
|
||||
|
||||
/**
|
||||
* A regular video is minimized.
|
||||
*
|
||||
* When spoofing to 16.x YouTube and watching a short with a regular video in the background,
|
||||
* the type can be this (and not [HIDDEN]).
|
||||
*/
|
||||
WATCH_WHILE_MINIMIZED,
|
||||
WATCH_WHILE_MAXIMIZED,
|
||||
@@ -56,8 +53,7 @@ enum class PlayerType {
|
||||
val newType = nameToPlayerType[enumName]
|
||||
if (newType == null) {
|
||||
Logger.printException { "Unknown PlayerType encountered: $enumName" }
|
||||
} else if (current != newType) {
|
||||
Logger.printDebug { "PlayerType changed to: $newType" }
|
||||
} else {
|
||||
current = newType
|
||||
}
|
||||
}
|
||||
@@ -68,9 +64,13 @@ enum class PlayerType {
|
||||
@JvmStatic
|
||||
var current
|
||||
get() = currentPlayerType
|
||||
private set(value) {
|
||||
currentPlayerType = value
|
||||
onChange(currentPlayerType)
|
||||
private set(type) {
|
||||
if (currentPlayerType != type) {
|
||||
Logger.printDebug { "Changed to: $type" }
|
||||
|
||||
currentPlayerType = type
|
||||
onChange(type)
|
||||
}
|
||||
}
|
||||
|
||||
@Volatile // Read/write from different threads.
|
||||
@@ -90,8 +90,6 @@ enum class PlayerType {
|
||||
* Does not include the first moment after a short is opened when a regular video is minimized on screen,
|
||||
* or while watching a short with a regular video present on a spoofed 16.x version of YouTube.
|
||||
* To include those situations instead use [isNoneHiddenOrMinimized].
|
||||
*
|
||||
* @see VideoInformation
|
||||
*/
|
||||
fun isNoneOrHidden(): Boolean {
|
||||
return this == NONE || this == HIDDEN
|
||||
@@ -107,8 +105,11 @@ enum class PlayerType {
|
||||
* when spoofing to an old version this will return false even
|
||||
* though a Short is being opened or is on screen (see [isNoneHiddenOrMinimized]).
|
||||
*
|
||||
* Instead of this method, consider using {@link ShortsPlayerState}
|
||||
* which may work better for some situations.
|
||||
*
|
||||
* @return If nothing, a Short, or a regular video is sliding off screen to a dismissed or hidden state.
|
||||
* @see VideoInformation
|
||||
* @see ShortsPlayerState
|
||||
*/
|
||||
fun isNoneHiddenOrSlidingMinimized(): Boolean {
|
||||
return isNoneOrHidden() || this == WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED
|
||||
@@ -125,9 +126,12 @@ enum class PlayerType {
|
||||
* Typically used to detect if a Short is playing when the player cannot be in a minimized state,
|
||||
* such as the user interacting with a button or element of the player.
|
||||
*
|
||||
* Instead of this method, consider using {@link ShortsPlayerState}
|
||||
* which may work better for some situations.
|
||||
*
|
||||
* @return If nothing, a Short, a regular video is sliding off screen to a dismissed or hidden state,
|
||||
* a regular video is minimized (and a new video is not being opened).
|
||||
* @see VideoInformation
|
||||
* @see ShortsPlayerState
|
||||
*/
|
||||
fun isNoneHiddenOrMinimized(): Boolean {
|
||||
return isNoneHiddenOrSlidingMinimized() || this == WATCH_WHILE_MINIMIZED
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user