mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 09:53:55 +01:00
Compare commits
100 Commits
v5.7.0-dev
...
v5.10.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
654b339f66 | ||
|
|
64cdce28a6 | ||
|
|
d01b9a67c5 | ||
|
|
a72404eeab | ||
|
|
3ff104528e | ||
|
|
76bbd7ed2f | ||
|
|
2fdf0f85c1 | ||
|
|
1d12c4156d | ||
|
|
c43050dce8 | ||
|
|
8104bbd7d7 | ||
|
|
8487888e6b | ||
|
|
6721a284cd | ||
|
|
6cde702854 | ||
|
|
7c8efcaf41 | ||
|
|
350ee02e3b | ||
|
|
df2d070a43 | ||
|
|
8167aaccc8 | ||
|
|
f4989ed0a5 | ||
|
|
8f5a0531bc | ||
|
|
622554de14 | ||
|
|
66e330ffe6 | ||
|
|
2afcd3d63d | ||
|
|
80d7c78cf6 | ||
|
|
d85bcc3c16 | ||
|
|
21368ea696 | ||
|
|
e687d3ed37 | ||
|
|
064b859d39 | ||
|
|
89882ddaf8 | ||
|
|
41881ba161 | ||
|
|
0615990138 | ||
|
|
70532313db | ||
|
|
e5e897de77 | ||
|
|
1e57ce9658 | ||
|
|
fcad0ab5bb | ||
|
|
91471eccf9 | ||
|
|
d559f016c6 | ||
|
|
5a82d26f03 | ||
|
|
e2eae499d9 | ||
|
|
64919d6443 | ||
|
|
c6ffaf86ae | ||
|
|
3ee99b7bf1 | ||
|
|
6f9bf4873f | ||
|
|
29a73089a3 | ||
|
|
74ef1841eb | ||
|
|
0c544d28e3 | ||
|
|
b1e5b99b44 | ||
|
|
7b90baadb5 | ||
|
|
4a6f3c8555 | ||
|
|
e7c6943ca7 | ||
|
|
ae1b987c0d | ||
|
|
9496438da1 | ||
|
|
fa51631ea6 | ||
|
|
8bf7108001 | ||
|
|
030eece04a | ||
|
|
30009b723d | ||
|
|
53b25ea7e9 | ||
|
|
189e1c90c4 | ||
|
|
f01603b3f3 | ||
|
|
3db5651e5c | ||
|
|
f3c4d6fd64 | ||
|
|
29dbc9ffbf | ||
|
|
fa4aa54f0c | ||
|
|
1d89ada07f | ||
|
|
8c529abad5 | ||
|
|
4ade7c7329 | ||
|
|
f35247a872 | ||
|
|
4de768febf | ||
|
|
1a5c86db93 | ||
|
|
dbba795468 | ||
|
|
0a9320551d | ||
|
|
9fac1614e7 | ||
|
|
2de3523c59 | ||
|
|
ad1e40b130 | ||
|
|
094a6aa6de | ||
|
|
a14e03e4bb | ||
|
|
6f40b6d30f | ||
|
|
1711e1c39d | ||
|
|
25372828d1 | ||
|
|
f58245c6cd | ||
|
|
87e1c7f4c8 | ||
|
|
55d01c92d1 | ||
|
|
ca21a69550 | ||
|
|
634d0b4058 | ||
|
|
47ea8d5ec8 | ||
|
|
9509ed53f3 | ||
|
|
39542ddf55 | ||
|
|
e1741130af | ||
|
|
e54eb3ce87 | ||
|
|
0ae756b0fc | ||
|
|
77a0ac5c9c | ||
|
|
899121b9de | ||
|
|
838edb48e7 | ||
|
|
b2665c916a | ||
|
|
4b81f7009b | ||
|
|
1a4c39a2ee | ||
|
|
99334d1e53 | ||
|
|
2850a6ed4e | ||
|
|
f28eb5105b | ||
|
|
69bed4d9fa | ||
|
|
a5f1efac27 |
3
.github/workflows/pull_strings.yml
vendored
3
.github/workflows/pull_strings.yml
vendored
@@ -16,8 +16,9 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: dev
|
||||
fetch-depth: 0
|
||||
clean: true
|
||||
|
||||
- name: Pull strings
|
||||
uses: crowdin/github-action@v2
|
||||
|
||||
292
CHANGELOG.md
292
CHANGELOG.md
@@ -1,3 +1,295 @@
|
||||
# [5.10.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.10.0-dev.4...v5.10.0-dev.5) (2025-01-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide video description components:** Use correct string key names ([0f28c2b](https://github.com/ReVanced/revanced-patches/commit/0f28c2b44c0051ea7ab3136433b84c73321cf5bd))
|
||||
|
||||
# [5.10.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.10.0-dev.3...v5.10.0-dev.4) (2025-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide video description components:** Add `Hide How this content was made section` ([#4355](https://github.com/ReVanced/revanced-patches/issues/4355)) ([68ec54e](https://github.com/ReVanced/revanced-patches/commit/68ec54ef850ae8d6461dd0ef2846e6efbb59e482))
|
||||
|
||||
# [5.10.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.10.0-dev.2...v5.10.0-dev.3) (2025-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide ads:** Add `Hide end screen store banner` ([#4351](https://github.com/ReVanced/revanced-patches/issues/4351)) ([5505087](https://github.com/ReVanced/revanced-patches/commit/55050878028fed82b0f583a9f7ba06b8f267f8ec))
|
||||
|
||||
# [5.10.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.10.0-dev.1...v5.10.0-dev.2) (2025-01-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add patch `Disable HDR video` ([#4347](https://github.com/ReVanced/revanced-patches/issues/4347)) ([0528f7c](https://github.com/ReVanced/revanced-patches/commit/0528f7cad856a2b1347e41944167b0583fc4a3d9))
|
||||
|
||||
# [5.10.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.9.1-dev.4...v5.10.0-dev.1) (2025-01-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Theme:** Add option to use custom seekbar accent color ([#4337](https://github.com/ReVanced/revanced-patches/issues/4337)) ([952b4fc](https://github.com/ReVanced/revanced-patches/commit/952b4fc4c9291e1a3e71437b503857763c973dd4))
|
||||
|
||||
## [5.9.1-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.9.1-dev.3...v5.9.1-dev.4) (2025-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Hide new kind of community post ([#4341](https://github.com/ReVanced/revanced-patches/issues/4341)) ([02685c4](https://github.com/ReVanced/revanced-patches/commit/02685c4567aca55f22d45dc238a7d1f0ea264143))
|
||||
|
||||
## [5.9.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.9.1-dev.2...v5.9.1-dev.3) (2025-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide seekbar:** Do not hide player seekbar if hide feed seekbar is enabled ([#4333](https://github.com/ReVanced/revanced-patches/issues/4333)) ([f5cf6f2](https://github.com/ReVanced/revanced-patches/commit/f5cf6f2a445492d33815a9772f49deac2d70eba9))
|
||||
|
||||
## [5.9.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.9.1-dev.1...v5.9.1-dev.2) (2025-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Theme:** Fix 19.25 - 19.45 patch error ([5b47a5f](https://github.com/ReVanced/revanced-patches/commit/5b47a5f0f6299daaae209341064fd85f16ca18a6))
|
||||
|
||||
## [5.9.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.9.0...v5.9.1-dev.1) (2025-01-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Theme:** Replace custom seekbar gradient colors instead of disabling ([#4329](https://github.com/ReVanced/revanced-patches/issues/4329)) ([f03da98](https://github.com/ReVanced/revanced-patches/commit/f03da983051021e0c372557a5354d5d967409564))
|
||||
|
||||
# [5.9.0](https://github.com/ReVanced/revanced-patches/compare/v5.8.1...v5.9.0) (2025-01-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Resolve playback issues after changing from cellular to wifi ([#4277](https://github.com/ReVanced/revanced-patches/issues/4277)) ([e93e1c8](https://github.com/ReVanced/revanced-patches/commit/e93e1c8ec3367e941034e9c4e3725ec1db429a60))
|
||||
* **YouTube - Spoof video streams:** Update client user-agent ([#4304](https://github.com/ReVanced/revanced-patches/issues/4304)) ([7917871](https://github.com/ReVanced/revanced-patches/commit/7917871f510b6b805370ef98a0cf8a4e2df0e900))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide feed components:** Handle new type of surveys ([#4295](https://github.com/ReVanced/revanced-patches/issues/4295)) ([c770e03](https://github.com/ReVanced/revanced-patches/commit/c770e03f3801367cb531af860fbdfa43dca89af0))
|
||||
* **YouTube - Playback speed:** Add option to change 2x tap and hold speed ([#4307](https://github.com/ReVanced/revanced-patches/issues/4307)) ([02fb26e](https://github.com/ReVanced/revanced-patches/commit/02fb26e9458fb8635d497e6e78f964055244d738))
|
||||
* **YouTube - Settings:** Add option to use new Cairo settings menus ([#4305](https://github.com/ReVanced/revanced-patches/issues/4305)) ([7b8a2a2](https://github.com/ReVanced/revanced-patches/commit/7b8a2a2721ab5351f8c0251401aceddf0c5327df))
|
||||
|
||||
# [5.9.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.9.0-dev.3...v5.9.0-dev.4) (2025-01-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Update client user-agent ([#4304](https://github.com/ReVanced/revanced-patches/issues/4304)) ([7917871](https://github.com/ReVanced/revanced-patches/commit/7917871f510b6b805370ef98a0cf8a4e2df0e900))
|
||||
|
||||
# [5.9.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.9.0-dev.2...v5.9.0-dev.3) (2025-01-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Settings:** Add option to use new Cairo settings menus ([#4305](https://github.com/ReVanced/revanced-patches/issues/4305)) ([7b8a2a2](https://github.com/ReVanced/revanced-patches/commit/7b8a2a2721ab5351f8c0251401aceddf0c5327df))
|
||||
|
||||
# [5.9.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.9.0-dev.1...v5.9.0-dev.2) (2025-01-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Playback speed:** Add option to change 2x tap and hold speed ([#4307](https://github.com/ReVanced/revanced-patches/issues/4307)) ([02fb26e](https://github.com/ReVanced/revanced-patches/commit/02fb26e9458fb8635d497e6e78f964055244d738))
|
||||
|
||||
# [5.9.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.8.2-dev.1...v5.9.0-dev.1) (2025-01-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide feed components:** Handle new type of surveys ([#4295](https://github.com/ReVanced/revanced-patches/issues/4295)) ([c770e03](https://github.com/ReVanced/revanced-patches/commit/c770e03f3801367cb531af860fbdfa43dca89af0))
|
||||
|
||||
## [5.8.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.8.1...v5.8.2-dev.1) (2025-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Resolve playback issues after changing from cellular to wifi ([#4277](https://github.com/ReVanced/revanced-patches/issues/4277)) ([e93e1c8](https://github.com/ReVanced/revanced-patches/commit/e93e1c8ec3367e941034e9c4e3725ec1db429a60))
|
||||
|
||||
## [5.8.1](https://github.com/ReVanced/revanced-patches/compare/v5.8.0...v5.8.1) (2025-01-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Add 'Android Creator' ([#4262](https://github.com/ReVanced/revanced-patches/issues/4262)) ([0479dd2](https://github.com/ReVanced/revanced-patches/commit/0479dd265e09b0accdf6ff6b00c8e938dc5b96c7))
|
||||
|
||||
## [5.8.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.8.0...v5.8.1-dev.1) (2025-01-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Add 'Android Creator' ([#4262](https://github.com/ReVanced/revanced-patches/issues/4262)) ([0479dd2](https://github.com/ReVanced/revanced-patches/commit/0479dd265e09b0accdf6ff6b00c8e938dc5b96c7))
|
||||
|
||||
# [5.8.0](https://github.com/ReVanced/revanced-patches/compare/v5.7.2...v5.8.0) (2024-12-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **GmsCore support:** Do not show battery optimization error on Android Automotive devices (Google built-in) ([#4218](https://github.com/ReVanced/revanced-patches/issues/4218)) ([d6e389c](https://github.com/ReVanced/revanced-patches/commit/d6e389cc43bc40724f032b230f70048276349a19))
|
||||
* **YouTube - Exit fullscreen mode:** Exit fullscreen mode of first video opened after cold start ([be5cf2e](https://github.com/ReVanced/revanced-patches/commit/be5cf2e834d87d51b5d3061d46bd7154d6306787))
|
||||
* **YouTube - Force original audio:** If stream spoofing to Android then show a summary text why force audio is not available ([#4220](https://github.com/ReVanced/revanced-patches/issues/4220)) ([029aee8](https://github.com/ReVanced/revanced-patches/commit/029aee8023f096413fc80a2c583b4fe55ecb10ac))
|
||||
* **YouTube - Spoof video streams:** Ignore harmless error toast if hide ads is disabled ([c3423bb](https://github.com/ReVanced/revanced-patches/commit/c3423bb9e531cfa52f6d28e0b98bbe8ab8684c30))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Swipe controls:** Add option to enable/disable fullscreen swipe to next video ([#4222](https://github.com/ReVanced/revanced-patches/issues/4222)) ([119092f](https://github.com/ReVanced/revanced-patches/commit/119092fafa4129849246df15fe8076ed3b491b85))
|
||||
* **YouTube - Hide Shorts components:** Add option to hide Shorts in watch history ([#4214](https://github.com/ReVanced/revanced-patches/issues/4214)) ([19c2742](https://github.com/ReVanced/revanced-patches/commit/19c2742aa367367c77bb50ddad6f8a20fef8ea0a))
|
||||
* **YouTube - Spoof app version:** Add 'Restore old navigation and toolbar icons' ([f84e459](https://github.com/ReVanced/revanced-patches/commit/f84e459d3d54b3001586796ab4e114ebadf09043))
|
||||
* **YouTube:** Add `Change form factor` patch ([#4217](https://github.com/ReVanced/revanced-patches/issues/4217)) ([644ac5b](https://github.com/ReVanced/revanced-patches/commit/644ac5baa68b209a32300149a2efa009b776f9a7))
|
||||
* **YouTube:** Add `Exit fullscreen mode` patch ([#4223](https://github.com/ReVanced/revanced-patches/issues/4223)) ([bb5d03b](https://github.com/ReVanced/revanced-patches/commit/bb5d03bd89a3f932c77e4e9de90174c374933688))
|
||||
* **YouTube:** Add in app option to select a preferred language for ReVanced specific text ([#4231](https://github.com/ReVanced/revanced-patches/issues/4231)) ([3932af3](https://github.com/ReVanced/revanced-patches/commit/3932af397ae89a0b30191cd870bd6cddb7a078db))
|
||||
|
||||
# [5.8.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.7...v5.8.0-dev.8) (2024-12-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add in app option to select a preferred language for ReVanced specific text ([#4231](https://github.com/ReVanced/revanced-patches/issues/4231)) ([3932af3](https://github.com/ReVanced/revanced-patches/commit/3932af397ae89a0b30191cd870bd6cddb7a078db))
|
||||
|
||||
# [5.8.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.6...v5.8.0-dev.7) (2024-12-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Ignore harmless error toast if hide ads is disabled ([c3423bb](https://github.com/ReVanced/revanced-patches/commit/c3423bb9e531cfa52f6d28e0b98bbe8ab8684c30))
|
||||
|
||||
# [5.8.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.5...v5.8.0-dev.6) (2024-12-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Exit fullscreen mode:** Exit fullscreen mode of first video opened after cold start ([be5cf2e](https://github.com/ReVanced/revanced-patches/commit/be5cf2e834d87d51b5d3061d46bd7154d6306787))
|
||||
|
||||
# [5.8.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.4...v5.8.0-dev.5) (2024-12-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Change form factor` patch ([#4217](https://github.com/ReVanced/revanced-patches/issues/4217)) ([644ac5b](https://github.com/ReVanced/revanced-patches/commit/644ac5baa68b209a32300149a2efa009b776f9a7))
|
||||
|
||||
# [5.8.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.3...v5.8.0-dev.4) (2024-12-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **GmsCore support:** Do not show battery optimization error on Android Automotive devices (Google built-in) ([#4218](https://github.com/ReVanced/revanced-patches/issues/4218)) ([d6e389c](https://github.com/ReVanced/revanced-patches/commit/d6e389cc43bc40724f032b230f70048276349a19))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Swipe controls:** Add option to enable/disable fullscreen swipe to next video ([#4222](https://github.com/ReVanced/revanced-patches/issues/4222)) ([119092f](https://github.com/ReVanced/revanced-patches/commit/119092fafa4129849246df15fe8076ed3b491b85))
|
||||
* **YouTube:** Add `Exit fullscreen mode` patch ([#4223](https://github.com/ReVanced/revanced-patches/issues/4223)) ([bb5d03b](https://github.com/ReVanced/revanced-patches/commit/bb5d03bd89a3f932c77e4e9de90174c374933688))
|
||||
|
||||
# [5.8.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.2...v5.8.0-dev.3) (2024-12-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Force original audio:** If stream spoofing to Android then show a summary text why force audio is not available ([#4220](https://github.com/ReVanced/revanced-patches/issues/4220)) ([029aee8](https://github.com/ReVanced/revanced-patches/commit/029aee8023f096413fc80a2c583b4fe55ecb10ac))
|
||||
|
||||
# [5.8.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.8.0-dev.1...v5.8.0-dev.2) (2024-12-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Spoof app version:** Add 'Restore old navigation and toolbar icons' ([f84e459](https://github.com/ReVanced/revanced-patches/commit/f84e459d3d54b3001586796ab4e114ebadf09043))
|
||||
|
||||
# [5.8.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.2...v5.8.0-dev.1) (2024-12-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Add option to hide Shorts in watch history ([#4214](https://github.com/ReVanced/revanced-patches/issues/4214)) ([19c2742](https://github.com/ReVanced/revanced-patches/commit/19c2742aa367367c77bb50ddad6f8a20fef8ea0a))
|
||||
|
||||
## [5.7.2](https://github.com/ReVanced/revanced-patches/compare/v5.7.1...v5.7.2) (2024-12-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Don't hide Shorts channel bar when toggling for video player ([9af6412](https://github.com/ReVanced/revanced-patches/commit/9af6412d92ec31e612eaabba6578453da0fc61d6))
|
||||
* **YouTube - Spoof video streams:** Add iOS TV client, restore iOS 'force AVC', show client type in stats for nerds ([#4202](https://github.com/ReVanced/revanced-patches/issues/4202)) ([ab29f80](https://github.com/ReVanced/revanced-patches/commit/ab29f808a9f55b5ab0055533c1a6de549b0631a6))
|
||||
|
||||
## [5.7.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.7.2-dev.1...v5.7.2-dev.2) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Don't hide Shorts channel bar when toggling for video player ([9af6412](https://github.com/ReVanced/revanced-patches/commit/9af6412d92ec31e612eaabba6578453da0fc61d6))
|
||||
|
||||
## [5.7.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.1...v5.7.2-dev.1) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Add iOS TV client, restore iOS 'force AVC', show client type in stats for nerds ([#4202](https://github.com/ReVanced/revanced-patches/issues/4202)) ([ab29f80](https://github.com/ReVanced/revanced-patches/commit/ab29f808a9f55b5ab0055533c1a6de549b0631a6))
|
||||
|
||||
## [5.7.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.0...v5.7.1) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Show a toast and not a dialog if segment submitted successfully ([134b189](https://github.com/ReVanced/revanced-patches/commit/134b189791113dcf1a1cb7c87b8a0954f432730c))
|
||||
* **YouTube - Spoof video streams:** Use 2 letter device language code ([33ff997](https://github.com/ReVanced/revanced-patches/commit/33ff9972000581aca92262f984efb114eeeb9537))
|
||||
* **YouTube - Spoof video streams:** Use Android VR authentication if using default audio language ([#4191](https://github.com/ReVanced/revanced-patches/issues/4191)) ([98773cc](https://github.com/ReVanced/revanced-patches/commit/98773cc7d46e5c9c7715b82c8006f1ccbcc5443c))
|
||||
* **YouTube - Theme:** Use dark theme color for status and navigation bar ([0240efe](https://github.com/ReVanced/revanced-patches/commit/0240efe33e5444625ca2b760c861c9046d3dc836))
|
||||
* **YouTube:** Do not reset playback speed to 1.0x after closing comment thread (Fixes stock YouTube bug) ([#4195](https://github.com/ReVanced/revanced-patches/issues/4195)) ([dda788c](https://github.com/ReVanced/revanced-patches/commit/dda788c58c789d4f91646ea8e8a8077f590ab6b3))
|
||||
|
||||
## [5.7.1-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.4...v5.7.1-dev.5) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Use 2 letter device language code ([33ff997](https://github.com/ReVanced/revanced-patches/commit/33ff9972000581aca92262f984efb114eeeb9537))
|
||||
|
||||
## [5.7.1-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.3...v5.7.1-dev.4) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Do not reset playback speed to 1.0x after closing comment thread (Fixes stock YouTube bug) ([#4195](https://github.com/ReVanced/revanced-patches/issues/4195)) ([dda788c](https://github.com/ReVanced/revanced-patches/commit/dda788c58c789d4f91646ea8e8a8077f590ab6b3))
|
||||
|
||||
## [5.7.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.2...v5.7.1-dev.3) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Show a toast and not a dialog if segment submitted successfully ([134b189](https://github.com/ReVanced/revanced-patches/commit/134b189791113dcf1a1cb7c87b8a0954f432730c))
|
||||
|
||||
## [5.7.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.1...v5.7.1-dev.2) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Theme:** Use dark theme color for status and navigation bar ([0240efe](https://github.com/ReVanced/revanced-patches/commit/0240efe33e5444625ca2b760c861c9046d3dc836))
|
||||
|
||||
## [5.7.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.0...v5.7.1-dev.1) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Use Android VR authentication if using default audio language ([#4191](https://github.com/ReVanced/revanced-patches/issues/4191)) ([98773cc](https://github.com/ReVanced/revanced-patches/commit/98773cc7d46e5c9c7715b82c8006f1ccbcc5443c))
|
||||
|
||||
# [5.7.0](https://github.com/ReVanced/revanced-patches/compare/v5.6.0...v5.7.0) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Force original audio:** Use correct availability for settings UI ([a7eedcb](https://github.com/ReVanced/revanced-patches/commit/a7eedcb4cca6b7b12629c478c24c0899c80e3615))
|
||||
* **YouTube - Spoof video stream:** Remove UI client type setting. Allow setting default audio language. ([#4184](https://github.com/ReVanced/revanced-patches/issues/4184)) ([99f3f29](https://github.com/ReVanced/revanced-patches/commit/99f3f29c649bf7693c05bbce2bb49bd53e05f050))
|
||||
* **YouTube - Spoof video streams:** Remove iOS, add clients Android TV and Android Creator ([#4180](https://github.com/ReVanced/revanced-patches/issues/4180)) ([86abfb2](https://github.com/ReVanced/revanced-patches/commit/86abfb2b0d4675f0a1cb9ab244783075bfe89281))
|
||||
* **YouTube:** Change fingerprints to support a wider range of target versions ([8a09174](https://github.com/ReVanced/revanced-patches/commit/8a09174def205a26ce49cb7815097e235069526a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `19.47.53` ([#4182](https://github.com/ReVanced/revanced-patches/issues/4182)) ([2089e61](https://github.com/ReVanced/revanced-patches/commit/2089e613d36c45352db7d852aaee0087b1c3e1a4))
|
||||
|
||||
# [5.7.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.6.1-dev.4...v5.7.0-dev.1) (2024-12-21)
|
||||
|
||||
|
||||
|
||||
@@ -106,7 +106,11 @@ public class GmsCoreSupport {
|
||||
}
|
||||
|
||||
// Check if GmsCore is whitelisted from battery optimizations.
|
||||
if (batteryOptimizationsEnabled(context)) {
|
||||
if (isAndroidAutomotive(context)) {
|
||||
// Ignore Android Automotive devices (Google built-in),
|
||||
// as there is no way to disable battery optimizations.
|
||||
Logger.printDebug(() -> "Device is Android Automotive");
|
||||
} else if (batteryOptimizationsEnabled(context)) {
|
||||
Logger.printInfo(() -> "GmsCore is not whitelisted from battery optimizations");
|
||||
|
||||
showBatteryOptimizationDialog(context,
|
||||
@@ -147,6 +151,10 @@ public class GmsCoreSupport {
|
||||
return !powerManager.isIgnoringBatteryOptimizations(GMS_CORE_PACKAGE_NAME);
|
||||
}
|
||||
|
||||
private static boolean isAndroidAutomotive(Context context) {
|
||||
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
|
||||
}
|
||||
|
||||
private static String getGmsCoreDownload() {
|
||||
final var vendorGroupId = getGmsCoreVendorGroupId();
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
|
||||
@@ -40,13 +40,15 @@ import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
import app.revanced.extension.shared.settings.preference.ReVancedAboutPreference;
|
||||
|
||||
public class Utils {
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static Context context;
|
||||
private static volatile Context context;
|
||||
|
||||
private static String versionName;
|
||||
private static String applicationLabel;
|
||||
@@ -360,7 +362,17 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static void setContext(Context appContext) {
|
||||
// Must initially set context as the language settings needs it.
|
||||
context = appContext;
|
||||
|
||||
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
|
||||
if (language != AppLanguage.DEFAULT) {
|
||||
// Create a new context with the desired 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.
|
||||
@@ -523,6 +535,11 @@ public class Utils {
|
||||
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
|
||||
}
|
||||
|
||||
public static boolean isLandscapeOrientation() {
|
||||
final int orientation = context.getResources().getConfiguration().orientation;
|
||||
return orientation == Configuration.ORIENTATION_LANDSCAPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically logs any exceptions the runnable throws.
|
||||
*
|
||||
@@ -595,7 +612,7 @@ public class Utils {
|
||||
|| networkType == NetworkType.OTHER;
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission") // permission already included in YouTube
|
||||
@SuppressLint({"MissingPermission", "deprecation"}) // Permission already included in YouTube.
|
||||
public static NetworkType getNetworkType() {
|
||||
Context networkContext = getContext();
|
||||
if (networkContext == null) {
|
||||
@@ -705,8 +722,8 @@ public class Utils {
|
||||
Preference preference = group.getPreference(i);
|
||||
|
||||
final Sort preferenceSort;
|
||||
if (preference instanceof PreferenceGroup) {
|
||||
sortPreferenceGroups((PreferenceGroup) preference);
|
||||
if (preference instanceof PreferenceGroup subGroup) {
|
||||
sortPreferenceGroups(subGroup);
|
||||
preferenceSort = groupSort; // Sort value for groups is for it's content, not itself.
|
||||
} else {
|
||||
// Allow individual preferences to set a key sorting.
|
||||
@@ -760,8 +777,8 @@ public class Utils {
|
||||
return;
|
||||
}
|
||||
|
||||
String deviceLanguage = Utils.getContext().getResources().getConfiguration().locale.getLanguage();
|
||||
if (deviceLanguage.equals("en")) {
|
||||
String revancedLocale = Utils.getContext().getResources().getConfiguration().locale.getLanguage();
|
||||
if (revancedLocale.equals(Locale.ENGLISH.getLanguage())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -769,8 +786,8 @@ public class Utils {
|
||||
Preference pref = group.getPreference(i);
|
||||
pref.setSingleLineTitle(false);
|
||||
|
||||
if (pref instanceof PreferenceGroup) {
|
||||
setPreferenceTitlesToMultiLineIfNeeded((PreferenceGroup) pref);
|
||||
if (pref instanceof PreferenceGroup subGroup) {
|
||||
setPreferenceTitlesToMultiLineIfNeeded(subGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package app.revanced.extension.shared.settings;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum AppLanguage {
|
||||
/**
|
||||
* The current app language.
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
// Language codes found in locale_config.xml
|
||||
// All region specific variants have been removed.
|
||||
AF,
|
||||
AM,
|
||||
AR,
|
||||
AS,
|
||||
AZ,
|
||||
BE,
|
||||
BG,
|
||||
BN,
|
||||
BS,
|
||||
CA,
|
||||
CS,
|
||||
DA,
|
||||
DE,
|
||||
EL,
|
||||
EN,
|
||||
ES,
|
||||
ET,
|
||||
EU,
|
||||
FA,
|
||||
FI,
|
||||
FR,
|
||||
GL,
|
||||
GU,
|
||||
HI,
|
||||
HE, // App uses obsolete 'IW' and not the modern 'HE' ISO code.
|
||||
HR,
|
||||
HU,
|
||||
HY,
|
||||
ID,
|
||||
IS,
|
||||
IT,
|
||||
JA,
|
||||
KA,
|
||||
KK,
|
||||
KM,
|
||||
KN,
|
||||
KO,
|
||||
KY,
|
||||
LO,
|
||||
LT,
|
||||
LV,
|
||||
MK,
|
||||
ML,
|
||||
MN,
|
||||
MR,
|
||||
MS,
|
||||
MY,
|
||||
NE,
|
||||
NL,
|
||||
NB,
|
||||
OR,
|
||||
PA,
|
||||
PL,
|
||||
PT,
|
||||
RO,
|
||||
RU,
|
||||
SI,
|
||||
SK,
|
||||
SL,
|
||||
SQ,
|
||||
SR,
|
||||
SV,
|
||||
SW,
|
||||
TA,
|
||||
TE,
|
||||
TH,
|
||||
TL,
|
||||
TR,
|
||||
UK,
|
||||
UR,
|
||||
UZ,
|
||||
VI,
|
||||
ZH,
|
||||
ZU;
|
||||
|
||||
private final String language;
|
||||
|
||||
AppLanguage() {
|
||||
language = name().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The 2 letter ISO 639_1 language code.
|
||||
*/
|
||||
public String getLanguage() {
|
||||
// Changing the app language does not force the app to completely restart,
|
||||
// so the default needs to be the current language and not a static field.
|
||||
if (this == DEFAULT) {
|
||||
return Locale.getDefault().getLanguage();
|
||||
}
|
||||
|
||||
return language;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
if (this == DEFAULT) {
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
return Locale.forLanguageTag(language);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,10 @@ package app.revanced.extension.shared.settings;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability;
|
||||
|
||||
import app.revanced.extension.shared.spoof.AudioStreamLanguage;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
|
||||
/**
|
||||
* Settings shared across multiple apps.
|
||||
@@ -19,6 +21,14 @@ public class BaseSettings {
|
||||
|
||||
public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false);
|
||||
|
||||
public static final EnumSetting<AppLanguage> REVANCED_LANGUAGE = new EnumSetting<>("revanced_language", AppLanguage.DEFAULT, true, "revanced_language_user_dialog_message");
|
||||
|
||||
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<AudioStreamLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT, parent(SPOOF_VIDEO_STREAMS));
|
||||
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));
|
||||
|
||||
}
|
||||
|
||||
@@ -153,7 +153,6 @@ public abstract class Setting<T> {
|
||||
|
||||
/**
|
||||
* Confirmation message to display, if the user tries to change the setting from the default value.
|
||||
* Currently this works only for Boolean setting types.
|
||||
*/
|
||||
@Nullable
|
||||
public final StringRef userDialogMessage;
|
||||
@@ -244,6 +243,7 @@ public abstract class Setting<T> {
|
||||
*
|
||||
* This method will be deleted in the future.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static void migrateFromOldPreferences(@NonNull SharedPrefCategory oldPrefs, @NonNull Setting setting, String settingKey) {
|
||||
if (!oldPrefs.preferences.contains(settingKey)) {
|
||||
return; // Nothing to do.
|
||||
@@ -419,6 +419,7 @@ public abstract class Setting<T> {
|
||||
|
||||
boolean rebootSettingChanged = false;
|
||||
int numberOfSettingsImported = 0;
|
||||
//noinspection rawtypes
|
||||
for (Setting setting : SETTINGS) {
|
||||
String key = setting.getImportExportKey();
|
||||
if (json.has(key)) {
|
||||
|
||||
@@ -42,7 +42,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||
try {
|
||||
Setting<?> setting = Setting.getSettingFromPath(str);
|
||||
Setting<?> setting = Setting.getSettingFromPath(Objects.requireNonNull(str));
|
||||
if (setting == null) {
|
||||
return;
|
||||
}
|
||||
@@ -52,23 +52,21 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
}
|
||||
Logger.printDebug(() -> "Preference changed: " + setting.key);
|
||||
|
||||
// Apply 'Setting <- Preference', unless during importing when it needs to be 'Setting -> Preference'.
|
||||
updatePreference(pref, setting, true, settingImportInProgress);
|
||||
// Update any other preference availability that may now be different.
|
||||
updateUIAvailability();
|
||||
|
||||
if (settingImportInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!showingUserDialogMessage) {
|
||||
if (setting.userDialogMessage != null && ((SwitchPreference) pref).isChecked() != (Boolean) setting.defaultValue) {
|
||||
showSettingUserDialogConfirmation((SwitchPreference) pref, (BooleanSetting) setting);
|
||||
if (!settingImportInProgress && !showingUserDialogMessage) {
|
||||
if (setting.userDialogMessage != null && !prefIsSetToDefault(pref, setting)) {
|
||||
// Do not change the setting yet, to allow preserving whatever
|
||||
// list/text value was previously set if it needs to be reverted.
|
||||
showSettingUserDialogConfirmation(pref, setting);
|
||||
return;
|
||||
} else if (setting.rebootApp) {
|
||||
showRestartDialog(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
// Apply 'Setting <- Preference', unless during importing when it needs to be 'Setting -> Preference'.
|
||||
updatePreference(pref, setting, true, settingImportInProgress);
|
||||
// Update any other preference availability that may now be different.
|
||||
updateUIAvailability();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "OnSharedPreferenceChangeListener failure", ex);
|
||||
}
|
||||
@@ -92,7 +90,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
Utils.setPreferenceTitlesToMultiLineIfNeeded(screen);
|
||||
}
|
||||
|
||||
private void showSettingUserDialogConfirmation(SwitchPreference switchPref, BooleanSetting setting) {
|
||||
private void showSettingUserDialogConfirmation(Preference pref, Setting<?> setting) {
|
||||
Utils.verifyOnMainThread();
|
||||
|
||||
final var context = getContext();
|
||||
@@ -104,12 +102,19 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
.setTitle(confirmDialogTitle)
|
||||
.setMessage(Objects.requireNonNull(setting.userDialogMessage).toString())
|
||||
.setPositiveButton(android.R.string.ok, (dialog, id) -> {
|
||||
// User confirmed, save to the Setting.
|
||||
updatePreference(pref, setting, true, false);
|
||||
|
||||
// Update availability of other preferences that may be changed.
|
||||
updateUIAvailability();
|
||||
|
||||
if (setting.rebootApp) {
|
||||
showRestartDialog(context);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, id) -> {
|
||||
switchPref.setChecked(setting.defaultValue); // Recursive call that resets the Setting value.
|
||||
// Restore whatever the setting was before the change.
|
||||
updatePreference(pref, setting, true, true);
|
||||
})
|
||||
.setOnDismissListener(dialog -> {
|
||||
showingUserDialogMessage = false;
|
||||
@@ -132,6 +137,24 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
updatePreferenceScreen(getPreferenceScreen(), false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the preference is currently set to the default value of the Setting.
|
||||
*/
|
||||
protected boolean prefIsSetToDefault(Preference pref, Setting<?> setting) {
|
||||
if (pref instanceof SwitchPreference switchPref) {
|
||||
return switchPref.isChecked() == (Boolean) setting.defaultValue;
|
||||
}
|
||||
if (pref instanceof EditTextPreference editPreference) {
|
||||
return editPreference.getText().equals(setting.defaultValue.toString());
|
||||
}
|
||||
if (pref instanceof ListPreference listPref) {
|
||||
return listPref.getValue().equals(setting.defaultValue.toString());
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Must override method to handle "
|
||||
+ "preference type: " + pref.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs all UI Preferences to any {@link Setting} they represent.
|
||||
*/
|
||||
@@ -170,23 +193,20 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
protected void syncSettingWithPreference(@NonNull Preference pref,
|
||||
@NonNull Setting<?> setting,
|
||||
boolean applySettingToPreference) {
|
||||
if (pref instanceof SwitchPreference) {
|
||||
SwitchPreference switchPref = (SwitchPreference) pref;
|
||||
if (pref instanceof SwitchPreference switchPref) {
|
||||
BooleanSetting boolSetting = (BooleanSetting) setting;
|
||||
if (applySettingToPreference) {
|
||||
switchPref.setChecked(boolSetting.get());
|
||||
} else {
|
||||
BooleanSetting.privateSetValue(boolSetting, switchPref.isChecked());
|
||||
}
|
||||
} else if (pref instanceof EditTextPreference) {
|
||||
EditTextPreference editPreference = (EditTextPreference) pref;
|
||||
} else if (pref instanceof EditTextPreference editPreference) {
|
||||
if (applySettingToPreference) {
|
||||
editPreference.setText(setting.get().toString());
|
||||
} else {
|
||||
Setting.privateSetValueFromString(setting, editPreference.getText());
|
||||
}
|
||||
} else if (pref instanceof ListPreference) {
|
||||
ListPreference listPref = (ListPreference) pref;
|
||||
} else if (pref instanceof ListPreference listPref) {
|
||||
if (applySettingToPreference) {
|
||||
listPref.setValue(setting.get().toString());
|
||||
} else {
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
package app.revanced.extension.shared.spoof;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum AudioStreamLanguage {
|
||||
/**
|
||||
* YouTube default.
|
||||
* Can be the original language or can be app language,
|
||||
* depending on what YouTube decides to pick as the default.
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
// Language codes found in locale_config.xml
|
||||
// Region specific variants of Chinese/English/Spanish/French have been removed.
|
||||
AF,
|
||||
AM,
|
||||
AR,
|
||||
AS,
|
||||
AZ,
|
||||
BE,
|
||||
BG,
|
||||
BN,
|
||||
BS,
|
||||
CA,
|
||||
CS,
|
||||
DA,
|
||||
DE,
|
||||
EL,
|
||||
EN,
|
||||
ES,
|
||||
ET,
|
||||
EU,
|
||||
FA,
|
||||
FI,
|
||||
FR,
|
||||
GL,
|
||||
GU,
|
||||
HI,
|
||||
HE, // App uses obsolete 'IW' and 'HE' is modern ISO code.
|
||||
HR,
|
||||
HU,
|
||||
HY,
|
||||
ID,
|
||||
IS,
|
||||
IT,
|
||||
JA,
|
||||
KA,
|
||||
KK,
|
||||
KM,
|
||||
KN,
|
||||
KO,
|
||||
KY,
|
||||
LO,
|
||||
LT,
|
||||
LV,
|
||||
MK,
|
||||
ML,
|
||||
MN,
|
||||
MR,
|
||||
MS,
|
||||
MY,
|
||||
NE,
|
||||
NL,
|
||||
NB,
|
||||
OR,
|
||||
PA,
|
||||
PL,
|
||||
PT_BR,
|
||||
PT_PT,
|
||||
RO,
|
||||
RU,
|
||||
SI,
|
||||
SK,
|
||||
SL,
|
||||
SQ,
|
||||
SR,
|
||||
SV,
|
||||
SW,
|
||||
TA,
|
||||
TE,
|
||||
TH,
|
||||
TL,
|
||||
TR,
|
||||
UK,
|
||||
UR,
|
||||
UZ,
|
||||
VI,
|
||||
ZH,
|
||||
ZU;
|
||||
|
||||
private final String iso639_1;
|
||||
|
||||
AudioStreamLanguage() {
|
||||
String name = name();
|
||||
final int regionSeparatorIndex = name.indexOf('_');
|
||||
if (regionSeparatorIndex >= 0) {
|
||||
iso639_1 = name.substring(0, regionSeparatorIndex).toLowerCase(Locale.US)
|
||||
+ name.substring(regionSeparatorIndex);
|
||||
} else {
|
||||
iso639_1 = name().toLowerCase(Locale.US);
|
||||
}
|
||||
}
|
||||
|
||||
public String getIso639_1() {
|
||||
// Changing the app language does not force the app to completely restart,
|
||||
// so the default needs to be the current language and not a static field.
|
||||
if (this == DEFAULT) {
|
||||
return Locale.getDefault().toLanguageTag();
|
||||
}
|
||||
|
||||
return iso639_1;
|
||||
}
|
||||
}
|
||||
@@ -4,45 +4,119 @@ import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
public enum ClientType {
|
||||
// https://dumps.tadiphone.dev/dumps/oculus/eureka
|
||||
ANDROID_VR_NO_AUTH( // Must be first so a default audio language can be set.
|
||||
ANDROID_VR_NO_AUTH(
|
||||
28,
|
||||
"ANDROID_VR",
|
||||
"com.google.android.apps.youtube.vr.oculus",
|
||||
"Oculus",
|
||||
"Quest 3",
|
||||
"Android",
|
||||
"12",
|
||||
"com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip",
|
||||
"32", // Android 12.1
|
||||
"1.56.21",
|
||||
false),
|
||||
// Fall over to authenticated ('hl' is ignored and audio is same as language set in users Google account).
|
||||
ANDROID_VR(
|
||||
ANDROID_VR_NO_AUTH.id,
|
||||
ANDROID_VR_NO_AUTH.clientName,
|
||||
ANDROID_VR_NO_AUTH.deviceModel,
|
||||
ANDROID_VR_NO_AUTH.osVersion,
|
||||
ANDROID_VR_NO_AUTH.userAgent,
|
||||
ANDROID_VR_NO_AUTH.androidSdkVersion,
|
||||
ANDROID_VR_NO_AUTH.clientVersion,
|
||||
true),
|
||||
// Android 12.1
|
||||
"32",
|
||||
"SQ3A.220605.009.A1",
|
||||
"132.0.6808.3",
|
||||
"1.61.48",
|
||||
false,
|
||||
false,
|
||||
"Android VR No auth"
|
||||
),
|
||||
// Chromecast with Google TV 4K.
|
||||
// https://dumps.tadiphone.dev/dumps/google/kirkwood
|
||||
ANDROID_UNPLUGGED(
|
||||
29,
|
||||
"ANDROID_UNPLUGGED",
|
||||
"com.google.android.apps.youtube.unplugged",
|
||||
"Google",
|
||||
"Google TV Streamer",
|
||||
"14",
|
||||
"com.google.android.apps.youtube.unplugged/8.49.0 (Linux; U; Android 14; GB) gzip",
|
||||
"34",
|
||||
"8.49.0",
|
||||
true), // Requires login.
|
||||
ANDROID_CREATOR(
|
||||
14,
|
||||
"ANDROID_CREATOR",
|
||||
"Android",
|
||||
"11",
|
||||
"com.google.android.apps.youtube.creator/24.45.100 (Linux; U; Android 11) gzip",
|
||||
"30",
|
||||
"24.45.100",
|
||||
true); // Requires login.
|
||||
"14",
|
||||
"34",
|
||||
"UTT3.240625.001.K5",
|
||||
"132.0.6808.3",
|
||||
"8.49.0",
|
||||
true,
|
||||
true,
|
||||
"Android TV"
|
||||
),
|
||||
// Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
|
||||
// Google Pixel 9 Pro Fold
|
||||
// https://dumps.tadiphone.dev/dumps/google/barbet
|
||||
ANDROID_CREATOR(
|
||||
14,
|
||||
"ANDROID_CREATOR",
|
||||
"com.google.android.apps.youtube.creator",
|
||||
"Google",
|
||||
"Pixel 9 Pro Fold",
|
||||
"Android",
|
||||
"15",
|
||||
"35",
|
||||
"AP3A.241005.015.A2",
|
||||
"132.0.6779.0",
|
||||
"23.47.101",
|
||||
true,
|
||||
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",
|
||||
"com.google.ios.youtubeunplugged",
|
||||
"Apple",
|
||||
forceAVC()
|
||||
// 11 Pro Max (last device with iOS 13)
|
||||
? "iPhone12,5"
|
||||
// 15 Pro Max
|
||||
: "iPhone16,2",
|
||||
"iOS",
|
||||
forceAVC()
|
||||
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
|
||||
? "13.7.17H35"
|
||||
: "18.2.22C152",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
// Version number should be a valid iOS release.
|
||||
// https://www.ipa4fun.com/history/152043/
|
||||
forceAVC()
|
||||
// Some newer versions can also force AVC,
|
||||
// but 6.45 is the last version that supports iOS 13.
|
||||
? "6.45"
|
||||
: "8.49",
|
||||
true,
|
||||
true,
|
||||
forceAVC()
|
||||
? "iOS TV Force AVC"
|
||||
: "iOS TV"
|
||||
);
|
||||
|
||||
private static boolean forceAVC() {
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* YouTube
|
||||
@@ -53,20 +127,35 @@ public enum ClientType {
|
||||
public final String clientName;
|
||||
|
||||
/**
|
||||
* Device model, equivalent to {@link Build#MODEL} (System property: ro.product.model)
|
||||
* App package name.
|
||||
*/
|
||||
public final String deviceModel;
|
||||
|
||||
/**
|
||||
* Device OS version.
|
||||
*/
|
||||
public final String osVersion;
|
||||
private final String packageName;
|
||||
|
||||
/**
|
||||
* Player user-agent.
|
||||
*/
|
||||
public final String userAgent;
|
||||
|
||||
/**
|
||||
* Device model, equivalent to {@link Build#MANUFACTURER} (System property: ro.product.vendor.manufacturer)
|
||||
*/
|
||||
public final String deviceMake;
|
||||
|
||||
/**
|
||||
* Device model, equivalent to {@link Build#MODEL} (System property: ro.product.vendor.model)
|
||||
*/
|
||||
public final String deviceModel;
|
||||
|
||||
/**
|
||||
* Device OS name.
|
||||
*/
|
||||
public final String osName;
|
||||
|
||||
/**
|
||||
* Device OS version.
|
||||
*/
|
||||
public final String osVersion;
|
||||
|
||||
/**
|
||||
* Android SDK version, equivalent to {@link Build.VERSION#SDK} (System property: ro.build.version.sdk)
|
||||
* Field is null if not applicable.
|
||||
@@ -74,31 +163,97 @@ public enum ClientType {
|
||||
@Nullable
|
||||
public final String androidSdkVersion;
|
||||
|
||||
/**
|
||||
* Android build id, equivalent to {@link Build#ID}.
|
||||
* Field is null if not applicable.
|
||||
*/
|
||||
@Nullable
|
||||
private final String buildId;
|
||||
|
||||
/**
|
||||
* Cronet release version, as found in decompiled client apk.
|
||||
* Field is null if not applicable.
|
||||
*/
|
||||
@Nullable
|
||||
private final String cronetVersion;
|
||||
|
||||
/**
|
||||
* App version.
|
||||
*/
|
||||
public final String clientVersion;
|
||||
|
||||
/**
|
||||
* If the client can access the API logged in.
|
||||
* If this client requires authentication and does not work
|
||||
* if logged out or in incognito mode.
|
||||
*/
|
||||
public final boolean canLogin;
|
||||
public final boolean requiresAuth;
|
||||
|
||||
/**
|
||||
* If the client should use authentication if available.
|
||||
*/
|
||||
public final boolean useAuth;
|
||||
|
||||
/**
|
||||
* Friendly name displayed in stats for nerds.
|
||||
*/
|
||||
public final String friendlyName;
|
||||
|
||||
@SuppressWarnings("ConstantLocale")
|
||||
ClientType(int id,
|
||||
String clientName,
|
||||
String packageName,
|
||||
String deviceMake,
|
||||
String deviceModel,
|
||||
String osName,
|
||||
String osVersion,
|
||||
String userAgent,
|
||||
@Nullable String androidSdkVersion,
|
||||
@Nullable String buildId,
|
||||
@Nullable String cronetVersion,
|
||||
String clientVersion,
|
||||
boolean canLogin) {
|
||||
boolean requiresAuth,
|
||||
boolean useAuth,
|
||||
String friendlyName) {
|
||||
this.id = id;
|
||||
this.clientName = clientName;
|
||||
this.packageName = packageName;
|
||||
this.deviceMake = deviceMake;
|
||||
this.deviceModel = deviceModel;
|
||||
this.osName = osName;
|
||||
this.osVersion = osVersion;
|
||||
this.userAgent = userAgent;
|
||||
this.androidSdkVersion = androidSdkVersion;
|
||||
this.buildId = buildId;
|
||||
this.cronetVersion = cronetVersion;
|
||||
this.clientVersion = clientVersion;
|
||||
this.canLogin = canLogin;
|
||||
this.requiresAuth = requiresAuth;
|
||||
this.useAuth = useAuth;
|
||||
this.friendlyName = friendlyName;
|
||||
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
if (androidSdkVersion == null) {
|
||||
// Convert version from '18.2.22C152' into '18_2_22'
|
||||
String userAgentOsVersion = osVersion
|
||||
.replaceAll("(\\d+\\.\\d+\\.\\d+).*", "$1")
|
||||
.replace(".", "_");
|
||||
// https://github.com/mitmproxy/mitmproxy/issues/4836
|
||||
this.userAgent = String.format("%s/%s (%s; U; CPU iOS %s like Mac OS X; %s)",
|
||||
packageName,
|
||||
clientVersion,
|
||||
deviceModel,
|
||||
userAgentOsVersion,
|
||||
defaultLocale
|
||||
);
|
||||
} else {
|
||||
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
|
||||
packageName,
|
||||
clientVersion,
|
||||
osVersion,
|
||||
defaultLocale,
|
||||
deviceModel,
|
||||
Objects.requireNonNull(buildId),
|
||||
Objects.requireNonNull(cronetVersion)
|
||||
);
|
||||
}
|
||||
Logger.printDebug(() -> "userAgent: " + this.userAgent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.extension.shared.spoof;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -17,6 +18,9 @@ import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
|
||||
public class SpoofVideoStreamsPatch {
|
||||
private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get();
|
||||
|
||||
private static final boolean FIX_HLS_CURRENT_TIME = SPOOF_STREAMING_DATA
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
|
||||
/**
|
||||
* Any unreachable ip address. Used to intentionally fail requests.
|
||||
*/
|
||||
@@ -30,15 +34,10 @@ public class SpoofVideoStreamsPatch {
|
||||
return false; // Modified during patching.
|
||||
}
|
||||
|
||||
public static final class NotSpoofingAndroidAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (SpoofVideoStreamsPatch.isPatchIncluded()) {
|
||||
return !BaseSettings.SPOOF_VIDEO_STREAMS.get();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static boolean notSpoofingToAndroid() {
|
||||
return !isPatchIncluded()
|
||||
|| !BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
|| BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,9 +77,9 @@ public class SpoofVideoStreamsPatch {
|
||||
String path = originalUri.getPath();
|
||||
|
||||
if (path != null && path.contains("initplayback")) {
|
||||
Logger.printDebug(() -> "Blocking 'initplayback' by returning unreachable url");
|
||||
Logger.printDebug(() -> "Blocking 'initplayback' by clearing query");
|
||||
|
||||
return UNREACHABLE_HOST_URI_STRING;
|
||||
return originalUri.buildUpon().clearQuery().build().toString();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockInitPlaybackRequest failure", ex);
|
||||
@@ -97,6 +96,17 @@ public class SpoofVideoStreamsPatch {
|
||||
return SPOOF_STREAMING_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Only invoked when playing a livestream on an iOS client.
|
||||
*/
|
||||
public static boolean fixHLSCurrentTime(boolean original) {
|
||||
if (!SPOOF_STREAMING_DATA) {
|
||||
return original;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@@ -105,20 +115,27 @@ public class SpoofVideoStreamsPatch {
|
||||
try {
|
||||
Uri uri = Uri.parse(url);
|
||||
String path = uri.getPath();
|
||||
if (path == null || !path.contains("player")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 'get_drm_license' has no video id and appears to happen when waiting for a paid video to start.
|
||||
// 'heartbeat' has no video id and appears to be only after playback has started.
|
||||
// 'refresh' has no video id and appears to happen when waiting for a livestream to start.
|
||||
if (path != null && path.contains("player") && !path.contains("heartbeat")
|
||||
&& !path.contains("refresh")) {
|
||||
String id = uri.getQueryParameter("id");
|
||||
if (id == null) {
|
||||
Logger.printException(() -> "Ignoring request that has no video id." +
|
||||
" Url: " + url + " headers: " + requestHeaders);
|
||||
return;
|
||||
}
|
||||
|
||||
StreamingDataRequest.fetchRequest(id, requestHeaders);
|
||||
// 'ad_break' has no video id.
|
||||
if (path.contains("get_drm_license") || path.contains("heartbeat")
|
||||
|| path.contains("refresh") || path.contains("ad_break")) {
|
||||
Logger.printDebug(() -> "Ignoring path: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
String id = uri.getQueryParameter("id");
|
||||
if (id == null) {
|
||||
Logger.printException(() -> "Ignoring request with no id: " + url);
|
||||
return;
|
||||
}
|
||||
|
||||
StreamingDataRequest.fetchRequest(id, requestHeaders);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "buildRequest failure", ex);
|
||||
}
|
||||
@@ -183,4 +200,38 @@ public class SpoofVideoStreamsPatch {
|
||||
|
||||
return postData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static String appendSpoofedClient(String videoFormat) {
|
||||
try {
|
||||
if (SPOOF_STREAMING_DATA && BaseSettings.SPOOF_STREAMING_DATA_STATS_FOR_NERDS.get()
|
||||
&& !TextUtils.isEmpty(videoFormat)) {
|
||||
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages.
|
||||
return "\u202D" + videoFormat + "\u2009(" // u202D = left to right override
|
||||
+ StreamingDataRequest.getLastSpoofedClientName() + ")";
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "appendSpoofedClient failure", ex);
|
||||
}
|
||||
|
||||
return videoFormat;
|
||||
}
|
||||
|
||||
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SpoofiOSAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.Locale;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.requests.Requester;
|
||||
@@ -30,27 +31,39 @@ final class PlayerRoutes {
|
||||
private PlayerRoutes() {
|
||||
}
|
||||
|
||||
static String createInnertubeBody(ClientType clientType) {
|
||||
static String createInnertubeBody(ClientType clientType, String videoId) {
|
||||
JSONObject innerTubeBody = new JSONObject();
|
||||
|
||||
try {
|
||||
JSONObject context = new JSONObject();
|
||||
|
||||
// Can override default language only if no login is used.
|
||||
// Could use preferred audio for all clients that do not login,
|
||||
// but if this is a fall over client it will set the language even though
|
||||
// the audio language is not selectable in the UI.
|
||||
ClientType userSelectedClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
Locale streamLocale = userSelectedClient == ClientType.ANDROID_VR_NO_AUTH
|
||||
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getLocale()
|
||||
: Locale.getDefault();
|
||||
|
||||
JSONObject client = new JSONObject();
|
||||
client.put("hl", BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getIso639_1());
|
||||
client.put("deviceMake", clientType.deviceMake);
|
||||
client.put("deviceModel", clientType.deviceModel);
|
||||
client.put("clientName", clientType.clientName);
|
||||
client.put("clientVersion", clientType.clientVersion);
|
||||
client.put("deviceModel", clientType.deviceModel);
|
||||
client.put("osName", clientType.osName);
|
||||
client.put("osVersion", clientType.osVersion);
|
||||
if (clientType.androidSdkVersion != null) {
|
||||
client.put("androidSdkVersion", clientType.androidSdkVersion);
|
||||
}
|
||||
client.put("hl", streamLocale.getLanguage());
|
||||
client.put("gl", streamLocale.getCountry());
|
||||
context.put("client", client);
|
||||
|
||||
innerTubeBody.put("context", context);
|
||||
innerTubeBody.put("contentCheckOk", true);
|
||||
innerTubeBody.put("racyCheckOk", true);
|
||||
innerTubeBody.put("videoId", "%s");
|
||||
innerTubeBody.put("videoId", videoId);
|
||||
} catch (JSONException e) {
|
||||
Logger.printException(() -> "Failed to create innerTubeBody", e);
|
||||
}
|
||||
@@ -66,6 +79,9 @@ final class PlayerRoutes {
|
||||
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("User-Agent", clientType.userAgent);
|
||||
// Not a typo. "Client-Name" uses the client type id.
|
||||
connection.setRequestProperty("X-YouTube-Client-Name", String.valueOf(clientType.id));
|
||||
connection.setRequestProperty("X-YouTube-Client-Version", clientType.clientVersion);
|
||||
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoOutput(true);
|
||||
|
||||
@@ -35,21 +35,41 @@ import app.revanced.extension.shared.spoof.ClientType;
|
||||
*/
|
||||
public class StreamingDataRequest {
|
||||
|
||||
private static final ClientType[] CLIENT_ORDER_TO_USE = ClientType.values();
|
||||
private static final ClientType[] CLIENT_ORDER_TO_USE;
|
||||
|
||||
static {
|
||||
ClientType[] allClientTypes = ClientType.values();
|
||||
ClientType preferredClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
|
||||
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
|
||||
CLIENT_ORDER_TO_USE[0] = preferredClient;
|
||||
|
||||
int i = 1;
|
||||
for (ClientType c : allClientTypes) {
|
||||
if (c != preferredClient) {
|
||||
CLIENT_ORDER_TO_USE[i++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
private static final String[] REQUEST_HEADER_KEYS = {
|
||||
AUTHORIZATION_HEADER, // Available only to logged-in users.
|
||||
"X-GOOG-API-FORMAT-VERSION",
|
||||
"X-Goog-Visitor-Id"
|
||||
};
|
||||
|
||||
/**
|
||||
* TCP connection and HTTP read timeout.
|
||||
*/
|
||||
private static final int HTTP_TIMEOUT_MILLISECONDS = 10 * 1000;
|
||||
|
||||
/**
|
||||
* Any arbitrarily large value, but must be at least twice {@link #HTTP_TIMEOUT_MILLISECONDS}
|
||||
*/
|
||||
private static final int MAX_MILLISECONDS_TO_WAIT_FOR_FETCH = 20 * 1000;
|
||||
|
||||
private static final Map<String, StreamingDataRequest> cache = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>(100) {
|
||||
/**
|
||||
@@ -67,7 +87,15 @@ public class StreamingDataRequest {
|
||||
}
|
||||
});
|
||||
|
||||
private static volatile ClientType lastSpoofedClientType;
|
||||
|
||||
public static String getLastSpoofedClientName() {
|
||||
ClientType client = lastSpoofedClientType;
|
||||
return client == null ? "Unknown" : client.friendlyName;
|
||||
}
|
||||
|
||||
private final String videoId;
|
||||
|
||||
private final Future<ByteBuffer> future;
|
||||
|
||||
private StreamingDataRequest(String videoId, Map<String, String> playerHeaders) {
|
||||
@@ -92,7 +120,8 @@ public class StreamingDataRequest {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static HttpURLConnection send(ClientType clientType, String videoId,
|
||||
private static HttpURLConnection send(ClientType clientType,
|
||||
String videoId,
|
||||
Map<String, String> playerHeaders,
|
||||
boolean showErrorToasts) {
|
||||
Objects.requireNonNull(clientType);
|
||||
@@ -100,21 +129,24 @@ public class StreamingDataRequest {
|
||||
Objects.requireNonNull(playerHeaders);
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
Logger.printDebug(() -> "Fetching video streams for: " + videoId + " using client: " + clientType);
|
||||
|
||||
try {
|
||||
HttpURLConnection connection = PlayerRoutes.getPlayerResponseConnectionFromRoute(GET_STREAMING_DATA, clientType);
|
||||
connection.setConnectTimeout(HTTP_TIMEOUT_MILLISECONDS);
|
||||
connection.setReadTimeout(HTTP_TIMEOUT_MILLISECONDS);
|
||||
|
||||
boolean authHeadersIncludes = false;
|
||||
|
||||
for (String key : REQUEST_HEADER_KEYS) {
|
||||
String value = playerHeaders.get(key);
|
||||
|
||||
if (value != null) {
|
||||
if (key.equals(AUTHORIZATION_HEADER)) {
|
||||
if (!clientType.canLogin) {
|
||||
if (!clientType.useAuth) {
|
||||
Logger.printDebug(() -> "Not including request header: " + key);
|
||||
continue;
|
||||
}
|
||||
authHeadersIncludes = true;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Including request header: " + key);
|
||||
@@ -122,7 +154,15 @@ public class StreamingDataRequest {
|
||||
}
|
||||
}
|
||||
|
||||
String innerTubeBody = String.format(PlayerRoutes.createInnertubeBody(clientType), videoId);
|
||||
if (!authHeadersIncludes && clientType.requiresAuth) {
|
||||
Logger.printDebug(() -> "Skipping client since user is not logged in: " + clientType
|
||||
+ " videoId: " + videoId);
|
||||
return null;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Fetching video streams for: " + videoId + " using client: " + clientType);
|
||||
|
||||
String innerTubeBody = PlayerRoutes.createInnertubeBody(clientType, videoId);
|
||||
byte[] requestBody = innerTubeBody.getBytes(StandardCharsets.UTF_8);
|
||||
connection.setFixedLengthStreamingMode(requestBody.length);
|
||||
connection.getOutputStream().write(requestBody);
|
||||
@@ -154,7 +194,7 @@ public class StreamingDataRequest {
|
||||
// Retry with different client if empty response body is received.
|
||||
int i = 0;
|
||||
for (ClientType clientType : CLIENT_ORDER_TO_USE) {
|
||||
// Show an error if the last client type fails, or if the debug is enabled then show for all attempts.
|
||||
// Show an error if the last client type fails, or if debug is enabled then show for all attempts.
|
||||
final boolean showErrorToast = (++i == CLIENT_ORDER_TO_USE.length) || debugEnabled;
|
||||
|
||||
HttpURLConnection connection = send(clientType, videoId, playerHeaders, showErrorToast);
|
||||
@@ -163,7 +203,9 @@ public class StreamingDataRequest {
|
||||
// gzip encoding doesn't response with content length (-1),
|
||||
// but empty response body does.
|
||||
if (connection.getContentLength() == 0) {
|
||||
Logger.printDebug(() -> "Received empty response for client: " + clientType);
|
||||
if (BaseSettings.DEBUG.get() && BaseSettings.DEBUG_TOAST_ON_ERROR.get()) {
|
||||
Utils.showToastShort("Ignoring empty spoof stream client: " + clientType);
|
||||
}
|
||||
} else {
|
||||
try (InputStream inputStream = new BufferedInputStream(connection.getInputStream());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
@@ -173,6 +215,7 @@ public class StreamingDataRequest {
|
||||
while ((bytesRead = inputStream.read(buffer)) >= 0) {
|
||||
baos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
lastSpoofedClientType = clientType;
|
||||
|
||||
return ByteBuffer.wrap(baos.toByteArray());
|
||||
}
|
||||
@@ -183,7 +226,8 @@ public class StreamingDataRequest {
|
||||
}
|
||||
}
|
||||
|
||||
handleConnectionError("Could not fetch any client streams", null, debugEnabled);
|
||||
lastSpoofedClientType = null;
|
||||
handleConnectionError("Could not fetch any client streams", null, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,4 +90,12 @@ public class ThemeHelper {
|
||||
public static int getForegroundColor() {
|
||||
return isDarkTheme() ? getLightThemeColor() : getDarkThemeColor();
|
||||
}
|
||||
|
||||
public static int getToolbarBackgroundColor() {
|
||||
final String colorName = isDarkTheme()
|
||||
? "yt_black3"
|
||||
: "yt_white1";
|
||||
|
||||
return getColorInt(colorName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,14 +176,13 @@ public final class AlternativeThumbnailsPatch {
|
||||
// Unknown tab, treat as the home tab;
|
||||
return homeOption;
|
||||
}
|
||||
if (selectedNavButton == NavigationButton.HOME) {
|
||||
return homeOption;
|
||||
}
|
||||
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS || selectedNavButton == NavigationButton.NOTIFICATIONS) {
|
||||
return subscriptionsOption;
|
||||
}
|
||||
// A library tab variant is active.
|
||||
return libraryOption;
|
||||
|
||||
return switch (selectedNavButton) {
|
||||
case SUBSCRIPTIONS, NOTIFICATIONS -> subscriptionsOption;
|
||||
case LIBRARY -> libraryOption;
|
||||
// Home or explore tab.
|
||||
default -> homeOption;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ChangeFormFactorPatch {
|
||||
|
||||
public enum FormFactor {
|
||||
/**
|
||||
* Unmodified, and same as un-patched.
|
||||
*/
|
||||
DEFAULT(null),
|
||||
/**
|
||||
* <pre>
|
||||
* Some changes include:
|
||||
* - Explore tab is present.
|
||||
* - watch history is missing.
|
||||
* - feed thumbnails fade in.
|
||||
*/
|
||||
UNKNOWN(0),
|
||||
SMALL(1),
|
||||
LARGE(2),
|
||||
/**
|
||||
* Cars with 'Google built-in'.
|
||||
* Layout seems identical to {@link #UNKNOWN}
|
||||
* even when using an Android Automotive device.
|
||||
*/
|
||||
AUTOMOTIVE(3),
|
||||
WEARABLE(4);
|
||||
|
||||
@Nullable
|
||||
final Integer formFactorType;
|
||||
|
||||
FormFactor(@Nullable Integer formFactorType) {
|
||||
this.formFactorType = formFactorType;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static final Integer FORM_FACTOR_TYPE = Settings.CHANGE_FORM_FACTOR.get().formFactorType;
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int getFormFactor(int original) {
|
||||
return FORM_FACTOR_TYPE == null
|
||||
? original
|
||||
: FORM_FACTOR_TYPE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DisableHdrPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean disableHDRVideo() {
|
||||
return !Settings.DISABLE_HDR_VIDEO.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,23 @@ import app.revanced.extension.shared.settings.BaseSettings;
|
||||
@SuppressWarnings("unused")
|
||||
public final class EnableDebuggingPatch {
|
||||
|
||||
private static final ConcurrentMap<Long, Boolean> featureFlags
|
||||
= new ConcurrentHashMap<>(300, 0.75f, 1);
|
||||
/**
|
||||
* Only log if debugging is enabled on startup.
|
||||
* This prevents enabling debugging
|
||||
* while the app is running then failing to restart
|
||||
* resulting in an incomplete log.
|
||||
*/
|
||||
private static final boolean LOG_FEATURE_FLAGS = BaseSettings.DEBUG.get();
|
||||
|
||||
private static final ConcurrentMap<Long, Boolean> featureFlags = LOG_FEATURE_FLAGS
|
||||
? new ConcurrentHashMap<>(800, 0.5f, 1)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isBooleanFeatureFlagEnabled(boolean value, long flag) {
|
||||
if (value && BaseSettings.DEBUG.get()) {
|
||||
if (LOG_FEATURE_FLAGS && value) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
Logger.printDebug(() -> "boolean feature is enabled: " + flag);
|
||||
}
|
||||
@@ -29,7 +38,7 @@ public final class EnableDebuggingPatch {
|
||||
* Injection point.
|
||||
*/
|
||||
public static double isDoubleFeatureFlagEnabled(double value, long flag, double defaultValue) {
|
||||
if (defaultValue != value && BaseSettings.DEBUG.get()) {
|
||||
if (LOG_FEATURE_FLAGS && defaultValue != value) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
// Align the log outputs to make post processing easier.
|
||||
Logger.printDebug(() -> " double feature is enabled: " + flag
|
||||
@@ -44,7 +53,7 @@ public final class EnableDebuggingPatch {
|
||||
* Injection point.
|
||||
*/
|
||||
public static long isLongFeatureFlagEnabled(long value, long flag, long defaultValue) {
|
||||
if (defaultValue != value && BaseSettings.DEBUG.get()) {
|
||||
if (LOG_FEATURE_FLAGS && defaultValue != value) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
Logger.printDebug(() -> " long feature is enabled: " + flag
|
||||
+ " value: " + value + (defaultValue == 0 ? "" : " default: " + defaultValue));
|
||||
@@ -58,7 +67,7 @@ public final class EnableDebuggingPatch {
|
||||
* Injection point.
|
||||
*/
|
||||
public static String isStringFeatureFlagEnabled(String value, long flag, String defaultValue) {
|
||||
if (BaseSettings.DEBUG.get() && !defaultValue.equals(value)) {
|
||||
if (LOG_FEATURE_FLAGS && !defaultValue.equals(value)) {
|
||||
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||
Logger.printDebug(() -> " string feature is enabled: " + flag
|
||||
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ExitFullscreenPatch {
|
||||
|
||||
public enum FullscreenMode {
|
||||
DISABLED,
|
||||
PORTRAIT,
|
||||
LANDSCAPE,
|
||||
PORTRAIT_LANDSCAPE,
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void endOfVideoReached() {
|
||||
try {
|
||||
FullscreenMode mode = Settings.EXIT_FULLSCREEN.get();
|
||||
if (mode == FullscreenMode.DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerType.getCurrent() == PlayerType.WATCH_WHILE_FULLSCREEN) {
|
||||
if (mode != FullscreenMode.PORTRAIT_LANDSCAPE) {
|
||||
if (Utils.isLandscapeOrientation()) {
|
||||
if (mode == FullscreenMode.PORTRAIT) {
|
||||
return;
|
||||
}
|
||||
} else if (mode == FullscreenMode.LANDSCAPE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user cold launches the app and plays a video but does not
|
||||
// tap to show the overlay controls, the fullscreen button is not
|
||||
// set because the overlay controls are not attached.
|
||||
// To fix this, push the perform click to the back fo the main thread,
|
||||
// and by then the overlay controls will be visible since the video is now finished.
|
||||
Utils.runOnMainThread(() -> {
|
||||
ImageView button = PlayerControlsPatch.fullscreenButtonRef.get();
|
||||
if (button == null) {
|
||||
Logger.printDebug(() -> "Fullscreen button is null, cannot click");
|
||||
} else {
|
||||
Logger.printDebug(() -> "Clicking fullscreen button");
|
||||
final boolean soundEffectsEnabled = button.isSoundEffectsEnabled();
|
||||
button.setSoundEffectsEnabled(false);
|
||||
button.performClick();
|
||||
button.setSoundEffectsEnabled(soundEffectsEnabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "endOfVideoReached failure", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class FixPlaybackSpeedWhilePlayingPatch {
|
||||
|
||||
private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f;
|
||||
|
||||
public static boolean playbackSpeedChanged(float playbackSpeed) {
|
||||
if (playbackSpeed == DEFAULT_YOUTUBE_PLAYBACK_SPEED &&
|
||||
PlayerType.getCurrent().isMaximizedOrFullscreen()) {
|
||||
|
||||
Logger.printDebug(() -> "Blocking call to change playback speed to 1.0x");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -8,6 +10,20 @@ public class ForceOriginalAudioPatch {
|
||||
|
||||
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
|
||||
|
||||
/**
|
||||
* If the conditions to use this patch were present when the app launched.
|
||||
*/
|
||||
public static boolean PATCH_AVAILABLE = SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
|
||||
public static final class ForceOriginalAudioAvailability implements Setting.Availability {
|
||||
@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 PATCH_AVAILABLE && SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
|
||||
@@ -4,15 +4,30 @@ import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PlayerControlsPatch {
|
||||
|
||||
public static WeakReference<ImageView> fullscreenButtonRef = new WeakReference<>(null);
|
||||
|
||||
private static boolean fullscreenButtonVisibilityCallbacksExist() {
|
||||
return false; // Modified during patching if needed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setFullscreenCloseButton(ImageView imageButton) {
|
||||
fullscreenButtonRef = new WeakReference<>(imageButton);
|
||||
Logger.printDebug(() -> "Fullscreen button set");
|
||||
|
||||
if (!fullscreenButtonVisibilityCallbacksExist()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a global listener, since the protected method
|
||||
// View#onVisibilityChanged() does not have any call backs.
|
||||
imageButton.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@@ -39,7 +54,7 @@ public class PlayerControlsPatch {
|
||||
}
|
||||
|
||||
// noinspection EmptyMethod
|
||||
public static void fullscreenButtonVisibilityChanged(boolean isVisible) {
|
||||
private static void fullscreenButtonVisibilityChanged(boolean isVisible) {
|
||||
// Code added during patching.
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class TabletLayoutPatch {
|
||||
|
||||
private static final boolean TABLET_LAYOUT_ENABLED = Settings.TABLET_LAYOUT.get();
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getTabletLayoutEnabled() {
|
||||
return TABLET_LAYOUT_ENABLED;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,9 @@ public final class AdsFilter extends Filter {
|
||||
private final StringFilterGroup playerShoppingShelf;
|
||||
private final ByteArrayFilterGroup playerShoppingShelfBuffer;
|
||||
|
||||
private final StringFilterGroup fullscreenOverlay;
|
||||
private final ByteArrayFilterGroup endScreenStoreBannerBuffer;
|
||||
|
||||
private final StringFilterGroup channelProfile;
|
||||
private final ByteArrayFilterGroup visitStoreButton;
|
||||
|
||||
@@ -112,11 +115,6 @@ public final class AdsFilter extends Filter {
|
||||
"expandable_list"
|
||||
);
|
||||
|
||||
channelProfile = new StringFilterGroup(
|
||||
null,
|
||||
"channel_profile.eml"
|
||||
);
|
||||
|
||||
playerShoppingShelf = new StringFilterGroup(
|
||||
null,
|
||||
"horizontal_shelf.eml"
|
||||
@@ -127,6 +125,21 @@ public final class AdsFilter extends Filter {
|
||||
"shopping_item_card_list.eml"
|
||||
);
|
||||
|
||||
fullscreenOverlay = new StringFilterGroup(
|
||||
Settings.HIDE_END_SCREEN_STORE_BANNER,
|
||||
"fullscreen_overlay.eml"
|
||||
);
|
||||
|
||||
endScreenStoreBannerBuffer = new ByteArrayFilterGroup(
|
||||
null,
|
||||
"gstatic.com/shopping"
|
||||
);
|
||||
|
||||
channelProfile = new StringFilterGroup(
|
||||
null,
|
||||
"channel_profile.eml"
|
||||
);
|
||||
|
||||
visitStoreButton = new ByteArrayFilterGroup(
|
||||
Settings.HIDE_VISIT_STORE_BUTTON,
|
||||
"header_store_button"
|
||||
@@ -154,6 +167,7 @@ public final class AdsFilter extends Filter {
|
||||
viewProducts,
|
||||
selfSponsor,
|
||||
fullscreenAd,
|
||||
fullscreenOverlay,
|
||||
channelProfile,
|
||||
webLinkPanel,
|
||||
shoppingLinks,
|
||||
@@ -172,6 +186,13 @@ public final class AdsFilter extends Filter {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchedGroup == fullscreenOverlay) {
|
||||
if (contentIndex == 0 && endScreenStoreBannerBuffer.check(protobufBufferArray).isFiltered()) {
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exceptions.matches(path))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -45,6 +45,11 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
"transcript_section"
|
||||
);
|
||||
|
||||
final StringFilterGroup howThisWasMadeSection = new StringFilterGroup(
|
||||
Settings.HIDE_HOW_THIS_WAS_MADE_SECTION,
|
||||
"how_this_was_made_section"
|
||||
);
|
||||
|
||||
macroMarkersCarousel = new StringFilterGroup(
|
||||
null,
|
||||
"macro_markers_carousel.eml"
|
||||
@@ -64,6 +69,7 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
addPathCallbacks(
|
||||
attributesSection,
|
||||
infoCardsSection,
|
||||
howThisWasMadeSection,
|
||||
podcastSection,
|
||||
transcriptSection,
|
||||
macroMarkersCarousel
|
||||
|
||||
@@ -528,14 +528,13 @@ final class KeywordContentFilter extends Filter {
|
||||
if (selectedNavButton == null) {
|
||||
return hideHome; // Unknown tab, treat the same as home.
|
||||
}
|
||||
if (selectedNavButton == NavigationButton.HOME) {
|
||||
return hideHome;
|
||||
}
|
||||
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) {
|
||||
return hideSubscriptions;
|
||||
}
|
||||
// User is in the Library or Notifications tab.
|
||||
return false;
|
||||
|
||||
return switch (selectedNavButton) {
|
||||
case HOME, EXPLORE -> hideHome;
|
||||
case SUBSCRIPTIONS -> hideSubscriptions;
|
||||
// User is in the Library or notifications.
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private void updateStats(boolean videoWasHidden, @Nullable String keyword) {
|
||||
|
||||
@@ -80,7 +80,8 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"images_post_root_slim.eml",
|
||||
"text_post_root_slim.eml",
|
||||
"post_base_wrapper_slim.eml",
|
||||
"poll_post_root.eml"
|
||||
"poll_post_root.eml",
|
||||
"videos_post_root.eml"
|
||||
);
|
||||
|
||||
final var communityGuidelines = new StringFilterGroup(
|
||||
@@ -106,7 +107,8 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
inFeedSurvey = new StringFilterGroup(
|
||||
Settings.HIDE_FEED_SURVEY,
|
||||
"in_feed_survey",
|
||||
"slimline_survey"
|
||||
"slimline_survey",
|
||||
"feed_nudge"
|
||||
);
|
||||
|
||||
final var medicalPanel = new StringFilterGroup(
|
||||
@@ -161,9 +163,9 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"inline_expander"
|
||||
);
|
||||
|
||||
final var channelBar = new StringFilterGroup(
|
||||
final var compactChannelBar = new StringFilterGroup(
|
||||
Settings.HIDE_CHANNEL_BAR,
|
||||
"channel_bar"
|
||||
"compact_channel_bar"
|
||||
);
|
||||
|
||||
final var relatedVideos = new StringFilterGroup(
|
||||
@@ -252,7 +254,7 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
inFeedSurvey,
|
||||
notifyMe,
|
||||
likeSubscribeGlow,
|
||||
channelBar,
|
||||
compactChannelBar,
|
||||
communityPosts,
|
||||
paidPromotion,
|
||||
searchResultVideo,
|
||||
|
||||
@@ -297,7 +297,7 @@ public final class ShortsFilter extends Filter {
|
||||
if (matchedGroup == suggestedAction) {
|
||||
// Skip searching the buffer if all suggested actions are set to hidden.
|
||||
// This has a secondary effect of hiding all new un-identified actions
|
||||
// under the assumption that the user wants all actions hidden.
|
||||
// under the assumption that the user wants all suggestions hidden.
|
||||
if (isEverySuggestedActionFilterEnabled()) {
|
||||
return super.isFiltered(path, identifier, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||
}
|
||||
@@ -324,19 +324,22 @@ public final class ShortsFilter extends Filter {
|
||||
}
|
||||
|
||||
private static boolean shouldHideShortsFeedItems() {
|
||||
// Known issue if hide home is on but at least one other hide is off:
|
||||
//
|
||||
// Shorts suggestions will load in the background if a video is opened and
|
||||
// immediately minimized before any suggestions are loaded.
|
||||
// In this state the player type will show minimized, which cannot
|
||||
// distinguish between Shorts suggestions loading in the player and between
|
||||
// scrolling thru search/home/subscription tabs while a player is minimized.
|
||||
final boolean hideHome = Settings.HIDE_SHORTS_HOME.get();
|
||||
final boolean hideSubscriptions = Settings.HIDE_SHORTS_SUBSCRIPTIONS.get();
|
||||
final boolean hideSearch = Settings.HIDE_SHORTS_SEARCH.get();
|
||||
final boolean hideHistory = Settings.HIDE_SHORTS_HISTORY.get();
|
||||
|
||||
if (hideHome && hideSubscriptions && hideSearch) {
|
||||
// Shorts suggestions can load in the background if a video is opened and
|
||||
// then immediately minimized before any suggestions are loaded.
|
||||
// In this state the player type will show minimized, which makes it not possible to
|
||||
// distinguish between Shorts suggestions loading in the player and between
|
||||
// scrolling thru search/home/subscription tabs while a player is minimized.
|
||||
//
|
||||
// To avoid this situation for users that never want to show Shorts (all hide Shorts options are enabled)
|
||||
// then hide all Shorts everywhere including the Library history and Library playlists.
|
||||
if (!hideHome && !hideSubscriptions && !hideSearch && !hideHistory) {
|
||||
return false;
|
||||
}
|
||||
if (hideHome && hideSubscriptions && hideSearch && hideHistory) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -352,24 +355,29 @@ public final class ShortsFilter extends Filter {
|
||||
}
|
||||
|
||||
// Avoid checking navigation button status if all other Shorts should show.
|
||||
if (!hideHome && !hideSubscriptions) {
|
||||
if (!hideHome && !hideSubscriptions && !hideHistory) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check navigation absolutely last since the check may block this thread.
|
||||
NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton();
|
||||
if (selectedNavButton == null) {
|
||||
return hideHome; // Unknown tab, treat the same as home.
|
||||
}
|
||||
if (selectedNavButton == NavigationButton.HOME) {
|
||||
return hideHome;
|
||||
}
|
||||
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) {
|
||||
return hideSubscriptions;
|
||||
}
|
||||
// User must be in the library tab. Don't hide the history or any playlists here.
|
||||
return false;
|
||||
|
||||
return switch (selectedNavButton) {
|
||||
case HOME, EXPLORE -> hideHome;
|
||||
case SUBSCRIPTIONS -> hideSubscriptions;
|
||||
case LIBRARY -> hideHistory;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. Only used if patching older than 19.03.
|
||||
* This hook may be obsolete even for old versions
|
||||
* as they now use a litho layout like newer versions.
|
||||
*/
|
||||
public static void hideShortsShelf(final View shortsShelfView) {
|
||||
if (shouldHideShortsFeedItems()) {
|
||||
Utils.hideViewByLayoutParams(shortsShelfView);
|
||||
|
||||
@@ -32,6 +32,11 @@ public class CustomPlaybackSpeedPatch {
|
||||
*/
|
||||
public static final float PLAYBACK_SPEED_MAXIMUM = 8;
|
||||
|
||||
/**
|
||||
* Tap and hold speed.
|
||||
*/
|
||||
private static final float TAP_AND_HOLD_SPEED;
|
||||
|
||||
/**
|
||||
* Custom playback speeds.
|
||||
*/
|
||||
@@ -48,12 +53,27 @@ public class CustomPlaybackSpeedPatch {
|
||||
private static String[] preferenceListEntries, preferenceListEntryValues;
|
||||
|
||||
static {
|
||||
final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get();
|
||||
if (holdSpeed > 0 && holdSpeed <= PLAYBACK_SPEED_MAXIMUM) {
|
||||
TAP_AND_HOLD_SPEED = holdSpeed;
|
||||
} else {
|
||||
showInvalidCustomSpeedToast();
|
||||
Settings.SPEED_TAP_AND_HOLD.resetToDefault();
|
||||
TAP_AND_HOLD_SPEED = Settings.SPEED_TAP_AND_HOLD.get();
|
||||
}
|
||||
|
||||
loadCustomSpeeds();
|
||||
}
|
||||
|
||||
private static void resetCustomSpeeds(@NonNull String toastMessage) {
|
||||
Utils.showToastLong(toastMessage);
|
||||
Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static float tapAndHoldSpeed() {
|
||||
return TAP_AND_HOLD_SPEED;
|
||||
}
|
||||
|
||||
private static void showInvalidCustomSpeedToast() {
|
||||
Utils.showToastLong(str("revanced_custom_playback_speeds_invalid", PLAYBACK_SPEED_MAXIMUM));
|
||||
}
|
||||
|
||||
private static void loadCustomSpeeds() {
|
||||
@@ -74,17 +94,18 @@ public class CustomPlaybackSpeedPatch {
|
||||
}
|
||||
|
||||
if (speedFloat >= PLAYBACK_SPEED_MAXIMUM) {
|
||||
resetCustomSpeeds(str("revanced_custom_playback_speeds_invalid", PLAYBACK_SPEED_MAXIMUM));
|
||||
showInvalidCustomSpeedToast();
|
||||
Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
|
||||
loadCustomSpeeds();
|
||||
return;
|
||||
}
|
||||
|
||||
customPlaybackSpeeds[i] = speedFloat;
|
||||
i++;
|
||||
customPlaybackSpeeds[i++] = speedFloat;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printInfo(() -> "parse error", ex);
|
||||
resetCustomSpeeds(str("revanced_custom_playback_speeds_parse_exception"));
|
||||
Utils.showToastLong(str("revanced_custom_playback_speeds_parse_exception"));
|
||||
Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
|
||||
loadCustomSpeeds();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ public final class SeekbarColorPatch {
|
||||
|
||||
private static final boolean SEEKBAR_CUSTOM_COLOR_ENABLED = Settings.SEEKBAR_CUSTOM_COLOR.get();
|
||||
|
||||
private static final boolean HIDE_SEEKBAR_THUMBNAIL_ENABLED = Settings.HIDE_SEEKBAR_THUMBNAIL.get();
|
||||
|
||||
/**
|
||||
* Default color of the litho seekbar.
|
||||
* Differs slightly from the default custom seekbar color setting.
|
||||
@@ -25,14 +27,19 @@ public final class SeekbarColorPatch {
|
||||
private static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000;
|
||||
|
||||
/**
|
||||
* Default colors of the gradient seekbar.
|
||||
* Feed default colors of the gradient seekbar.
|
||||
*/
|
||||
private static final int[] ORIGINAL_SEEKBAR_GRADIENT_COLORS = { 0xFFFF0033, 0xFFFF2791 };
|
||||
private static final int[] FEED_ORIGINAL_SEEKBAR_GRADIENT_COLORS = { 0xFFFF0033, 0xFFFF2791 };
|
||||
|
||||
/**
|
||||
* Default positions of the gradient seekbar.
|
||||
* Feed default positions of the gradient seekbar.
|
||||
*/
|
||||
private static final float[] ORIGINAL_SEEKBAR_GRADIENT_POSITIONS = { 0.8f, 1.0f };
|
||||
private static final float[] FEED_ORIGINAL_SEEKBAR_GRADIENT_POSITIONS = { 0.8f, 1.0f };
|
||||
|
||||
/**
|
||||
* Empty seekbar gradient, if hide seekbar in feed is enabled.
|
||||
*/
|
||||
private static final int[] HIDDEN_SEEKBAR_GRADIENT_COLORS = { 0x0, 0x0 };
|
||||
|
||||
/**
|
||||
* Default YouTube seekbar color brightness.
|
||||
@@ -41,16 +48,21 @@ public final class SeekbarColorPatch {
|
||||
|
||||
/**
|
||||
* If {@link Settings#SEEKBAR_CUSTOM_COLOR} is enabled,
|
||||
* this is the color value of {@link Settings#SEEKBAR_CUSTOM_COLOR_VALUE}.
|
||||
* this is the color value of {@link Settings#SEEKBAR_CUSTOM_COLOR_PRIMARY}.
|
||||
* Otherwise this is {@link #ORIGINAL_SEEKBAR_COLOR}.
|
||||
*/
|
||||
private static int seekbarColor = ORIGINAL_SEEKBAR_COLOR;
|
||||
private static int customSeekbarColor = ORIGINAL_SEEKBAR_COLOR;
|
||||
|
||||
/**
|
||||
* Custom seekbar hue, saturation, and brightness values.
|
||||
*/
|
||||
private static final float[] customSeekbarColorHSV = new float[3];
|
||||
|
||||
/**
|
||||
* Custom seekbar color, used for linear gradient replacements.
|
||||
*/
|
||||
private static final int[] customSeekbarColorGradient = new int[2];
|
||||
|
||||
static {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(ORIGINAL_SEEKBAR_COLOR, hsv);
|
||||
@@ -63,26 +75,22 @@ public final class SeekbarColorPatch {
|
||||
|
||||
private static void loadCustomSeekbarColor() {
|
||||
try {
|
||||
seekbarColor = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_VALUE.get());
|
||||
Color.colorToHSV(seekbarColor, customSeekbarColorHSV);
|
||||
customSeekbarColor = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.get());
|
||||
Color.colorToHSV(customSeekbarColor, customSeekbarColorHSV);
|
||||
|
||||
customSeekbarColorGradient[0] = customSeekbarColor;
|
||||
customSeekbarColorGradient[1] = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_ACCENT.get());
|
||||
} catch (Exception ex) {
|
||||
Utils.showToastShort(str("revanced_seekbar_custom_color_invalid"));
|
||||
Settings.SEEKBAR_CUSTOM_COLOR_VALUE.resetToDefault();
|
||||
Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.resetToDefault();
|
||||
Settings.SEEKBAR_CUSTOM_COLOR_ACCENT.resetToDefault();
|
||||
|
||||
loadCustomSeekbarColor();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getSeekbarColor() {
|
||||
return seekbarColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean playerSeekbarGradientEnabled(boolean original) {
|
||||
if (SEEKBAR_CUSTOM_COLOR_ENABLED) return false;
|
||||
|
||||
return original;
|
||||
return customSeekbarColor;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,7 +134,7 @@ public final class SeekbarColorPatch {
|
||||
// Even if the seekbar color xml value is changed to a completely different color (such as green),
|
||||
// a color filter still cannot be selectively applied when the drawable has more than 1 color.
|
||||
try {
|
||||
String seekbarStyle = get9BitStyleIdentifier(seekbarColor);
|
||||
String seekbarStyle = get9BitStyleIdentifier(customSeekbarColor);
|
||||
Logger.printDebug(() -> "Using splash seekbar style: " + seekbarStyle);
|
||||
|
||||
final int styleIdentifierDefault = Utils.getResourceIdentifier(
|
||||
@@ -146,6 +154,13 @@ public final class SeekbarColorPatch {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean showWatchHistoryProgressDrawable(boolean original) {
|
||||
return !HIDE_SEEKBAR_THUMBNAIL_ENABLED && original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
@@ -156,35 +171,61 @@ public final class SeekbarColorPatch {
|
||||
*/
|
||||
public static int getLithoColor(int colorValue) {
|
||||
if (colorValue == ORIGINAL_SEEKBAR_COLOR) {
|
||||
if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) {
|
||||
return 0x00000000;
|
||||
if (HIDE_SEEKBAR_THUMBNAIL_ENABLED) {
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
return getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR);
|
||||
return customSeekbarColor;
|
||||
}
|
||||
|
||||
return colorValue;
|
||||
}
|
||||
|
||||
private static String colorArrayToHex(int[] colors) {
|
||||
final int length = colors.length;
|
||||
StringBuilder builder = new StringBuilder(length * 12);
|
||||
builder.append("[");
|
||||
|
||||
int i = 0;
|
||||
for (int color : colors) {
|
||||
builder.append(String.format("#%X", color));
|
||||
if (++i < length) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setLinearGradient(int[] colors, float[] positions) {
|
||||
final boolean hideSeekbar = Settings.HIDE_SEEKBAR_THUMBNAIL.get();
|
||||
public static int[] getPlayerLinearGradient(int[] original) {
|
||||
return SEEKBAR_CUSTOM_COLOR_ENABLED
|
||||
? customSeekbarColorGradient
|
||||
: original;
|
||||
}
|
||||
|
||||
if (SEEKBAR_CUSTOM_COLOR_ENABLED || hideSeekbar) {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int[] getLithoLinearGradient(int[] colors, float[] positions) {
|
||||
if (SEEKBAR_CUSTOM_COLOR_ENABLED || HIDE_SEEKBAR_THUMBNAIL_ENABLED) {
|
||||
// Most litho usage of linear gradients is hooked here,
|
||||
// so must only change if the values are those for the seekbar.
|
||||
if (Arrays.equals(ORIGINAL_SEEKBAR_GRADIENT_COLORS, colors)
|
||||
&& Arrays.equals(ORIGINAL_SEEKBAR_GRADIENT_POSITIONS, positions)) {
|
||||
Arrays.fill(colors, hideSeekbar
|
||||
? 0x00000000
|
||||
: seekbarColor);
|
||||
return;
|
||||
if ((Arrays.equals(FEED_ORIGINAL_SEEKBAR_GRADIENT_COLORS, colors)
|
||||
&& Arrays.equals(FEED_ORIGINAL_SEEKBAR_GRADIENT_POSITIONS, positions))) {
|
||||
return HIDE_SEEKBAR_THUMBNAIL_ENABLED
|
||||
? HIDDEN_SEEKBAR_GRADIENT_COLORS
|
||||
: customSeekbarColorGradient;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Ignoring gradient colors: " + Arrays.toString(colors)
|
||||
Logger.printDebug(() -> "Ignoring gradient colors: " + colorArrayToHex(colors)
|
||||
+ " positions: " + Arrays.toString(positions));
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +239,7 @@ public final class SeekbarColorPatch {
|
||||
}
|
||||
|
||||
return colorValue == ORIGINAL_SEEKBAR_COLOR
|
||||
? getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR)
|
||||
? customSeekbarColor
|
||||
: colorValue;
|
||||
}
|
||||
|
||||
@@ -208,11 +249,9 @@ public final class SeekbarColorPatch {
|
||||
* Overrides color used for the video player seekbar.
|
||||
*/
|
||||
public static int getVideoPlayerSeekbarColor(int originalColor) {
|
||||
if (!SEEKBAR_CUSTOM_COLOR_ENABLED) {
|
||||
return originalColor;
|
||||
}
|
||||
|
||||
return getSeekbarColorValue(originalColor);
|
||||
return SEEKBAR_CUSTOM_COLOR_ENABLED
|
||||
? getSeekbarColorValue(originalColor)
|
||||
: originalColor;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,10 +260,6 @@ public final class SeekbarColorPatch {
|
||||
*/
|
||||
private static int getSeekbarColorValue(int originalColor) {
|
||||
try {
|
||||
if (!SEEKBAR_CUSTOM_COLOR_ENABLED || originalColor == seekbarColor) {
|
||||
return originalColor; // nothing to do
|
||||
}
|
||||
|
||||
final int alphaDifference = Color.alpha(originalColor) - Color.alpha(ORIGINAL_SEEKBAR_COLOR);
|
||||
|
||||
// The seekbar uses the same color but different brightness for different situations.
|
||||
@@ -237,7 +272,7 @@ public final class SeekbarColorPatch {
|
||||
hsv[1] = customSeekbarColorHSV[1];
|
||||
hsv[2] = clamp(customSeekbarColorHSV[2] + brightnessDifference, 0, 1);
|
||||
|
||||
final int replacementAlpha = clamp(Color.alpha(seekbarColor) + alphaDifference, 0, 255);
|
||||
final int replacementAlpha = clamp(Color.alpha(customSeekbarColor) + alphaDifference, 0, 255);
|
||||
final int replacementColor = Color.HSVToColor(replacementAlpha, hsv);
|
||||
Logger.printDebug(() -> String.format("Original color: #%08X replacement color: #%08X",
|
||||
originalColor, replacementColor));
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
package app.revanced.extension.youtube.settings;
|
||||
|
||||
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.ImageButton;
|
||||
import android.widget.TextView;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.ThemeHelper;
|
||||
import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.preference.ReturnYouTubeDislikePreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.preference.SponsorBlockPreferenceFragment;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.getChildView;
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
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.settings.preference.ReVancedPreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.preference.ReturnYouTubeDislikePreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.preference.SponsorBlockPreferenceFragment;
|
||||
|
||||
/**
|
||||
* Hooks LicenseActivity.
|
||||
@@ -25,17 +34,57 @@ import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
@SuppressWarnings("unused")
|
||||
public class LicenseActivityHook {
|
||||
|
||||
private static ViewGroup.LayoutParams toolbarLayoutParams;
|
||||
|
||||
public static void setToolbarLayoutParams(Toolbar toolbar) {
|
||||
if (toolbarLayoutParams != null) {
|
||||
toolbar.setLayoutParams(toolbarLayoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Overrides the ReVanced settings language.
|
||||
*/
|
||||
public static Context getAttachBaseContext(Context original) {
|
||||
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
|
||||
if (language == AppLanguage.DEFAULT) {
|
||||
return original;
|
||||
}
|
||||
|
||||
return Utils.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean useCairoSettingsFragment(boolean original) {
|
||||
// Early targets have layout issues and it's better to always force off.
|
||||
if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
|
||||
return false;
|
||||
}
|
||||
if (Settings.RESTORE_OLD_SETTINGS_MENUS.get()) {
|
||||
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.
|
||||
// 19.34+ cairo settings are always on, so it doesn't need to be forced anyway.
|
||||
// Cairo setting will show on the next launch of the app.
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* <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);
|
||||
licenseActivity.setContentView(
|
||||
getResourceIdentifier("revanced_settings_with_toolbar", "layout"));
|
||||
setBackButton(licenseActivity);
|
||||
licenseActivity.setContentView(getResourceIdentifier(
|
||||
"revanced_settings_with_toolbar", "layout"));
|
||||
|
||||
PreferenceFragment fragment;
|
||||
String toolbarTitleResourceName;
|
||||
@@ -58,7 +107,7 @@ public class LicenseActivityHook {
|
||||
return;
|
||||
}
|
||||
|
||||
setToolbarTitle(licenseActivity, toolbarTitleResourceName);
|
||||
createToolbar(licenseActivity, toolbarTitleResourceName);
|
||||
|
||||
//noinspection deprecation
|
||||
licenseActivity.getFragmentManager()
|
||||
@@ -70,28 +119,36 @@ public class LicenseActivityHook {
|
||||
}
|
||||
}
|
||||
|
||||
private static void setToolbarTitle(Activity activity, String toolbarTitleResourceName) {
|
||||
ViewGroup toolbar = activity.findViewById(getToolbarResourceId());
|
||||
TextView toolbarTextView = Objects.requireNonNull(getChildView(toolbar, false,
|
||||
view -> view instanceof TextView));
|
||||
toolbarTextView.setText(getResourceIdentifier(toolbarTitleResourceName, "string"));
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private static void setBackButton(Activity activity) {
|
||||
ViewGroup toolbar = activity.findViewById(getToolbarResourceId());
|
||||
ImageButton imageButton = Objects.requireNonNull(getChildView(toolbar, false,
|
||||
view -> view instanceof ImageButton));
|
||||
imageButton.setImageDrawable(ReVancedPreferenceFragment.getBackButtonDrawable());
|
||||
imageButton.setOnClickListener(view -> activity.onBackPressed());
|
||||
}
|
||||
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"));
|
||||
toolbarLayoutParams = dummyToolbar.getLayoutParams();
|
||||
toolBarParent.removeView(dummyToolbar);
|
||||
|
||||
private static int getToolbarResourceId() {
|
||||
final int toolbarResourceId = getResourceIdentifier("revanced_toolbar", "id");
|
||||
if (toolbarResourceId == 0) {
|
||||
throw new IllegalStateException("Could not find back button resource");
|
||||
Toolbar toolbar = new Toolbar(toolBarParent.getContext());
|
||||
toolbar.setBackgroundColor(ThemeHelper.getToolbarBackgroundColor());
|
||||
toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable());
|
||||
toolbar.setNavigationOnClickListener(view -> activity.onBackPressed());
|
||||
toolbar.setTitle(getResourceIdentifier(toolbarTitleResourceName, "string"));
|
||||
|
||||
final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
|
||||
Utils.getContext().getResources().getDisplayMetrics());
|
||||
toolbar.setTitleMarginStart(margin);
|
||||
toolbar.setTitleMarginEnd(margin);
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar, false,
|
||||
view -> view instanceof TextView);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(ThemeHelper.getForegroundColor());
|
||||
}
|
||||
return toolbarResourceId;
|
||||
setToolbarLayoutParams(toolbar);
|
||||
|
||||
toolBarParent.addView(toolbar, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ import static app.revanced.extension.shared.settings.Setting.migrateFromOldPrefe
|
||||
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;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.NotSpoofingAndroidAvailability;
|
||||
import static app.revanced.extension.youtube.patches.ChangeFormFactorPatch.FormFactor;
|
||||
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;
|
||||
@@ -25,6 +27,8 @@ import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehavi
|
||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
|
||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY_ONCE;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
@@ -43,21 +47,24 @@ 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);
|
||||
// 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);
|
||||
public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE);
|
||||
public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f);
|
||||
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
|
||||
"0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true);
|
||||
// Audio
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new NotSpoofingAndroidAvailability());
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new ForceOriginalAudioAvailability());
|
||||
|
||||
// Ads
|
||||
public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE);
|
||||
public static final BooleanSetting HIDE_END_SCREEN_STORE_BANNER = new BooleanSetting("revanced_hide_end_screen_store_banner", FALSE);
|
||||
public static final BooleanSetting HIDE_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", TRUE);
|
||||
public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE);
|
||||
public static final BooleanSetting HIDE_GET_PREMIUM = new BooleanSetting("revanced_hide_get_premium", TRUE);
|
||||
@@ -120,6 +127,7 @@ public class Settings extends BaseSettings {
|
||||
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);
|
||||
public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_hide_cast_button", TRUE, true);
|
||||
@@ -139,10 +147,10 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_SUBSCRIBERS_COMMUNITY_GUIDELINES = new BooleanSetting("revanced_hide_subscribers_community_guidelines", TRUE);
|
||||
public static final BooleanSetting HIDE_TIMED_REACTIONS = new BooleanSetting("revanced_hide_timed_reactions", TRUE);
|
||||
public static final BooleanSetting HIDE_VIDEO_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE);
|
||||
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
||||
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
|
||||
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true);
|
||||
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
|
||||
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
||||
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true);
|
||||
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
|
||||
// Miniplayer
|
||||
public static final EnumSetting<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.DEFAULT, true);
|
||||
private static final Availability MINIPLAYER_ANY_MODERN = MINIPLAYER_TYPE.availability(MODERN_1, MODERN_2, MODERN_3, MODERN_4);
|
||||
@@ -171,6 +179,7 @@ public class Settings extends BaseSettings {
|
||||
// Description
|
||||
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);
|
||||
public static final BooleanSetting HIDE_INFO_CARDS_SECTION = new BooleanSetting("revanced_hide_info_cards_section", TRUE);
|
||||
public static final BooleanSetting HIDE_KEY_CONCEPTS_SECTION = new BooleanSetting("revanced_hide_key_concepts_section", FALSE);
|
||||
public static final BooleanSetting HIDE_PODCAST_SECTION = new BooleanSetting("revanced_hide_podcast_section", TRUE);
|
||||
@@ -200,15 +209,16 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_WATCH_IN_VR = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
|
||||
|
||||
// General layout
|
||||
public static final BooleanSetting RESTORE_OLD_SETTINGS_MENUS = new BooleanSetting("revanced_restore_old_settings_menus", FALSE, true);
|
||||
public static final EnumSetting<FormFactor> CHANGE_FORM_FACTOR = new EnumSetting<>("revanced_change_form_factor", FormFactor.DEFAULT, true, "revanced_change_form_factor_user_dialog_message");
|
||||
public static final BooleanSetting BYPASS_IMAGE_REGION_RESTRICTIONS = new BooleanSetting("revanced_bypass_image_region_restrictions", FALSE, true);
|
||||
public static final BooleanSetting GRADIENT_LOADING_SCREEN = new BooleanSetting("revanced_gradient_loading_screen", FALSE, true);
|
||||
public static final BooleanSetting REMOVE_VIEWER_DISCRETION_DIALOG = new BooleanSetting("revanced_remove_viewer_discretion_dialog", FALSE,
|
||||
"revanced_remove_viewer_discretion_dialog_user_dialog_message");
|
||||
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 TABLET_LAYOUT = new BooleanSetting("revanced_tablet_layout", FALSE, true, "revanced_tablet_layout_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.35.36" : "17.33.42", true, parent(SPOOF_APP_VERSION));
|
||||
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));
|
||||
// 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));
|
||||
@@ -233,6 +243,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_SHORTS_FULL_VIDEO_LINK_LABEL = new BooleanSetting("revanced_hide_shorts_full_video_link_label", FALSE);
|
||||
public static final BooleanSetting HIDE_SHORTS_GREEN_SCREEN_BUTTON = new BooleanSetting("revanced_hide_shorts_green_screen_button", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_HASHTAG_BUTTON = new BooleanSetting("revanced_hide_shorts_hashtag_button", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_HISTORY = new BooleanSetting("revanced_hide_shorts_history", FALSE);
|
||||
public static final BooleanSetting HIDE_SHORTS_HOME = new BooleanSetting("revanced_hide_shorts_home", FALSE);
|
||||
public static final BooleanSetting HIDE_SHORTS_INFO_PANEL = new BooleanSetting("revanced_hide_shorts_info_panel", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_JOIN_BUTTON = new BooleanSetting("revanced_hide_shorts_join_button", TRUE);
|
||||
@@ -261,18 +272,19 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting SHORTS_AUTOPLAY_BACKGROUND = new BooleanSetting("revanced_shorts_autoplay_background", TRUE);
|
||||
|
||||
// Seekbar
|
||||
|
||||
public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", TRUE);
|
||||
public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", FALSE);
|
||||
public static final BooleanSetting HIDE_SEEKBAR = new BooleanSetting("revanced_hide_seekbar", FALSE, true);
|
||||
public static final BooleanSetting HIDE_SEEKBAR_THUMBNAIL = new BooleanSetting("revanced_hide_seekbar_thumbnail", FALSE);
|
||||
public static final BooleanSetting HIDE_SEEKBAR_THUMBNAIL = new BooleanSetting("revanced_hide_seekbar_thumbnail", FALSE, true);
|
||||
public static final BooleanSetting HIDE_TIMESTAMP = new BooleanSetting("revanced_hide_timestamp", FALSE);
|
||||
public static final BooleanSetting RESTORE_OLD_SEEKBAR_THUMBNAILS = new BooleanSetting("revanced_restore_old_seekbar_thumbnails", TRUE);
|
||||
public static final BooleanSetting SEEKBAR_CUSTOM_COLOR = new BooleanSetting("revanced_seekbar_custom_color", FALSE, true);
|
||||
public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", TRUE);
|
||||
public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", FALSE);
|
||||
public static final BooleanSetting SEEKBAR_THUMBNAILS_HIGH_QUALITY = new BooleanSetting("revanced_seekbar_thumbnails_high_quality", FALSE, true,
|
||||
"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 StringSetting SEEKBAR_CUSTOM_COLOR_VALUE = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033", true, parent(SEEKBAR_CUSTOM_COLOR));
|
||||
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));
|
||||
|
||||
// Misc
|
||||
public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE);
|
||||
@@ -293,8 +305,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting DEBUG_PROTOBUFFER = new BooleanSetting("revanced_debug_protobuffer", FALSE, parent(BaseSettings.DEBUG));
|
||||
|
||||
// Swipe controls
|
||||
public static final BooleanSetting SWIPE_BRIGHTNESS = new BooleanSetting("revanced_swipe_brightness", TRUE);
|
||||
public static final BooleanSetting SWIPE_VOLUME = new BooleanSetting("revanced_swipe_volume", TRUE);
|
||||
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_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,
|
||||
@@ -399,6 +412,30 @@ public class Settings extends BaseSettings {
|
||||
MINIPLAYER_TYPE.save(MINIMAL);
|
||||
}
|
||||
|
||||
// Migrate old single color seekbar with a slightly brighter accent color based on the primary.
|
||||
// Eventually delete this logic.
|
||||
if (!DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.isSetToDefault()) {
|
||||
try {
|
||||
String oldPrimaryColorString = DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.get();
|
||||
final int oldPrimaryColor = Color.parseColor(oldPrimaryColorString);
|
||||
SEEKBAR_CUSTOM_COLOR_PRIMARY.save(oldPrimaryColorString);
|
||||
|
||||
final float brightnessScale = 1.3f;
|
||||
final int accentColor = Color.argb(
|
||||
0, // Save without alpha channel.
|
||||
Math.min(255, (int) (brightnessScale * Color.red(oldPrimaryColor))),
|
||||
Math.min(255, (int) (brightnessScale * Color.green(oldPrimaryColor))),
|
||||
Math.min(255, (int) (brightnessScale * Color.blue(oldPrimaryColor)))
|
||||
);
|
||||
|
||||
SEEKBAR_CUSTOM_COLOR_ACCENT.save(String.format("#%06X", accentColor));
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Could not parse old seekbar color", ex);
|
||||
}
|
||||
|
||||
DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.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.youtube.patches.ForceOriginalAudioPatch;
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class ForceOriginalAudioSwitchPreference extends SwitchPreference {
|
||||
|
||||
{
|
||||
if (!ForceOriginalAudioPatch.PATCH_AVAILABLE) {
|
||||
// Show why force audio is not available.
|
||||
String summary = str("revanced_force_original_audio_not_available");
|
||||
setSummary(summary);
|
||||
setSummaryOn(summary);
|
||||
setSummaryOff(summary);
|
||||
}
|
||||
}
|
||||
|
||||
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
public ForceOriginalAudioSwitchPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,12 @@ import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.EnumSetting;
|
||||
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
|
||||
import app.revanced.extension.youtube.ThemeHelper;
|
||||
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||
import app.revanced.extension.youtube.settings.LicenseActivityHook;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
@@ -109,15 +112,20 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
CustomPlaybackSpeedPatch.initializeListPreference(playbackPreference);
|
||||
}
|
||||
|
||||
preference = findPreference(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE.key);
|
||||
if (preference instanceof ListPreference languagePreference) {
|
||||
sortListPreferenceByValues(languagePreference, 1);
|
||||
}
|
||||
sortPreferenceListMenu(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE);
|
||||
sortPreferenceListMenu(BaseSettings.REVANCED_LANGUAGE);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initialize failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void sortPreferenceListMenu(EnumSetting<?> setting) {
|
||||
Preference preference = findPreference(setting.key);
|
||||
if (preference instanceof ListPreference languagePreference) {
|
||||
sortListPreferenceByValues(languagePreference, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferenceScreenToolbar(PreferenceScreen parentScreen) {
|
||||
for (int i = 0, preferenceCount = parentScreen.getPreferenceCount(); i < preferenceCount; i++) {
|
||||
Preference childPreference = parentScreen.getPreference(i);
|
||||
@@ -133,9 +141,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
.getParent();
|
||||
|
||||
// Fix required for Android 15 and YT 19.45+
|
||||
// FIXME:
|
||||
// On Android 15 the text layout is not aligned the same as the parent
|
||||
// screen and it looks a little off. Otherwise this works.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
|
||||
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
|
||||
@@ -162,6 +167,8 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
toolbarTextView.setTextColor(ThemeHelper.getForegroundColor());
|
||||
}
|
||||
|
||||
LicenseActivityHook.setToolbarLayoutParams(toolbar);
|
||||
|
||||
rootView.addView(toolbar, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
|
||||
@Nullable
|
||||
private ClientType currentClientType;
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||
// Because this listener may run before the ReVanced settings fragment updates Settings,
|
||||
// this could show the prior config and not the current.
|
||||
//
|
||||
// Push this call to the end of the main run queue,
|
||||
// so all other listeners are done and Settings is up to date.
|
||||
Utils.runOnMainThread(this::updateUI);
|
||||
};
|
||||
|
||||
public SpoofStreamingDataSideEffectsPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public SpoofStreamingDataSideEffectsPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public SpoofStreamingDataSideEffectsPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SpoofStreamingDataSideEffectsPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private void addChangeListener() {
|
||||
Setting.preferences.preferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
private void removeChangeListener() {
|
||||
Setting.preferences.preferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
|
||||
super.onAttachedToHierarchy(preferenceManager);
|
||||
updateUI();
|
||||
addChangeListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareForRemoval() {
|
||||
super.onPrepareForRemoval();
|
||||
removeChangeListener();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
ClientType clientType = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
if (currentClientType == clientType) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
||||
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
||||
|
||||
String key = "revanced_spoof_video_streams_about_" +
|
||||
(clientType == ClientType.IOS_UNPLUGGED
|
||||
? "ios_tv"
|
||||
: "android");
|
||||
String title = str(key + "_title");
|
||||
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) {
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
|
||||
}
|
||||
|
||||
setTitle(title);
|
||||
setSummary(summary);
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,15 @@ 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.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -54,20 +57,21 @@ public final class NavigationBar {
|
||||
* How long to wait for the set nav button latch to be released. Maximum wait time must
|
||||
* be as small as possible while still allowing enough time for the nav bar to update.
|
||||
*
|
||||
* YT calls it's back button handlers out of order,
|
||||
* and litho starts filtering before the navigation bar is updated.
|
||||
* YT calls it's back button handlers out of order, and litho starts filtering before the
|
||||
* navigation bar is updated. Fixing this situation and not needlessly waiting requires
|
||||
* somehow detecting if a back button key/gesture will not change the active tab.
|
||||
*
|
||||
* Fixing this situation and not needlessly waiting requires somehow
|
||||
* detecting if a back button key-press will cause a tab change.
|
||||
* On average the time between pressing the back button and the first litho event is
|
||||
* about 10-20ms. Waiting up to 75-150ms should be enough time to handle normal use cases
|
||||
* and not be noticeable, since YT typically takes 100-200ms (or more) to update the view.
|
||||
*
|
||||
* Typically after pressing the back button, the time between the first litho event and
|
||||
* when the nav button is updated is about 10-20ms. Using 50-100ms here should be enough time
|
||||
* and not noticeable, since YT typically takes 100-200ms (or more) to update the view anyways.
|
||||
* This delay is only noticeable when the device back button/gesture will not
|
||||
* change the current navigation tab, such as backing out of the watch history.
|
||||
*
|
||||
* This issue can also be avoided on a patch by patch basis, by avoiding calls to
|
||||
* {@link NavigationButton#getSelectedNavigationButton()} unless absolutely necessary.
|
||||
*/
|
||||
private static final long LATCH_AWAIT_TIMEOUT_MILLISECONDS = 75;
|
||||
private static final long LATCH_AWAIT_TIMEOUT_MILLISECONDS = 120;
|
||||
|
||||
/**
|
||||
* Used as a workaround to fix the issue of YT calling back button handlers out of order.
|
||||
@@ -113,7 +117,8 @@ public final class NavigationBar {
|
||||
// The latch is released from the main thread, and waiting from the main thread will always timeout.
|
||||
// This situation has only been observed when navigating out of a submenu and not changing tabs.
|
||||
// and for that use case the nav bar does not change so it's safe to return here.
|
||||
Logger.printDebug(() -> "Cannot block main thread waiting for nav button. Using last known navbar button status.");
|
||||
Logger.printDebug(() -> "Cannot block main thread waiting for nav button. " +
|
||||
"Using last known navbar button status.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -131,7 +136,9 @@ public final class NavigationBar {
|
||||
Logger.printDebug(() -> "Latch wait timed out");
|
||||
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.printException(() -> "Latch wait interrupted failure", ex); // Will never happen.
|
||||
// Calling YouTube thread was interrupted.
|
||||
Logger.printException(() -> "Latch wait interrupted", ex);
|
||||
Thread.currentThread().interrupt(); // Restore interrupt status flag.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +245,30 @@ public final class NavigationBar {
|
||||
// Code is added during patching.
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the bundled non cairo filled icon instead of a custom icon.
|
||||
* Use the old non cairo filled icon, which is almost identical to
|
||||
* the what would be the filled cairo icon.
|
||||
*/
|
||||
private static final int fillBellCairoBlack = Utils.getResourceIdentifier(
|
||||
"yt_fill_bell_black_24", "drawable");
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// Show a popup informing this fix is no longer needed to those who might care.
|
||||
if (BaseSettings.DEBUG.get() && enumMap.containsKey(tabActivityCairo)) {
|
||||
Logger.printException(() -> "YouTube fixed the cairo notification icons");
|
||||
}
|
||||
enumMap.putIfAbsent(tabActivityCairo, fillBellCairoBlack);
|
||||
}
|
||||
}
|
||||
|
||||
public enum NavigationButton {
|
||||
HOME("PIVOT_HOME", "TAB_HOME_CAIRO"),
|
||||
SHORTS("TAB_SHORTS", "TAB_SHORTS_CAIRO"),
|
||||
@@ -246,6 +277,10 @@ public final class NavigationBar {
|
||||
* This tab will never be in a selected state, even if the create video UI is on screen.
|
||||
*/
|
||||
CREATE("CREATION_TAB_LARGE", "CREATION_TAB_LARGE_CAIRO"),
|
||||
/**
|
||||
* Only shown to automotive layout.
|
||||
*/
|
||||
EXPLORE("TAB_EXPLORE"),
|
||||
SUBSCRIPTIONS("PIVOT_SUBSCRIPTIONS", "TAB_SUBSCRIPTIONS_CAIRO"),
|
||||
/**
|
||||
* Notifications tab. Only present when
|
||||
@@ -283,8 +318,8 @@ public final class NavigationBar {
|
||||
*
|
||||
* All code calling this method should handle a null return value.
|
||||
*
|
||||
* <b>Due to issues with how YT processes physical back button events,
|
||||
* this patch uses workarounds that can cause this method to take up to 75ms
|
||||
* <b>Due to issues with how YT processes physical back button/gesture events,
|
||||
* this patch uses workarounds that can cause this method to take up to 120ms
|
||||
* if the device back button was recently pressed.</b>
|
||||
*
|
||||
* @return The active navigation tab.
|
||||
|
||||
@@ -73,7 +73,7 @@ enum class PlayerType {
|
||||
onChange(currentPlayerType)
|
||||
}
|
||||
|
||||
@Volatile // value is read/write from different threads
|
||||
@Volatile // Read/write from different threads.
|
||||
private var currentPlayerType = NONE
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,7 @@ enum class VideoState {
|
||||
currentVideoState = value
|
||||
}
|
||||
|
||||
@Volatile // Read/write from different threads.
|
||||
private var currentVideoState: VideoState? = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,11 +150,16 @@ public class SBRequester {
|
||||
String end = String.format(Locale.US, TIME_TEMPLATE, endTime / 1000f);
|
||||
String duration = String.format(Locale.US, TIME_TEMPLATE, videoLength / 1000f);
|
||||
|
||||
HttpURLConnection connection = getConnectionFromRoute(SBRoutes.SUBMIT_SEGMENTS, privateUserId, videoId, category, start, end, duration);
|
||||
HttpURLConnection connection = getConnectionFromRoute(SBRoutes.SUBMIT_SEGMENTS,
|
||||
privateUserId, videoId, category, start, end, duration);
|
||||
final int responseCode = connection.getResponseCode();
|
||||
|
||||
String userMessage = switch (responseCode) {
|
||||
case HTTP_STATUS_CODE_SUCCESS -> str("revanced_sb_submit_succeeded");
|
||||
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||
Utils.showToastLong(str("revanced_sb_submit_succeeded"));
|
||||
return;
|
||||
}
|
||||
|
||||
String userErrorMessage = switch (responseCode) {
|
||||
case 409 -> str("revanced_sb_submit_failed_duplicate");
|
||||
case 403 -> str("revanced_sb_submit_failed_forbidden",
|
||||
Requester.parseErrorStringAndDisconnect(connection));
|
||||
@@ -167,7 +172,7 @@ public class SBRequester {
|
||||
|
||||
// Message might be about the users account or an error too large to show in a toast.
|
||||
// Use a dialog instead.
|
||||
SponsorBlockUtils.showErrorDialog(userMessage);
|
||||
SponsorBlockUtils.showErrorDialog(userErrorMessage);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
Logger.printDebug(() -> "Timeout", ex);
|
||||
Utils.showToastLong(str("revanced_sb_submit_failed_timeout"));
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import app.revanced.extension.shared.Logger.printDebug
|
||||
import app.revanced.extension.shared.Logger.printException
|
||||
import app.revanced.extension.youtube.settings.Settings
|
||||
import app.revanced.extension.youtube.shared.PlayerType
|
||||
import app.revanced.extension.youtube.swipecontrols.controller.AudioVolumeController
|
||||
import app.revanced.extension.youtube.swipecontrols.controller.ScreenBrightnessController
|
||||
@@ -232,5 +233,12 @@ class SwipeControlsHostActivity : Activity() {
|
||||
@JvmStatic
|
||||
var currentHost: WeakReference<SwipeControlsHostActivity> = WeakReference(null)
|
||||
private set
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
fun allowSwipeChangeVideo(original: Boolean): Boolean = Settings.SWIPE_CHANGE_VIDEO.get()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.google.protos.youtube.api.innertube;
|
||||
|
||||
public class InnertubeContext$ClientInfo {
|
||||
public int r;
|
||||
}
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.7.0-dev.1
|
||||
version = 5.10.0-dev.5
|
||||
|
||||
@@ -461,10 +461,6 @@ public final class app/revanced/patches/reddit/customclients/joeyforreddit/detec
|
||||
public static final fun getDisablePiracyDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/redditisfun/api/FingerprintsKt {
|
||||
public static final fun baseClientIdFingerprint (Ljava/lang/String;)Lapp/revanced/patcher/Fingerprint;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/redditisfun/api/SpoofClientPatchKt {
|
||||
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -548,7 +544,6 @@ public final class app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentP
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/extension/ExtensionHook {
|
||||
public final fun getFingerprint ()Lapp/revanced/patcher/Fingerprint;
|
||||
public final fun invoke (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
@@ -608,16 +603,19 @@ public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatch
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt {
|
||||
public static final fun settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun settingsPatch (Lkotlin/Pair;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static synthetic fun settingsPatch$default (Lkotlin/Pair;Ljava/util/Set;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static synthetic fun settingsPatch$default (Ljava/util/List;Ljava/util/Set;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public static final field Companion Lapp/revanced/patches/shared/misc/settings/preference/BasePreference$Companion;
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getIcon ()Ljava/lang/String;
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getLayout ()Ljava/lang/String;
|
||||
public final fun getSummaryKey ()Ljava/lang/String;
|
||||
public final fun getTag ()Ljava/lang/String;
|
||||
public final fun getTitleKey ()Ljava/lang/String;
|
||||
@@ -640,17 +638,19 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
|
||||
|
||||
public abstract class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getIcon ()Ljava/lang/String;
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getLayout ()Ljava/lang/String;
|
||||
public final fun getPreferences ()Ljava/util/Set;
|
||||
public final fun getTitleKey ()Ljava/lang/String;
|
||||
public abstract fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||
public final fun getCategories ()Ljava/util/Set;
|
||||
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||
@@ -658,8 +658,8 @@ public class app/revanced/patches/shared/misc/settings/preference/BasePreference
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen$Category : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$BasePreferenceCollection {
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun addPreferences ([Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||
public synthetic fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;
|
||||
public fun transform ()Lapp/revanced/patches/shared/misc/settings/preference/PreferenceCategory;
|
||||
@@ -667,6 +667,7 @@ public class app/revanced/patches/shared/misc/settings/preference/BasePreference
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/InputType : java/lang/Enum {
|
||||
public static final field NUMBER Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
public static final field NUMBER_DECIMAL Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
public static final field TEXT Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
public static final field TEXT_CAP_CHARACTERS Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
public static final field TEXT_MULTI_LINE Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
@@ -677,8 +678,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/InputTyp
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/IntentPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getIntent ()Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
|
||||
public fun hashCode ()I
|
||||
@@ -698,8 +699,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/ListPref
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/util/resource/ArrayResource;Lapp/revanced/util/resource/ArrayResource;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/util/resource/ArrayResource;Lapp/revanced/util/resource/ArrayResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getEntries ()Lapp/revanced/util/resource/ArrayResource;
|
||||
public final fun getEntriesKey ()Ljava/lang/String;
|
||||
public final fun getEntryValues ()Lapp/revanced/util/resource/ArrayResource;
|
||||
@@ -708,22 +709,22 @@ public final class app/revanced/patches/shared/misc/settings/preference/ListPref
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/NonInteractivePreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getSelectable ()Z
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/PreferenceCategory : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getPreferences ()Ljava/util/Set;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
public class app/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getPreferences ()Ljava/util/Set;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
@@ -732,6 +733,7 @@ public final class app/revanced/patches/shared/misc/settings/preference/Preferen
|
||||
public static final field BY_KEY Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
|
||||
public static final field BY_TITLE Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
|
||||
public static final field UNSORTED Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
|
||||
public final fun appendSortType (Ljava/lang/String;)Ljava/lang/String;
|
||||
public static fun getEntries ()Lkotlin/enums/EnumEntries;
|
||||
public final fun getKeySuffix ()Ljava/lang/String;
|
||||
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference$Sorting;
|
||||
@@ -750,8 +752,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/SummaryT
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/SwitchPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getSummaryOffKey ()Ljava/lang/String;
|
||||
public final fun getSummaryOnKey ()Ljava/lang/String;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
@@ -759,8 +761,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/SwitchPr
|
||||
|
||||
public final class app/revanced/patches/shared/misc/settings/preference/TextPreference : app/revanced/patches/shared/misc/settings/preference/BasePreference {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patches/shared/misc/settings/preference/InputType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getInputType ()Lapp/revanced/patches/shared/misc/settings/preference/InputType;
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
@@ -1106,6 +1108,10 @@ public final class app/revanced/patches/youtube/layout/buttons/overlay/HidePlaye
|
||||
public static final fun getHidePlayerOverlayButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatchKt {
|
||||
public static final fun getChangeFormFactorPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatchKt {
|
||||
public static final fun getHideEndscreenCardsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1235,7 +1241,6 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt {
|
||||
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
|
||||
public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -1268,10 +1273,6 @@ public final class app/revanced/patches/youtube/misc/backgroundplayback/Backgrou
|
||||
public static final fun getBackgroundPlaybackPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/check/CheckEnvironmentPatchKt {
|
||||
public static final fun getCheckEnvironmentPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatchKt {
|
||||
public static final fun getEnableDebuggingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1296,6 +1297,10 @@ public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClien
|
||||
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playbackspeed/FIxPlaybackSpeedWhilePlayingPatchKt {
|
||||
public static final fun getFixPlaybackSpeedWhilePlayingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatchKt {
|
||||
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1360,6 +1365,7 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat
|
||||
public static final fun is_19_43_or_greater ()Z
|
||||
public static final fun is_19_46_or_greater ()Z
|
||||
public static final fun is_19_47_or_greater ()Z
|
||||
public static final fun is_19_49_or_greater ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt {
|
||||
@@ -1404,14 +1410,14 @@ public final class app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatc
|
||||
public static final fun getZoomHapticsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/shared/FingerprintsKt {
|
||||
public static final fun getRollingNumberTextViewAnimationUpdateFingerprint ()Lapp/revanced/patcher/Fingerprint;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatchKt {
|
||||
public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/hdr/DisableHdrPatchKt {
|
||||
public static final fun getDisableHdrPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/information/VideoInformationPatchKt {
|
||||
public static final fun getVideoInformationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun userSelectedPlaybackSpeedHook (Ljava/lang/String;Ljava/lang/String;)V
|
||||
@@ -1453,10 +1459,6 @@ public final class app/revanced/patches/youtube/video/speed/button/PlaybackSpeed
|
||||
public static final fun getPlaybackSpeedButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatchKt {
|
||||
public static final fun getSpeedUnavailableId ()J
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/videoid/VideoIdPatchKt {
|
||||
public static final fun getVideoIdPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun hookBackgroundPlayVideoId (Ljava/lang/String;)V
|
||||
|
||||
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
fun baseClientIdFingerprint(string: String) = fingerprint {
|
||||
internal fun baseClientIdFingerprint(string: String) = fingerprint {
|
||||
strings("yyOCBp.RHJhDKd", string)
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ fun sharedExtensionPatch(
|
||||
}
|
||||
|
||||
class ExtensionHook internal constructor(
|
||||
val fingerprint: Fingerprint,
|
||||
private val fingerprint: Fingerprint,
|
||||
private val insertIndexResolver: ((Method) -> Int),
|
||||
private val contextRegisterResolver: (Method) -> String,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.shared.misc.settings
|
||||
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResource
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
@@ -12,15 +13,22 @@ import app.revanced.util.getNode
|
||||
import app.revanced.util.insertFirst
|
||||
import org.w3c.dom.Node
|
||||
|
||||
// TODO: Delete this on next major version bump.
|
||||
@Deprecated("Use non deprecated settings patch function")
|
||||
fun settingsPatch (
|
||||
rootPreference: Pair<IntentPreference, String>,
|
||||
preferences: Set<BasePreference>,
|
||||
) = settingsPatch(listOf(rootPreference), preferences)
|
||||
|
||||
/**
|
||||
* A resource patch that adds settings to a settings fragment.
|
||||
*
|
||||
* @param rootPreference A pair of an intent preference and the name of the fragment file to add it to.
|
||||
* If null, no preference will be added.
|
||||
* @param rootPreferences List of intent preferences and the name of the fragment file to add it to.
|
||||
* File names that do not exist are ignored and not processed.
|
||||
* @param preferences A set of preferences to add to the ReVanced fragment.
|
||||
*/
|
||||
fun settingsPatch(
|
||||
rootPreference: Pair<IntentPreference, String>? = null,
|
||||
fun settingsPatch (
|
||||
rootPreferences: List<Pair<BasePreference, String>>? = null,
|
||||
preferences: Set<BasePreference>,
|
||||
) = resourcePatch {
|
||||
dependsOn(addResourcesPatch)
|
||||
@@ -46,10 +54,20 @@ fun settingsPatch(
|
||||
}
|
||||
|
||||
// Add the root preference to an existing fragment if needed.
|
||||
rootPreference?.let { (intentPreference, fragment) ->
|
||||
document("res/xml/$fragment.xml").use { document ->
|
||||
document.getNode("PreferenceScreen").addPreference(intentPreference, true)
|
||||
rootPreferences?.let {
|
||||
var modified = false
|
||||
|
||||
it.forEach { (intent, fileName) ->
|
||||
val preferenceFileName = "res/xml/$fileName.xml"
|
||||
if (get(preferenceFileName).exists()) {
|
||||
document(preferenceFileName).use { document ->
|
||||
document.getNode("PreferenceScreen").addPreference(intent, true)
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!modified) throw PatchException("No declared preference files exists: $rootPreferences")
|
||||
}
|
||||
|
||||
// Add all preferences to the ReVanced fragment.
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.w3c.dom.Element
|
||||
*
|
||||
* @param key The key of the preference. If null, other parameters must be specified.
|
||||
* @param titleKey The key of the preference title.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param summaryKey The key of the preference summary.
|
||||
* @param tag The tag or full class name of the preference.
|
||||
*/
|
||||
@@ -17,6 +19,8 @@ abstract class BasePreference(
|
||||
val key: String? = null,
|
||||
val titleKey: String = "${key}_title",
|
||||
val summaryKey: String? = "${key}_summary",
|
||||
val icon: String? = null,
|
||||
val layout: String? = null,
|
||||
val tag: String
|
||||
) {
|
||||
/**
|
||||
@@ -33,6 +37,11 @@ abstract class BasePreference(
|
||||
key?.let { setAttribute("android:key", it) }
|
||||
setAttribute("android:title", "@string/${titleKey}")
|
||||
summaryKey?.let { addSummary(it) }
|
||||
icon?.let {
|
||||
setAttribute("android:icon", it)
|
||||
setAttribute("app:iconSpaceReserved", "true")
|
||||
}
|
||||
layout?.let { setAttribute("android:layout", layout) }
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
||||
@@ -24,16 +24,20 @@ abstract class BasePreferenceScreen(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
private val summaryKey: String? = "${key}_summary",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||
val categories: MutableSet<Category> = mutableSetOf(),
|
||||
private val sorting: Sorting = Sorting.BY_TITLE,
|
||||
) : BasePreferenceCollection(key, titleKey, preferences) {
|
||||
) : BasePreferenceCollection(key, titleKey, icon, layout, preferences) {
|
||||
|
||||
override fun transform(): PreferenceScreenPreference {
|
||||
return PreferenceScreenPreference(
|
||||
key,
|
||||
titleKey,
|
||||
summaryKey,
|
||||
icon,
|
||||
layout,
|
||||
sorting,
|
||||
// Screens and preferences are sorted at runtime by extension code,
|
||||
// so title sorting uses the localized language in use.
|
||||
@@ -56,12 +60,17 @@ abstract class BasePreferenceScreen(
|
||||
open inner class Category(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||
) : BasePreferenceCollection(key, titleKey, preferences) {
|
||||
) : BasePreferenceCollection(key, titleKey, icon, layout, preferences) {
|
||||
override fun transform(): PreferenceCategory {
|
||||
return PreferenceCategory(
|
||||
key,
|
||||
titleKey,
|
||||
icon,
|
||||
layout,
|
||||
sorting,
|
||||
preferences = preferences,
|
||||
)
|
||||
}
|
||||
@@ -82,6 +91,8 @@ abstract class BasePreferenceScreen(
|
||||
abstract class BasePreferenceCollection(
|
||||
val key: String? = null,
|
||||
val titleKey: String = "${key}_title",
|
||||
val icon: String? = null,
|
||||
val layout: String? = null,
|
||||
val preferences: MutableSet<BasePreference> = mutableSetOf(),
|
||||
) {
|
||||
abstract fun transform(): BasePreference
|
||||
|
||||
@@ -5,4 +5,5 @@ enum class InputType(val type: String) {
|
||||
TEXT_CAP_CHARACTERS("textCapCharacters"),
|
||||
TEXT_MULTI_LINE("textMultiLine"),
|
||||
NUMBER("number"),
|
||||
NUMBER_DECIMAL("numberDecimal"),
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import org.w3c.dom.Document
|
||||
* @param key Optional preference key.
|
||||
* @param titleKey The preference title key.
|
||||
* @param summaryKey The preference summary key.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The preference tag.
|
||||
* @param intent The intent to open.
|
||||
*/
|
||||
@@ -16,9 +18,11 @@ class IntentPreference(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
tag: String = "Preference",
|
||||
val intent: Intent,
|
||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||
) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
|
||||
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.w3c.dom.Document
|
||||
* @param key The preference key. If null, other parameters must be specified.
|
||||
* @param titleKey The preference title key.
|
||||
* @param summaryKey The preference summary key.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The preference tag.
|
||||
* @param entriesKey The entries array key.
|
||||
* @param entryValuesKey The entry values array key.
|
||||
@@ -19,10 +21,12 @@ class ListPreference(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
tag: String = "ListPreference",
|
||||
val entriesKey: String? = "${key}_entries",
|
||||
val entryValuesKey: String? = "${key}_entry_values"
|
||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||
) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
|
||||
var entries: ArrayResource? = null
|
||||
private set
|
||||
var entryValues: ArrayResource? = null
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.w3c.dom.Document
|
||||
*
|
||||
* @param key The preference key.
|
||||
* @param summaryKey The preference summary key.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The tag or full class name of the preference.
|
||||
* @param selectable If the preference is selectable and responds to tap events.
|
||||
*/
|
||||
@@ -18,9 +20,11 @@ class NonInteractivePreference(
|
||||
key: String,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
tag: String = "Preference",
|
||||
val selectable: Boolean = false,
|
||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||
) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
setAttribute("android:selectable", selectable.toString())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.shared.misc.settings.preference
|
||||
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.util.resource.BaseResource
|
||||
import org.w3c.dom.Document
|
||||
|
||||
@@ -8,6 +9,8 @@ import org.w3c.dom.Document
|
||||
*
|
||||
* @param key The key of the preference. If null, other parameters must be specified.
|
||||
* @param titleKey The key of the preference title.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The tag or full class name of the preference.
|
||||
* @param preferences The preferences in this category.
|
||||
*/
|
||||
@@ -15,9 +18,12 @@ import org.w3c.dom.Document
|
||||
open class PreferenceCategory(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
sorting: Sorting = Sorting.BY_TITLE,
|
||||
tag: String = "PreferenceCategory",
|
||||
val preferences: Set<BasePreference>
|
||||
) : BasePreference(key, titleKey, null, tag) {
|
||||
) : BasePreference(sorting.appendSortType(key), titleKey, null, icon, layout, tag) {
|
||||
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.w3c.dom.Document
|
||||
* @param key The key of the preference. If null, other parameters must be specified.
|
||||
* @param titleKey The key of the preference title.
|
||||
* @param summaryKey The key of the preference summary.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param sorting Sorting to use. If the sorting is not [Sorting.UNSORTED],
|
||||
* then the key parameter will be modified to include the sort type.
|
||||
* @param tag The tag or full class name of the preference.
|
||||
@@ -19,6 +21,8 @@ open class PreferenceScreenPreference(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
sorting: Sorting = Sorting.BY_TITLE,
|
||||
tag: String = "PreferenceScreen",
|
||||
val preferences: Set<BasePreference>,
|
||||
@@ -28,7 +32,7 @@ open class PreferenceScreenPreference(
|
||||
// or adding new attributes to the attrs.xml file.
|
||||
// Since the key value is not currently used by the extensions,
|
||||
// for now it's much simpler to modify the key to include the sort parameter.
|
||||
) : BasePreference(if (sorting == Sorting.UNSORTED) key else (key + sorting.keySuffix), titleKey, summaryKey, tag) {
|
||||
) : BasePreference(sorting.appendSortType(key), titleKey, summaryKey, icon, layout, tag) {
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
preferences.forEach {
|
||||
@@ -53,6 +57,16 @@ open class PreferenceScreenPreference(
|
||||
/**
|
||||
* Unspecified sorting.
|
||||
*/
|
||||
UNSORTED("_sort_by_unsorted"),
|
||||
UNSORTED("_sort_by_unsorted");
|
||||
|
||||
/**
|
||||
* @return The key with this sort type appended to to the end,
|
||||
* or if key is null then null is returned.
|
||||
*/
|
||||
fun appendSortType(key: String?): String? {
|
||||
if (key == null) return null
|
||||
if (this == UNSORTED) return key
|
||||
return key + keySuffix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import org.w3c.dom.Document
|
||||
*
|
||||
* @param key The preference key. If null, other parameters must be specified.
|
||||
* @param titleKey The preference title key.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The preference tag.
|
||||
* @param summaryOnKey The preference summary-on key.
|
||||
* @param summaryOffKey The preference summary-off key.
|
||||
@@ -17,9 +19,11 @@ class SwitchPreference(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
tag: String = "SwitchPreference",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
val summaryOnKey: String = "${key}_summary_on",
|
||||
val summaryOffKey: String = "${key}_summary_off"
|
||||
) : BasePreference(key, titleKey, null, tag) {
|
||||
) : BasePreference(key, titleKey, null, icon, layout, tag) {
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
addSummary(summaryOnKey, SummaryType.ON)
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.w3c.dom.Document
|
||||
* @param key The preference key. If null, other parameters must be specified.
|
||||
* @param titleKey The preference title key.
|
||||
* @param summaryKey The preference summary key.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The preference tag.
|
||||
* @param inputType The preference input type.
|
||||
*/
|
||||
@@ -17,9 +19,11 @@ class TextPreference(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
tag: String = "app.revanced.extension.shared.settings.preference.ResettableEditTextPreference",
|
||||
val inputType: InputType = InputType.TEXT
|
||||
) : BasePreference(key, titleKey, summaryKey, tag) {
|
||||
) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
|
||||
|
||||
override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
|
||||
super.serialize(ownerDocument, resourceCallback).apply {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.shared.misc.spoof
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -111,6 +112,23 @@ internal val buildMediaDataSourceFingerprint = fingerprint {
|
||||
)
|
||||
}
|
||||
|
||||
internal const val HLS_CURRENT_TIME_FEATURE_FLAG = 45355374L
|
||||
|
||||
internal val hlsCurrentTimeFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters("Z", "L")
|
||||
literal {
|
||||
HLS_CURRENT_TIME_FEATURE_FLAG
|
||||
}
|
||||
}
|
||||
|
||||
internal val nerdsStatsVideoFormatBuilderFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters("L")
|
||||
strings("codecs=\"")
|
||||
}
|
||||
|
||||
internal val patchIncludedExtensionMethodFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Z")
|
||||
|
||||
@@ -10,8 +10,10 @@ import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -206,6 +208,34 @@ fun spoofVideoStreamsPatch(
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Append spoof info.
|
||||
|
||||
nerdsStatsVideoFormatBuilderFingerprint.method.apply {
|
||||
findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index ->
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->appendSpoofedClient(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fix iOS livestream current time.
|
||||
|
||||
hlsCurrentTimeFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||
HLS_CURRENT_TIME_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z"
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
executeBlock()
|
||||
|
||||
@@ -37,6 +37,7 @@ private val hideAdsResourcePatch = resourcePatch {
|
||||
|
||||
PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference("revanced_hide_general_ads"),
|
||||
SwitchPreference("revanced_hide_end_screen_store_banner"),
|
||||
SwitchPreference("revanced_hide_fullscreen_ads"),
|
||||
SwitchPreference("revanced_hide_buttoned_ads"),
|
||||
SwitchPreference("revanced_hide_paid_promotion_label"),
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
package app.revanced.patches.youtube.interaction.swipecontrols
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val swipeControlsHostActivityFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters()
|
||||
custom { method, _ ->
|
||||
method.definingClass == "Lapp/revanced/extension/youtube/swipecontrols/SwipeControlsHostActivity;"
|
||||
method.definingClass == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal const val SWIPE_CHANGE_VIDEO_FEATURE_FLAG = 45631116L
|
||||
|
||||
internal val swipeChangeVideoFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters("L")
|
||||
literal {
|
||||
SWIPE_CHANGE_VIDEO_FEATURE_FLAG
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_43_or_greater
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityFingerprint
|
||||
@@ -17,6 +18,8 @@ import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/swipecontrols/SwipeControlsHostActivity;"
|
||||
|
||||
private val swipeControlsResourcePatch = resourcePatch {
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
@@ -26,6 +29,12 @@ private val swipeControlsResourcePatch = resourcePatch {
|
||||
execute {
|
||||
addResources("youtube", "interaction.swipecontrols.swipeControlsResourcePatch")
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
PreferenceScreen.SWIPE_CONTROLS.addPreferences(
|
||||
SwitchPreference("revanced_swipe_change_video")
|
||||
)
|
||||
}
|
||||
|
||||
PreferenceScreen.SWIPE_CONTROLS.addPreferences(
|
||||
SwitchPreference("revanced_swipe_brightness"),
|
||||
SwitchPreference("revanced_swipe_volume"),
|
||||
@@ -101,5 +110,16 @@ val swipeControlsPatch = bytecodePatch(
|
||||
).toMutable()
|
||||
}
|
||||
}
|
||||
|
||||
// region patch to enable/disable swipe to change video.
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
swipeChangeVideoFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||
SWIPE_CHANGE_VIDEO_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->allowSwipeChangeVideo(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +65,12 @@ val navigationButtonsPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
preferences += SwitchPreference("revanced_disable_translucent_status_bar")
|
||||
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_light")
|
||||
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_dark")
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_disable_translucent_status_bar")
|
||||
)
|
||||
}
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package app.revanced.patches.youtube.layout.formfactor
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ChangeFormFactorPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val changeFormFactorPatch = bytecodePatch(
|
||||
name = "Change form factor",
|
||||
description = "Adds an option to change the UI appearance to a phone, tablet, or automotive device.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"18.38.44",
|
||||
"18.49.37",
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "layout.formfactor.changeFormFactorPatch")
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
ListPreference(
|
||||
"revanced_change_form_factor",
|
||||
summaryKey = null,
|
||||
)
|
||||
)
|
||||
|
||||
createPlayerRequestBodyWithModelFingerprint.method.apply {
|
||||
val formFactorEnumClass = formFactorEnumConstructorFingerprint.originalClassDef.type
|
||||
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET &&
|
||||
reference?.definingClass == formFactorEnumClass &&
|
||||
reference.type == "I"
|
||||
}
|
||||
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getFormFactor(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package app.revanced.patches.youtube.layout.formfactor
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
internal val formFactorEnumConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
strings(
|
||||
"UNKNOWN_FORM_FACTOR",
|
||||
"SMALL_FORM_FACTOR",
|
||||
"LARGE_FORM_FACTOR",
|
||||
"AUTOMOTIVE_FORM_FACTOR"
|
||||
)
|
||||
}
|
||||
|
||||
internal val createPlayerRequestBodyWithModelFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters()
|
||||
opcodes(Opcode.OR_INT_LIT16)
|
||||
custom { method, _ ->
|
||||
method.indexOfModelInstruction() >= 0 &&
|
||||
method.indexOfReleaseInstruction() >= 0
|
||||
}
|
||||
}
|
||||
|
||||
private fun Method.indexOfModelInstruction() =
|
||||
indexOfFirstInstruction {
|
||||
val reference = getReference<FieldReference>()
|
||||
|
||||
reference?.definingClass == "Landroid/os/Build;" &&
|
||||
reference.name == "MODEL" &&
|
||||
reference.type == "Ljava/lang/String;"
|
||||
}
|
||||
|
||||
internal fun Method.indexOfReleaseInstruction(): Int =
|
||||
indexOfFirstInstruction {
|
||||
val reference = getReference<FieldReference>()
|
||||
|
||||
reference?.definingClass == "Landroid/os/Build${'$'}VERSION;" &&
|
||||
reference.name == "RELEASE" &&
|
||||
reference.type == "Ljava/lang/String;"
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_hide_attributes_section"),
|
||||
SwitchPreference("revanced_hide_chapters_section"),
|
||||
SwitchPreference("revanced_hide_info_cards_section"),
|
||||
SwitchPreference("revanced_hide_how_this_was_made_section"),
|
||||
SwitchPreference("revanced_hide_key_concepts_section"),
|
||||
SwitchPreference("revanced_hide_podcast_section"),
|
||||
SwitchPreference("revanced_hide_transcript_section"),
|
||||
|
||||
@@ -71,6 +71,7 @@ private val hideShortsComponentsResourcePatch = resourcePatch {
|
||||
SwitchPreference("revanced_hide_shorts_home"),
|
||||
SwitchPreference("revanced_hide_shorts_subscriptions"),
|
||||
SwitchPreference("revanced_hide_shorts_search"),
|
||||
SwitchPreference("revanced_hide_shorts_history"),
|
||||
|
||||
PreferenceScreenPreference(
|
||||
key = "revanced_shorts_player_screen",
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.playerControlsPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.autoRepeatFingerprint
|
||||
import app.revanced.patches.youtube.shared.autoRepeatParentFingerprint
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
|
||||
@Suppress("unused")
|
||||
internal val exitFullscreenPatch = bytecodePatch(
|
||||
name = "Exit fullscreen mode",
|
||||
description = "Adds options to automatically exit fullscreen mode when a video reaches the end."
|
||||
) {
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"18.38.44",
|
||||
"18.49.37",
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
)
|
||||
)
|
||||
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
playerTypeHookPatch,
|
||||
playerControlsPatch
|
||||
)
|
||||
|
||||
// Cannot declare as top level since this patch is in the same package as
|
||||
// other patches that declare same constant name with internal visibility.
|
||||
@Suppress("LocalVariableName")
|
||||
val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/ExitFullscreenPatch;"
|
||||
|
||||
execute {
|
||||
addResources("youtube", "layout.player.fullscreen.exitFullscreenPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
ListPreference(
|
||||
"revanced_exit_fullscreen",
|
||||
summaryKey = null,
|
||||
)
|
||||
)
|
||||
|
||||
autoRepeatFingerprint.match(autoRepeatParentFingerprint.originalClassDef).method.apply {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
implementation!!.instructions.lastIndex,
|
||||
"invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->endOfVideoReached()V",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,17 @@ internal val shortsSeekbarColorFingerprint = fingerprint {
|
||||
literal { reelTimeBarPlayedColorId }
|
||||
}
|
||||
|
||||
internal const val PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG = 45617850L
|
||||
internal val playerSeekbarHandleColorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters("Landroid/content/Context;")
|
||||
literal { ytStaticBrandRedId }
|
||||
}
|
||||
|
||||
internal val playerSeekbarGradientConfigFingerprint = fingerprint {
|
||||
internal val watchHistoryMenuUseProgressDrawableFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
parameters()
|
||||
literal { PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG }
|
||||
returns("V")
|
||||
parameters("L")
|
||||
literal { -1712394514 }
|
||||
}
|
||||
|
||||
internal val lithoLinearGradientFingerprint = fingerprint {
|
||||
@@ -49,6 +53,49 @@ internal val lithoLinearGradientFingerprint = fingerprint {
|
||||
parameters("F", "F", "F", "F", "[I", "[F")
|
||||
}
|
||||
|
||||
/**
|
||||
* 19.49+
|
||||
*/
|
||||
internal val playerLinearGradientFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
parameters("I", "I", "I", "I", "Landroid/content/Context;", "I")
|
||||
returns("Landroid/graphics/LinearGradient;")
|
||||
opcodes(
|
||||
Opcode.FILLED_NEW_ARRAY,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
)
|
||||
literal { ytYoutubeMagentaColorId }
|
||||
}
|
||||
|
||||
/**
|
||||
* 19.46 - 19.47
|
||||
*/
|
||||
internal val playerLinearGradientLegacy1946Fingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters("I", "I", "I", "I")
|
||||
returns("V")
|
||||
opcodes(
|
||||
Opcode.FILLED_NEW_ARRAY,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
)
|
||||
custom { method, _ ->
|
||||
method.name == "setBounds" && method.containsLiteralInstruction(ytYoutubeMagentaColorId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 19.25 - 19.45
|
||||
*/
|
||||
internal val playerLinearGradientLegacy1925Fingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters("Landroid/content/Context;")
|
||||
opcodes(
|
||||
Opcode.FILLED_NEW_ARRAY,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
)
|
||||
literal { ytYoutubeMagentaColorId }
|
||||
}
|
||||
|
||||
internal const val launchScreenLayoutTypeLotteFeatureFlag = 268507948L
|
||||
|
||||
internal val launchScreenLayoutTypeFingerprint = fingerprint {
|
||||
|
||||
@@ -14,7 +14,9 @@ import app.revanced.patches.youtube.layout.theme.lithoColorHookPatch
|
||||
import app.revanced.patches.youtube.layout.theme.lithoColorOverrideHook
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
@@ -39,6 +41,10 @@ internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
|
||||
private set
|
||||
internal var inlineTimeBarPlayedNotHighlightedColorId = -1L
|
||||
private set
|
||||
internal var ytYoutubeMagentaColorId = -1L
|
||||
private set
|
||||
internal var ytStaticBrandRedId = -1L
|
||||
private set
|
||||
|
||||
internal const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color"
|
||||
|
||||
@@ -83,6 +89,15 @@ private val seekbarColorResourcePatch = resourcePatch {
|
||||
return@execute
|
||||
}
|
||||
|
||||
ytYoutubeMagentaColorId = resourceMappings[
|
||||
"color",
|
||||
"yt_youtube_magenta",
|
||||
]
|
||||
ytStaticBrandRedId = resourceMappings[
|
||||
"attr",
|
||||
"ytStaticBrandRed",
|
||||
]
|
||||
|
||||
// Add attribute and styles for splash screen custom color.
|
||||
// Using a style is the only way to selectively change just the seekbar fill color.
|
||||
//
|
||||
@@ -182,28 +197,31 @@ val seekbarColorPatch = bytecodePatch(
|
||||
sharedExtensionPatch,
|
||||
lithoColorHookPatch,
|
||||
seekbarColorResourcePatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
execute {
|
||||
fun MutableMethod.addColorChangeInstructions(resourceId: Long) {
|
||||
val registerIndex = indexOfFirstLiteralInstructionOrThrow(resourceId) + 2
|
||||
val colorRegister = getInstruction<OneRegisterInstruction>(registerIndex).registerA
|
||||
fun MutableMethod.addColorChangeInstructions(resourceId: Long, methodName: String) {
|
||||
val index = indexOfFirstLiteralInstructionOrThrow(resourceId)
|
||||
val insertIndex = indexOfFirstInstructionOrThrow(index, Opcode.MOVE_RESULT)
|
||||
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
registerIndex + 1,
|
||||
insertIndex + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
invoke-static { v$colorRegister }, $EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
|
||||
move-result v$colorRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
playerSeekbarColorFingerprint.method.apply {
|
||||
addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId)
|
||||
addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId)
|
||||
addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId, "getVideoPlayerSeekbarColor")
|
||||
addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId, "getVideoPlayerSeekbarColor")
|
||||
}
|
||||
|
||||
shortsSeekbarColorFingerprint.method.apply {
|
||||
addColorChangeInstructions(reelTimeBarPlayedColorId)
|
||||
addColorChangeInstructions(reelTimeBarPlayedColorId, "getVideoPlayerSeekbarColor")
|
||||
}
|
||||
|
||||
setSeekbarClickedColorFingerprint.originalMethod.let {
|
||||
@@ -229,16 +247,63 @@ val seekbarColorPatch = bytecodePatch(
|
||||
|
||||
// 19.25+ changes
|
||||
|
||||
playerSeekbarGradientConfigFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||
PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z"
|
||||
)
|
||||
playerSeekbarHandleColorFingerprint.method.apply {
|
||||
addColorChangeInstructions(ytStaticBrandRedId, "getVideoPlayerSeekbarColor")
|
||||
}
|
||||
|
||||
lithoLinearGradientFingerprint.method.addInstruction(
|
||||
// If hiding feed seekbar thumbnails, then turn off the cairo gradient
|
||||
// of the watch history menu items as they use the same gradient as the
|
||||
// player and there is no easy way to distinguish which to use a transparent color.
|
||||
if (is_19_34_or_greater) {
|
||||
watchHistoryMenuUseProgressDrawableFingerprint.method.apply {
|
||||
val progressIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass == "Landroid/widget/ProgressBar;" && reference.name == "setMax"
|
||||
}
|
||||
val index = indexOfFirstInstructionOrThrow(progressIndex, Opcode.MOVE_RESULT)
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
lithoLinearGradientFingerprint.method.addInstructions(
|
||||
0,
|
||||
"invoke-static/range { p4 .. p5 }, $EXTENSION_CLASS_DESCRIPTOR->setLinearGradient([I[F)V"
|
||||
"""
|
||||
invoke-static/range { p4 .. p5 }, $EXTENSION_CLASS_DESCRIPTOR->getLithoLinearGradient([I[F)[I
|
||||
move-result-object p4
|
||||
"""
|
||||
)
|
||||
|
||||
val playerFingerprint =
|
||||
if (is_19_49_or_greater) {
|
||||
playerLinearGradientFingerprint
|
||||
} else if (is_19_46_or_greater) {
|
||||
playerLinearGradientLegacy1946Fingerprint
|
||||
} else {
|
||||
playerLinearGradientLegacy1925Fingerprint
|
||||
}
|
||||
|
||||
playerFingerprint.let {
|
||||
it.method.apply {
|
||||
val index = it.patternMatch!!.endIndex
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerLinearGradient([I)[I
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// region apply seekbar custom color to splash screen animation.
|
||||
|
||||
|
||||
@@ -1,66 +1,9 @@
|
||||
package app.revanced.patches.youtube.layout.tablet
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.layout.formfactor.changeFormFactorPatch
|
||||
|
||||
const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/TabletLayoutPatch;"
|
||||
|
||||
val enableTabletLayoutPatch = bytecodePatch(
|
||||
name = "Enable tablet layout",
|
||||
description = "Adds an option to enable tablet layout.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"18.38.44",
|
||||
"18.49.37",
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "layout.tablet.enableTabletLayoutPatch")
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_tablet_layout"),
|
||||
)
|
||||
|
||||
getFormFactorFingerprint.method.apply {
|
||||
val returnIsLargeFormFactorIndex = instructions.lastIndex - 4
|
||||
val returnIsLargeFormFactorLabel = getInstruction(returnIsLargeFormFactorIndex)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getTabletLayoutEnabled()Z
|
||||
move-result v0
|
||||
if-nez v0, :is_large_form_factor
|
||||
""",
|
||||
ExternalLabel(
|
||||
"is_large_form_factor",
|
||||
returnIsLargeFormFactorLabel,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@Deprecated("Use 'Change form factor' instead.")
|
||||
val enableTabletLayoutPatch = bytecodePatch {
|
||||
dependsOn(changeFormFactorPatch)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.tablet
|
||||
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val getFormFactorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("L")
|
||||
parameters("Landroid/content/Context;", "Ljava/util/List;")
|
||||
opcodes(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
)
|
||||
strings("")
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.layout.seekbar.seekbarColorPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.forEachChildElement
|
||||
@@ -71,6 +73,7 @@ val themePatch = bytecodePatch(
|
||||
dependsOn(
|
||||
lithoColorHookPatch,
|
||||
seekbarColorPatch,
|
||||
versionCheckPatch,
|
||||
resourcePatch {
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
@@ -83,9 +86,15 @@ val themePatch = bytecodePatch(
|
||||
|
||||
PreferenceScreen.SEEKBAR.addPreferences(
|
||||
SwitchPreference("revanced_seekbar_custom_color"),
|
||||
TextPreference("revanced_seekbar_custom_color_value", inputType = InputType.TEXT_CAP_CHARACTERS),
|
||||
TextPreference("revanced_seekbar_custom_color_primary", inputType = InputType.TEXT_CAP_CHARACTERS),
|
||||
)
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
PreferenceScreen.SEEKBAR.addPreferences(
|
||||
TextPreference("revanced_seekbar_custom_color_accent", inputType = InputType.TEXT_CAP_CHARACTERS),
|
||||
)
|
||||
}
|
||||
|
||||
// Edit theme colors via resources.
|
||||
document("res/values/colors.xml").use { document ->
|
||||
|
||||
@@ -163,22 +172,31 @@ val themePatch = bytecodePatch(
|
||||
}
|
||||
|
||||
// Fix the splash screen dark mode background color.
|
||||
// In earlier versions of the app this is white and makes no sense for dark mode.
|
||||
// This is only required for 19.32 and greater, but is applied to all targets.
|
||||
// Only dark mode needs this fix as light mode correctly uses the custom color.
|
||||
// In 19.32+ the dark mode splash screen is white and fades to black.
|
||||
// Maybe it's a bug in YT, or maybe it intentionally. Who knows.
|
||||
document("res/values-night/styles.xml").use { document ->
|
||||
// Create a night mode specific override for the splash screen background.
|
||||
val style = document.createElement("style")
|
||||
style.setAttribute("name", "Theme.YouTube.Home")
|
||||
style.setAttribute("parent", "@style/Base.V23.Theme.YouTube.Home")
|
||||
|
||||
val windowItem = document.createElement("item")
|
||||
windowItem.setAttribute("name", "android:windowBackground")
|
||||
windowItem.textContent = "@color/$splashBackgroundColor"
|
||||
style.appendChild(windowItem)
|
||||
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
resourcesNode.appendChild(style)
|
||||
val childNodes = resourcesNode.childNodes
|
||||
|
||||
for (i in 0 until childNodes.length) {
|
||||
val node = childNodes.item(i) as? Element ?: continue
|
||||
val nodeAttributeName = node.getAttribute("name")
|
||||
if (nodeAttributeName.startsWith("Theme.YouTube.Launcher")) {
|
||||
val nodeAttributeParent = node.getAttribute("parent")
|
||||
|
||||
val style = document.createElement("style")
|
||||
style.setAttribute("name", "Theme.YouTube.Home")
|
||||
style.setAttribute("parent", nodeAttributeParent)
|
||||
|
||||
val windowItem = document.createElement("item")
|
||||
windowItem.setAttribute("name", "android:windowBackground")
|
||||
windowItem.textContent = "@color/$splashBackgroundColor"
|
||||
style.appendChild(windowItem)
|
||||
|
||||
resourcesNode.removeChild(node)
|
||||
resourcesNode.appendChild(style)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import app.revanced.patches.shared.misc.checks.checkEnvironmentPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
|
||||
val checkEnvironmentPatch = checkEnvironmentPatch(
|
||||
internal val checkEnvironmentPatch = checkEnvironmentPatch(
|
||||
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint,
|
||||
extensionPatch = sharedExtensionPatch,
|
||||
"com.google.android.youtube",
|
||||
|
||||
@@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
@@ -13,7 +14,10 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
|
||||
name = "Check watch history domain name resolution",
|
||||
description = "Checks if the device DNS server is preventing user watch history from being saved.",
|
||||
) {
|
||||
dependsOn(addResourcesPatch)
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
addResourcesPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.fix.cairo
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.backgroundPlaybackPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_04_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
internal val disableCairoSettingsPatch = bytecodePatch(
|
||||
description = "Disables Cairo Fragment from being used.",
|
||||
) {
|
||||
dependsOn(versionCheckPatch)
|
||||
|
||||
execute {
|
||||
if (!is_19_04_or_greater) {
|
||||
return@execute
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Cairo Fragment was added since YouTube v19.04.38.
|
||||
*
|
||||
* Disable this for the following reasons:
|
||||
* 1. [backgroundPlaybackPatch] does not activate the Minimized playback setting of Cairo Fragment.
|
||||
* 2. Some patches do not yet support Cairo Fragments (ie: custom Seekbar color).
|
||||
* 3. Settings preferences added by ReVanced are missing.
|
||||
*
|
||||
* Screenshots of the Cairo Fragment:
|
||||
* <a href="https://github.com/qnblackcat/uYouPlus/issues/1468">uYouPlus#1468</a>.
|
||||
*/
|
||||
cairoFragmentConfigFingerprint.method.apply {
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(CAIRO_CONFIG_LITERAL_VALUE)
|
||||
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
||||
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
resultIndex + 1,
|
||||
"const/16 v$register, 0x0",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.fix.cairo
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
/**
|
||||
* Added in YouTube v19.04.38.
|
||||
*
|
||||
* When this value is true, Cairo Fragment is used.
|
||||
* In this case, some of the patches may be broken, so set this value to FALSE.
|
||||
*/
|
||||
internal const val CAIRO_CONFIG_LITERAL_VALUE = 45532100L
|
||||
|
||||
internal val cairoFragmentConfigFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
literal { CAIRO_CONFIG_LITERAL_VALUE }
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playbackspeed
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/FixPlaybackSpeedWhilePlayingPatch;"
|
||||
|
||||
/**
|
||||
* Fixes a bug in YouTube 19.34+ where the playback speed
|
||||
* can incorrectly reset to 1.0x under certain conditions.
|
||||
*
|
||||
* Reproduction steps using 19.34+
|
||||
* 1. Open a video and start playback
|
||||
* 2. Change the speed to any value that is not 1.0x.
|
||||
* 3. Open the comments panel.
|
||||
* 4. Tap any "N more replies" link at the bottom of a comment, or tap on a timestamp of a comment.
|
||||
* 5. Pause the video
|
||||
* 6. Resume the video
|
||||
* 7. Playback speed will incorrectly change to 1.0x.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
val fixPlaybackSpeedWhilePlayingPatch = bytecodePatch{
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
playerTypeHookPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
if (!is_19_34_or_greater) {
|
||||
return@execute
|
||||
}
|
||||
|
||||
playbackSpeedInFeedsFingerprint.method.apply {
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
val playbackSpeedIndex = indexOfGetPlaybackSpeedInstruction(this)
|
||||
val playbackSpeedRegister = getInstruction<TwoRegisterInstruction>(playbackSpeedIndex).registerA
|
||||
val returnIndex = indexOfFirstInstructionOrThrow(playbackSpeedIndex, Opcode.RETURN_VOID)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
playbackSpeedIndex + 1,
|
||||
"""
|
||||
invoke-static { v$playbackSpeedRegister }, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedChanged(F)Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :do_not_change
|
||||
""",
|
||||
ExternalLabel("do_not_change", getInstruction(returnIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playbackspeed
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
/**
|
||||
* This method is usually used to set the initial speed (1.0x) when playback starts from the feed.
|
||||
* For some reason, in the latest YouTube, it is invoked even after the video has already started.
|
||||
*/
|
||||
internal val playbackSpeedInFeedsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
Opcode.IGET,
|
||||
Opcode.MUL_INT_LIT16,
|
||||
Opcode.IGET_WIDE,
|
||||
Opcode.CONST_WIDE_16,
|
||||
Opcode.CMP_LONG,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IF_LEZ,
|
||||
Opcode.SUB_LONG_2ADDR,
|
||||
)
|
||||
custom { method, _ ->
|
||||
indexOfGetPlaybackSpeedInstruction(method) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun indexOfGetPlaybackSpeedInstruction(method: Method) =
|
||||
method.indexOfFirstInstructionReversed {
|
||||
opcode == Opcode.IGET &&
|
||||
getReference<FieldReference>()?.type == "F"
|
||||
}
|
||||
@@ -105,3 +105,15 @@ internal val pivotBarConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
strings("com.google.android.apps.youtube.app.endpoint.flags")
|
||||
}
|
||||
|
||||
internal val imageEnumConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
strings("TAB_ACTIVITY_CAIRO")
|
||||
}
|
||||
|
||||
internal val setEnumMapFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
literal {
|
||||
ytFillBellId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.misc.navigation
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
@@ -12,13 +13,16 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
@@ -26,6 +30,8 @@ internal var imageOnlyTabResourceId = -1L
|
||||
private set
|
||||
internal var actionBarSearchResultsViewMicId = -1L
|
||||
private set
|
||||
internal var ytFillBellId = -1L
|
||||
private set
|
||||
|
||||
private val navigationBarHookResourcePatch = resourcePatch {
|
||||
dependsOn(resourceMappingPatch)
|
||||
@@ -33,6 +39,7 @@ private val navigationBarHookResourcePatch = resourcePatch {
|
||||
execute {
|
||||
imageOnlyTabResourceId = resourceMappings["layout", "image_only_tab"]
|
||||
actionBarSearchResultsViewMicId = resourceMappings["layout", "action_bar_search_results_view_mic"]
|
||||
ytFillBellId = resourceMappings["drawable", "yt_fill_bell_black_24"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +151,36 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
|
||||
"(${EXTENSION_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V",
|
||||
)
|
||||
}
|
||||
|
||||
// Fix YT bug of notification tab missing the filled icon.
|
||||
if (is_19_35_or_greater) {
|
||||
val cairoNotificationEnumReference = with(imageEnumConstructorFingerprint) {
|
||||
val stringIndex = stringMatches!!.first().index
|
||||
val cairoNotificationEnumIndex = method.indexOfFirstInstructionOrThrow(stringIndex) {
|
||||
opcode == Opcode.SPUT_OBJECT
|
||||
}
|
||||
method.getInstruction<ReferenceInstruction>(cairoNotificationEnumIndex).reference
|
||||
}
|
||||
|
||||
setEnumMapFingerprint.method.apply {
|
||||
val enumMapIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
reference?.definingClass == "Ljava/util/EnumMap;" &&
|
||||
reference.name == "put" &&
|
||||
reference.parameterTypes.firstOrNull() == "Ljava/lang/Enum;"
|
||||
}
|
||||
val instruction = getInstruction<FiveRegisterInstruction>(enumMapIndex)
|
||||
|
||||
addInstructions(
|
||||
enumMapIndex + 1,
|
||||
"""
|
||||
sget-object v${instruction.registerD}, $cairoNotificationEnumReference
|
||||
invoke-static { v${instruction.registerC}, v${instruction.registerD} }, $EXTENSION_CLASS_DESCRIPTOR->setCairoNotificationFilledIcon(Ljava/util/EnumMap;Ljava/lang/Enum;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,23 @@ internal val playerTopControlsInflateFingerprint = fingerprint {
|
||||
literal { controlsLayoutStub }
|
||||
}
|
||||
|
||||
internal val playerControlsExtensionHookListenersExistFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Z")
|
||||
parameters()
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "fullscreenButtonVisibilityCallbacksExist" &&
|
||||
classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal val playerControlsExtensionHookFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("V")
|
||||
parameters("Z")
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "fullscreenButtonVisibilityChanged" &&
|
||||
classDef.type == "Lapp/revanced/extension/youtube/patches/PlayerControlsPatch;"
|
||||
classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,13 +189,18 @@ fun injectVisibilityCheckCall(descriptor: String) {
|
||||
"invoke-static { p1 , p2 }, $descriptor->changeVisibility(ZZ)V",
|
||||
)
|
||||
|
||||
if (!visibilityImmediateCallbacksExistModified) {
|
||||
visibilityImmediateCallbacksExistModified = true
|
||||
visibilityImmediateCallbacksExistMethod.returnEarly(true)
|
||||
}
|
||||
|
||||
visibilityImmediateMethod.addInstruction(
|
||||
visibilityImmediateInsertIndex++,
|
||||
"invoke-static { p0 }, $descriptor->changeVisibilityImmediate(Z)V",
|
||||
)
|
||||
}
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/PlayerControlsPatch;"
|
||||
|
||||
private lateinit var inflateTopControlMethod: MutableMethod
|
||||
@@ -209,6 +214,9 @@ private var inflateBottomControlRegister: Int = -1
|
||||
private lateinit var visibilityMethod: MutableMethod
|
||||
private var visibilityInsertIndex: Int = 0
|
||||
|
||||
private var visibilityImmediateCallbacksExistModified = false
|
||||
private lateinit var visibilityImmediateCallbacksExistMethod : MutableMethod
|
||||
|
||||
private lateinit var visibilityImmediateMethod: MutableMethod
|
||||
private var visibilityImmediateInsertIndex: Int = 0
|
||||
|
||||
@@ -266,6 +274,7 @@ val playerControlsPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistFingerprint.method
|
||||
visibilityImmediateMethod = playerControlsExtensionHookFingerprint.method
|
||||
|
||||
// A/B test for a slightly different bottom overlay controls,
|
||||
|
||||
@@ -41,6 +41,8 @@ var is_19_46_or_greater = false
|
||||
private set
|
||||
var is_19_47_or_greater = false
|
||||
private set
|
||||
var is_19_49_or_greater = false
|
||||
private set
|
||||
|
||||
val versionCheckPatch = resourcePatch(
|
||||
description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.",
|
||||
@@ -74,5 +76,6 @@ val versionCheckPatch = resourcePatch(
|
||||
is_19_43_or_greater = 244405000 <= playStoreServicesVersion
|
||||
is_19_46_or_greater = 244705000 <= playStoreServicesVersion
|
||||
is_19_47_or_greater = 244799000 <= playStoreServicesVersion
|
||||
is_19_49_or_greater = 245005000 <= playStoreServicesVersion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,3 +21,14 @@ internal val setThemeFingerprint = fingerprint {
|
||||
opcodes(Opcode.RETURN_OBJECT)
|
||||
literal { appearanceStringId }
|
||||
}
|
||||
|
||||
/**
|
||||
* Added in YouTube v19.04.38.
|
||||
*/
|
||||
internal const val CAIRO_CONFIG_LITERAL_VALUE = 45532100L
|
||||
|
||||
internal val cairoFragmentConfigFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
literal { CAIRO_CONFIG_LITERAL_VALUE }
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
@@ -17,10 +18,17 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPref
|
||||
import app.revanced.patches.shared.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.fix.cairo.disableCairoSettingsPatch
|
||||
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_04_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
// Used by a fingerprint() from SettingsPatch.
|
||||
@@ -37,13 +45,28 @@ private val settingsResourcePatch = resourcePatch {
|
||||
dependsOn(
|
||||
resourceMappingPatch,
|
||||
settingsPatch(
|
||||
rootPreference = IntentPreference(
|
||||
titleKey = "revanced_settings_title",
|
||||
summaryKey = null,
|
||||
intent = newIntent("revanced_settings_intent"),
|
||||
) to "settings_fragment",
|
||||
preferences,
|
||||
),
|
||||
listOf(
|
||||
IntentPreference(
|
||||
titleKey = "revanced_settings_title",
|
||||
summaryKey = null,
|
||||
intent = newIntent("revanced_settings_intent"),
|
||||
) to "settings_fragment",
|
||||
PreferenceCategory(
|
||||
titleKey = "revanced_settings_title",
|
||||
layout = "@layout/preference_group_title",
|
||||
preferences = setOf(
|
||||
IntentPreference(
|
||||
titleKey = "revanced_settings_submenu_title",
|
||||
summaryKey = null,
|
||||
icon = "@drawable/revanced_settings_icon",
|
||||
layout = "@layout/preference_with_icon",
|
||||
intent = newIntent("revanced_settings_intent"),
|
||||
)
|
||||
)
|
||||
) to "settings_fragment_cairo",
|
||||
),
|
||||
preferences
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
@@ -51,6 +74,7 @@ private val settingsResourcePatch = resourcePatch {
|
||||
appearanceStringId = resourceMappings["string", "app_theme_appearance_dark"]
|
||||
|
||||
arrayOf(
|
||||
ResourceGroup("drawable", "revanced_settings_icon.xml"),
|
||||
ResourceGroup("layout", "revanced_settings_with_toolbar.xml"),
|
||||
).forEach { resourceGroup ->
|
||||
copyResources("settings", resourceGroup)
|
||||
@@ -73,7 +97,6 @@ private val settingsResourcePatch = resourcePatch {
|
||||
// Remove horizontal divider from the settings Preferences
|
||||
// To better match the appearance of the stock YouTube settings.
|
||||
document("res/values/styles.xml").use { document ->
|
||||
|
||||
arrayOf(
|
||||
"Theme.YouTube.Settings",
|
||||
"Theme.YouTube.Settings.Dark",
|
||||
@@ -93,7 +116,6 @@ private val settingsResourcePatch = resourcePatch {
|
||||
// Some devices freak out if undeclared data is passed to an intent,
|
||||
// and this change appears to fix the issue.
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
|
||||
val licenseElement = document.childNodes.findElementByAttributeValueOrThrow(
|
||||
"android:name",
|
||||
"com.google.android.libraries.social.licenses.LicenseActivity",
|
||||
@@ -117,7 +139,8 @@ val settingsPatch = bytecodePatch(
|
||||
sharedExtensionPatch,
|
||||
settingsResourcePatch,
|
||||
addResourcesPatch,
|
||||
disableCairoSettingsPatch,
|
||||
versionCheckPatch,
|
||||
fixPlaybackSpeedWhilePlayingPatch,
|
||||
// Currently there is no easy way to make a mandatory patch,
|
||||
// so for now this is a dependent of this patch.
|
||||
checkEnvironmentPatch,
|
||||
@@ -140,6 +163,12 @@ val settingsPatch = bytecodePatch(
|
||||
selectable = true,
|
||||
)
|
||||
|
||||
if (is_19_34_or_greater) {
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_restore_old_settings_menus")
|
||||
)
|
||||
}
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
TextPreference(
|
||||
key = null,
|
||||
@@ -148,6 +177,10 @@ val settingsPatch = bytecodePatch(
|
||||
inputType = InputType.TEXT_MULTI_LINE,
|
||||
tag = "app.revanced.extension.shared.settings.preference.ImportExportPreference",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_language",
|
||||
summaryKey = null
|
||||
)
|
||||
)
|
||||
|
||||
setThemeFingerprint.method.let { setThemeMethod ->
|
||||
@@ -187,6 +220,40 @@ val settingsPatch = bytecodePatch(
|
||||
licenseActivityOnCreateFingerprint.classDef.apply {
|
||||
methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
|
||||
}
|
||||
|
||||
// Add context override to force a specific settings language.
|
||||
licenseActivityOnCreateFingerprint.classDef.apply {
|
||||
val attachBaseContext = ImmutableMethod(
|
||||
type,
|
||||
"attachBaseContext",
|
||||
listOf(ImmutableMethodParameter("Landroid/content/Context;", null, null)),
|
||||
"V",
|
||||
AccessFlags.PROTECTED.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(3),
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-static { p1 }, $activityHookClassDescriptor->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
|
||||
move-result-object p1
|
||||
invoke-super { p0, p1 }, $superclass->attachBaseContext(Landroid/content/Context;)V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
methods.add(attachBaseContext)
|
||||
}
|
||||
|
||||
// Add setting to force cairo settings fragment on/off.
|
||||
if (is_19_04_or_greater) {
|
||||
cairoFragmentConfigFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||
CAIRO_CONFIG_LITERAL_VALUE,
|
||||
"$activityHookClassDescriptor->useCairoSettingsFragment(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
finalize {
|
||||
@@ -222,17 +289,15 @@ object PreferenceScreen : BasePreferenceScreen() {
|
||||
key = "revanced_settings_screen_03_feed",
|
||||
summaryKey = null,
|
||||
)
|
||||
val PLAYER = Screen(
|
||||
key = "revanced_settings_screen_04_player",
|
||||
val GENERAL_LAYOUT = Screen(
|
||||
key = "revanced_settings_screen_04_general",
|
||||
summaryKey = null,
|
||||
)
|
||||
val GENERAL_LAYOUT = Screen(
|
||||
key = "revanced_settings_screen_05_general",
|
||||
val PLAYER = Screen(
|
||||
key = "revanced_settings_screen_05_player",
|
||||
summaryKey = null,
|
||||
)
|
||||
|
||||
// Don't sort, as related preferences are scattered apart.
|
||||
// Can use title sorting after PreferenceCategory support is added.
|
||||
val SHORTS = Screen(
|
||||
key = "revanced_settings_screen_06_shorts",
|
||||
summaryKey = null,
|
||||
|
||||
@@ -38,10 +38,23 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference(
|
||||
"revanced_spoof_video_streams_language",
|
||||
summaryKey = null
|
||||
"revanced_spoof_video_streams_client_type",
|
||||
summaryKey = null,
|
||||
),
|
||||
NonInteractivePreference("revanced_spoof_video_streams_about")
|
||||
NonInteractivePreference(
|
||||
// Requires a key and title but the actual text is chosen at runtime.
|
||||
key = "revanced_spoof_video_streams_about_android",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_spoof_video_streams_language",
|
||||
summaryKey = null,
|
||||
// Language strings are declared in Setting patch.
|
||||
entriesKey = "revanced_language_entries",
|
||||
entryValuesKey = "revanced_language_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
|
||||
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -51,7 +51,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint {
|
||||
internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("Landroid/graphics/Bitmap;")
|
||||
|
||||
@@ -31,8 +31,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
@Suppress("unused")
|
||||
val forceOriginalAudioPatch = bytecodePatch(
|
||||
name = "Force original audio",
|
||||
description = "Adds an option to always use the original audio track. " +
|
||||
"This patch does nothing if 'Spoof video streams' is enabled.",
|
||||
description = "Adds an option to always use the original audio track.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
@@ -58,7 +57,10 @@ val forceOriginalAudioPatch = bytecodePatch(
|
||||
addResources("youtube", "video.audio.forceOriginalAudioPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_force_original_audio")
|
||||
SwitchPreference(
|
||||
key = "revanced_force_original_audio",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ForceOriginalAudioSwitchPreference"
|
||||
)
|
||||
)
|
||||
|
||||
fun Method.firstFormatStreamingModelCall(
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package app.revanced.patches.youtube.video.hdr
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableHdrPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val disableHdrPatch = bytecodePatch(
|
||||
name = "Disable HDR video",
|
||||
description = "Adds an option to disable video HDR.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"18.38.44",
|
||||
"18.49.37",
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "video.hdr.disableHdrPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_disable_hdr_video")
|
||||
)
|
||||
|
||||
hdrCapabilityFingerprint.let {
|
||||
it.originalMethod.apply {
|
||||
val stringIndex = it.stringMatches!!.first().index
|
||||
val navigateIndex = indexOfFirstInstructionOrThrow(stringIndex) {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.parameterTypes == listOf("I", "Landroid/view/Display;") &&
|
||||
reference.returnType == "Z"
|
||||
}
|
||||
|
||||
// Modify the HDR lookup method (Method is in the same class as the fingerprint).
|
||||
navigate(this).to(navigateIndex).stop().addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableHDRVideo()Z
|
||||
move-result v0
|
||||
if-nez v0, :useHdr
|
||||
return v0
|
||||
:useHdr
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.youtube.video.hdr
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val hdrCapabilityFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
strings(
|
||||
"av1_profile_main_10_hdr_10_plus_supported",
|
||||
"video/av01"
|
||||
)
|
||||
}
|
||||
@@ -17,22 +17,26 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.interaction.seekbar.disableFastForwardNoticeFingerprint
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter
|
||||
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTreeHook
|
||||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
|
||||
var speedUnavailableId = -1L
|
||||
internal set
|
||||
internal var speedUnavailableId = -1L
|
||||
private set
|
||||
|
||||
private val customPlaybackSpeedResourcePatch = resourcePatch {
|
||||
dependsOn(resourceMappingPatch)
|
||||
@@ -61,6 +65,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
recyclerViewTreeHookPatch,
|
||||
customPlaybackSpeedResourcePatch,
|
||||
addResourcesPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
execute {
|
||||
@@ -71,6 +76,12 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
TextPreference("revanced_custom_playback_speeds", inputType = InputType.TEXT_MULTI_LINE),
|
||||
)
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
TextPreference("revanced_speed_tap_and_hold", inputType = InputType.NUMBER_DECIMAL),
|
||||
)
|
||||
}
|
||||
|
||||
// Replace the speeds float array with custom speeds.
|
||||
speedArrayGeneratorFingerprint.method.apply {
|
||||
val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference<MethodReference>()?.name == "size" }
|
||||
@@ -166,5 +177,27 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region Custom tap and hold 2x speed.
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
disableFastForwardNoticeFingerprint.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
(this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits()
|
||||
}
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->tapAndHoldSpeed()F
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,31 +24,31 @@ class StringResource(
|
||||
if (value.startsWith('"') && value.endsWith('"')) {
|
||||
// Raw strings allow unescaped single quote but not double quote.
|
||||
if (!value.substring(1, value.length - 1).contains(Regex("(?<!\\\\)[\"]"))) {
|
||||
return this;
|
||||
return this
|
||||
}
|
||||
} else {
|
||||
if (value.contains('\n')) {
|
||||
// Don't throw an exception, otherwise unnoticed mistakes
|
||||
// in Crowdin can cause patching failures.
|
||||
// Incorrectly escaped strings still work but do not display as intended.
|
||||
Logger.getLogger(StringResource.javaClass.name).severe(
|
||||
Logger.getLogger(StringResource.javaClass.name).warning(
|
||||
"String $name is not raw but contains encoded new line characters: $value")
|
||||
}
|
||||
if (!value.contains(Regex("(?<!\\\\)['\"]"))) {
|
||||
return this;
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
Logger.getLogger(StringResource.javaClass.name).severe(
|
||||
Logger.getLogger(StringResource.javaClass.name).warning(
|
||||
"String $name cannot contain unescaped quotes in value: $value")
|
||||
|
||||
return this;
|
||||
return this
|
||||
}
|
||||
|
||||
// if the string is un-formatted, explicitly add the formatted attribute
|
||||
if (!formatted) setAttribute("formatted", "false")
|
||||
|
||||
textContent = value.validateAndroidStringEscaping();
|
||||
textContent = value.validateAndroidStringEscaping()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -136,6 +136,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.panels.popup.playerPopupPanelsPatch">
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
</patch>
|
||||
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
||||
@@ -155,6 +157,8 @@ Second \"item\" text"</string>
|
||||
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
|
||||
<!-- Shown in the settings preferences, and translations can be any text length. -->
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
@@ -168,8 +172,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
</patch>
|
||||
<patch id="layout.theme.themePatch">
|
||||
@@ -218,6 +220,7 @@ Second \"item\" text"</string>
|
||||
<patch id="interaction.seekbar.enableSlideToSeekPatch">
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<!-- 'no auth' means no authentication -->
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -136,6 +136,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.panels.popup.playerPopupPanelsPatch">
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
</patch>
|
||||
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
||||
@@ -155,6 +157,8 @@ Second \"item\" text"</string>
|
||||
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
|
||||
<!-- Shown in the settings preferences, and translations can be any text length. -->
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
@@ -168,8 +172,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
</patch>
|
||||
<patch id="layout.theme.themePatch">
|
||||
@@ -218,6 +220,7 @@ Second \"item\" text"</string>
|
||||
<patch id="interaction.seekbar.enableSlideToSeekPatch">
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<!-- 'no auth' means no authentication -->
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -43,6 +43,62 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_import_reset">ØĨؚاد؊ ØĒØšŲŲŲ ØĨؚداداØĒ ReVanced ØĨŲŲ Ø§ŲŲØļØš Ø§ŲØ§ŲØĒØąØ§ØļŲ</string>
|
||||
<string name="revanced_settings_import_success">ØĒŲ
Ø§ØŗØĒŲØąØ§Ø¯ %d ØĨؚداداØĒ</string>
|
||||
<string name="revanced_settings_import_failure_parse">ŲØ´Ų Ø§ŲØ§ØŗØĒŲØąØ§Ø¯: %s</string>
|
||||
<string name="revanced_language_title">ŲØēØŠ ReVanced</string>
|
||||
<string name="revanced_language_user_dialog_message">"ŲØ¯ ØĒŲŲŲ Ø§ŲØĒØąØŦŲ
اØĒ ŲØ¨ØšØļ اŲب稧ØĒ Ų
ŲŲŲØ¯ØŠ ØŖŲ ØēŲØą Ų
ŲØĒŲ
ŲØŠ.
|
||||
|
||||
ŲØĒØąØŦŲ
ØŠ ب稧ØĒ ØŦØ¯ŲØ¯ØŠØ ØĒŲØļŲ Ø¨Ø˛ŲØ§ØąØŠ translate.revanced.app"</string>
|
||||
<string name="revanced_language_DEFAULT">ŲØēØŠ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
<string name="revanced_language_AR">Ø§ŲØšØąØ¨ŲØŠ</string>
|
||||
<string name="revanced_language_AZ">Azerbaijani</string>
|
||||
<string name="revanced_language_BG">Bulgarian</string>
|
||||
<string name="revanced_language_BN">Bengali</string>
|
||||
<string name="revanced_language_CA">Catalan</string>
|
||||
<string name="revanced_language_CS">Czech</string>
|
||||
<string name="revanced_language_DA">Danish</string>
|
||||
<string name="revanced_language_DE">German</string>
|
||||
<string name="revanced_language_EL">Greek</string>
|
||||
<string name="revanced_language_EN">English</string>
|
||||
<string name="revanced_language_ES">Spanish</string>
|
||||
<string name="revanced_language_ET">Estonian</string>
|
||||
<string name="revanced_language_FA">ŲØ§ØąØŗŲ</string>
|
||||
<string name="revanced_language_FI">Finnish</string>
|
||||
<string name="revanced_language_FR">French - Français</string>
|
||||
<string name="revanced_language_GU">Gujarati</string>
|
||||
<string name="revanced_language_HI">Hindi</string>
|
||||
<string name="revanced_language_HR">Croatian</string>
|
||||
<string name="revanced_language_HU">Hungarian</string>
|
||||
<string name="revanced_language_ID">Indonesian</string>
|
||||
<string name="revanced_language_IT">Italian</string>
|
||||
<string name="revanced_language_JA">Japanese</string>
|
||||
<string name="revanced_language_KK">Kazakh</string>
|
||||
<string name="revanced_language_KO">Korean</string>
|
||||
<string name="revanced_language_LT">Lithuanian</string>
|
||||
<string name="revanced_language_LV">Latvian</string>
|
||||
<string name="revanced_language_MK">Macedonian</string>
|
||||
<string name="revanced_language_MN">Mongolian</string>
|
||||
<string name="revanced_language_MR">Marathi</string>
|
||||
<string name="revanced_language_MS">Malay</string>
|
||||
<string name="revanced_language_MY">Burmese</string>
|
||||
<string name="revanced_language_NL">Dutch</string>
|
||||
<string name="revanced_language_OR">Odia</string>
|
||||
<string name="revanced_language_PA">Punjabi</string>
|
||||
<string name="revanced_language_PL">Polish</string>
|
||||
<string name="revanced_language_PT">Portugese</string>
|
||||
<string name="revanced_language_RO">Romanian</string>
|
||||
<string name="revanced_language_RU">Russian - Đ ŅŅŅĐēиК</string>
|
||||
<string name="revanced_language_SK">Slovak</string>
|
||||
<string name="revanced_language_SL">Slovene</string>
|
||||
<string name="revanced_language_SR">Serbian</string>
|
||||
<string name="revanced_language_SV">Swedish</string>
|
||||
<string name="revanced_language_SW">Swahili</string>
|
||||
<string name="revanced_language_TA">Tamil</string>
|
||||
<string name="revanced_language_TE">Telugu</string>
|
||||
<string name="revanced_language_TH">Thai</string>
|
||||
<string name="revanced_language_TR">Turkish</string>
|
||||
<string name="revanced_language_UK">Ukrainian</string>
|
||||
<string name="revanced_language_UR">Urdu</string>
|
||||
<string name="revanced_language_VI">Vietnamese</string>
|
||||
<string name="revanced_language_ZH">Chinese</string>
|
||||
<string name="revanced_pref_import_export_title">Ø§ØŗØĒŲØąØ§Ø¯ / ØĒØĩØ¯ŲØą</string>
|
||||
<string name="revanced_pref_import_export_summary">Ø§ØŗØĒŲØąØ§Ø¯ / ØĒØĩØ¯ŲØą ØĨؚداداØĒ ReVanced</string>
|
||||
<!-- Settings about dialog. -->
|
||||
@@ -77,12 +133,13 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_screen_01_ads_title">Ø§ŲØĨØšŲØ§ŲاØĒ</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">Ų
ŲØĩØēŲبਧØĒ ŲŲØ¯ŲŲ Ø¨Ø¯ŲŲØŠ</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">اŲŲ
ŲØŦØ˛</string>
|
||||
<string name="revanced_settings_screen_04_player_title">اŲŲ
Ø´ØēŲ</string>
|
||||
<string name="revanced_settings_screen_05_general_title">Ø§ŲØĒØĩŲ
ŲŲ
Ø§ŲØšØ§Ų
</string>
|
||||
<string name="revanced_settings_screen_04_general_title">ؚاŲ
</string>
|
||||
<string name="revanced_settings_screen_05_player_title">Ų
Ø´ØēŲ</string>
|
||||
<string name="revanced_settings_screen_07_seekbar_title">Ø´ØąŲØˇ ØĒŲØ¯Ų
اŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_settings_screen_08_swipe_controls_title">Ø§ŲØĒØŲŲ
ØšŲ ØˇØąŲŲ ØĨŲŲ
Ø§ØĄØŠ Ø§ŲØĒŲ
ØąŲØą</string>
|
||||
<string name="revanced_settings_screen_11_misc_title">ØĨؚداداØĒ Ų
ØĒŲŲØšØŠ</string>
|
||||
<string name="revanced_settings_screen_11_misc_title">Ų
ØĒŲŲØš</string>
|
||||
<string name="revanced_settings_screen_12_video_title">اŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_restore_old_settings_menus_title">ØĨؚاد؊ ŲŲØ§ØĻŲ
ØĨؚداداØĒ ŲØ¯ŲŲ
ØŠ</string>
|
||||
</patch>
|
||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||
<string name="revanced_shorts_disable_background_playback_title">ØĒØšØˇŲŲ ØĒØ´ØēŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts ŲŲ Ø§ŲØŽŲŲŲØŠ</string>
|
||||
@@ -138,12 +195,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØ˛Øą</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØ˛Øą</string>
|
||||
<!-- 'For you' should be translated using the same localized wording YouTube displays. -->
|
||||
<string name="revanced_hide_for_you_shelf_title">ØĨØŽŲØ§ØĄ ØąŲ \"Ų
Ų ØŖØŦŲŲ\" ŲŲ ØĩŲØØŠ اŲŲŲØ§ØŠ</string>
|
||||
<string name="revanced_hide_for_you_shelf_title">ØĨØŽŲØ§ØĄ ØąŲ \"ŲŲŲ\" ŲŲ ØĩŲØØŠ اŲŲŲØ§ØŠ</string>
|
||||
<string name="revanced_hide_for_you_shelf_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØąŲ</string>
|
||||
<string name="revanced_hide_for_you_shelf_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØąŲ</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą \'ŲØ¨ŲŲŲ\'</string>
|
||||
<string name="revanced_hide_notify_me_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą \'ØĒŲØ¨ŲŲŲ\'</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØ˛Øą</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØ˛Øą</string>
|
||||
<!-- 'People also watch' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -164,9 +221,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_chips_shelf_title">ØĨØŽŲØ§ØĄ ØąŲ Ø§ŲØ´ØąØ§ØĻØ</string>
|
||||
<string name="revanced_hide_chips_shelf_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ ØąŲ Ø§ŲØ´ØąØ§ØĻØ</string>
|
||||
<string name="revanced_hide_chips_shelf_summary_off">ŲØĒŲ
ØšØąØļ ØąŲ Ø§ŲØ´ØąØ§ØĻØ</string>
|
||||
<string name="revanced_hide_expandable_chip_title">ØĨØŽŲØ§ØĄ Ø§ŲØ´ØąŲØØŠ Ø§ŲŲØ§Ø¨ŲØŠ ŲŲØĒŲØŗŲØš ØĒØØĒ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_hide_expandable_chip_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØąŲاØĻŲ Ø§ŲŲØ§Ø¨ŲØŠ ŲŲØĒŲØŗŲØš</string>
|
||||
<string name="revanced_hide_expandable_chip_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØąŲاØĻŲ Ø§ŲŲØ§Ø¨ŲØŠ ŲŲØĒŲØŗŲØš</string>
|
||||
<string name="revanced_hide_expandable_chip_title">ØĨØŽŲØ§ØĄ Ø§ŲØ´ØąŲØØŠ Ø§ŲŲØ§Ø¨ŲØŠ ŲŲØĒŲØŗŲØš ØĒØØĒ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_expandable_chip_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØ´ØąØ§ØĻØ Ø§ŲŲØ§Ø¨ŲØŠ ŲŲØĒŲØŗŲØš</string>
|
||||
<string name="revanced_hide_expandable_chip_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØ´ØąØ§ØĻØ Ø§ŲŲØ§Ø¨ŲØŠ ŲŲØĒŲØŗŲØš</string>
|
||||
<string name="revanced_hide_community_posts_title">ØĨØŽŲØ§ØĄ Ų
Ø´Ø§ØąŲØ§ØĒ اŲŲ
ØŦØĒŲ
Øš</string>
|
||||
<string name="revanced_hide_community_posts_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ų
Ø´Ø§ØąŲØ§ØĒ اŲŲ
ØŦØĒŲ
Øš</string>
|
||||
<string name="revanced_hide_community_posts_summary_off">ŲØĒŲ
ØšØąØļ Ų
Ø´Ø§ØąŲØ§ØĒ اŲŲ
ØŦØĒŲ
Øš</string>
|
||||
@@ -207,8 +264,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØĨØŦØąØ§ØĄØ§ØĒ Ø§ŲØŗØąŲؚ؊</string>
|
||||
<string name="revanced_hide_quick_actions_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØĨØŦØąØ§ØĄØ§ØĒ Ø§ŲØŗØąŲؚ؊</string>
|
||||
<string name="revanced_hide_related_videos_title">ØĨØŽŲØ§ØĄ اŲŲŲØ¯ŲŲŲØ§ØĒ ذاØĒ Ø§ŲØĩŲØŠ ŲŲ Ø§ŲØĨØŦØąØ§ØĄØ§ØĒ Ø§ŲØŗØąŲؚ؊</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ø°Ø§ØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">ŲØĒŲ
ØšØąØļ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ø°Ø§ØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ اŲŲŲØ¯ŲŲŲØ§ØĒ ذاØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">ŲØĒŲ
ØšØąØļ اŲŲŲØ¯ŲŲŲØ§ØĒ ذاØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_image_shelf_title">ØĨØŽŲØ§ØĄ ØąŲŲŲ Ø§ŲØĩŲØą ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ</string>
|
||||
<string name="revanced_hide_image_shelf_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ ØąŲŲŲ Ø§ŲØĩŲØąØŠ</string>
|
||||
<string name="revanced_hide_image_shelf_summary_off">ŲØĒŲ
ØšØąØļ ØąŲŲŲ Ø§ŲØĩŲØąØŠ</string>
|
||||
@@ -242,7 +299,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_description_components_screen_title">ŲØĩŲ Ø§ŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲ ØšØąØļ Ų
ŲŲŲØ§ØĒ ŲØĩŲ Ø§ŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Ø´ØąŲØˇ Ø§ŲØĒØĩŲŲØŠ</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">ØĨØŽŲØ§ØĄ Ø´ØąŲØˇ Ø§ŲØĒØĩŲŲØŠ ØŖŲ ØšØąØļŲ ŲŲ Ø§ŲŲ
ŲØŦØ˛ ŲØ§ŲØ¨ØØĢ ŲŲ
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ø°Ø§ØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">ØĨØŽŲØ§ØĄ Ø´ØąŲØˇ Ø§ŲØĒØĩŲŲØŠ ØŖŲ ØšØąØļŲ ŲŲ Ø§ŲŲ
ŲØŦØ˛ ŲØ§ŲØ¨ØØĢ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ذاØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">ØĨØŽŲØ§ØĄ ŲŲ Ø§ŲŲ
ŲØŦØ˛</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Ų
ØŽŲŲ ŲŲ Ø§ŲŲ
ŲØŦØ˛</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">ŲØšØąØļ ŲŲ Ø§ŲŲ
ŲØŦØ˛</string>
|
||||
@@ -293,10 +350,10 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_custom_filter_toast_invalid_syntax">ŲŲØĒØą Ų
ØŽØĩØĩ ØēŲØą ØĩØ§ŲØ: %s</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">ØĨØŽŲØ§ØĄ Ų
ØØĒŲŲ Ø§ŲŲŲŲ
اØĒ Ø§ŲØąØĻŲØŗŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_screen_summary">ØĨØŽŲØ§ØĄ ŲŲØ¯ŲŲŲØ§ØĒ Ø§ŲØ¨ØØĢ ŲØ§ŲŲ
ŲØŦØ˛ Ø¨Ø§ØŗØĒ؎داŲ
ŲŲØ§ØĒØą اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_home_title">ØĨØŽŲØ§ØĄ Ų
ŲØ§ØˇØš ŲŲØ¯ŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ Ø¨ŲØ§ØŗØˇØŠ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_on">ØĒØĒŲ
ØĒØĩŲŲØŠ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ ŲŲ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ \"Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ\" ØØŗØ¨ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_off">ŲØ§ ØĒØĒŲ
ØĒØĩŲŲØŠ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ ŲŲ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ \"Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ\" ØØŗØ¨ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_title">ØĨØŽŲØ§ØĄ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ø§ŲØŽØ§ØĩØŠ Ø¨Ø§ŲØ§Ø´ØĒØąØ§Ų ØšŲ ØˇØąŲŲ Ø§ŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_home_title">ØĨØŽŲØ§ØĄ ŲŲØ¯ŲŲŲØ§ØĒ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ Ø¨ŲØ§ØŗØˇØŠ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_on">ØĒØĒŲ
ØĒØĩŲŲØŠ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ \"Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ\" ØØŗØ¨ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_off">ŲØ§ ØĒØĒŲ
ØĒØĩŲŲØŠ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ \"Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ\" ØØŗØ¨ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_title">ØĨØŽŲØ§ØĄ اŲŲŲØ¯ŲŲŲØ§ØĒ Ø§ŲØŽØ§ØĩØŠ Ø¨Ø§ŲØ§Ø´ØĒØąØ§Ų ØšŲ ØˇØąŲŲ Ø§ŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_summary_on">ŲØĒŲ
ØĒØĩŲŲØŠ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ ØØŗØ¨ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_summary_off">ŲØ§ ŲØĒŲ
ØĒØĩŲŲØŠ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ ØØŗØ¨ اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
<string name="revanced_hide_keyword_content_search_title">ØĨØŽŲØ§ØĄ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ ØšŲ ØˇØąŲŲ Ø§ŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ</string>
|
||||
@@ -445,6 +502,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_overlay_background_alpha_summary">ŲŲŲ
ØŠ Ø´ŲØ§ŲŲØŠ ØŽŲŲŲØŠ ŲØ§ØŦŲØŠ Ø§ŲØĒŲ
ØąŲØą</string>
|
||||
<string name="revanced_swipe_threshold_title">Ų
ŲØ¯Ø§Øą ØØ¯ Ø§ŲØĒŲ
ØąŲØą</string>
|
||||
<string name="revanced_swipe_threshold_summary">Ø§ŲØØ¯ Ø§ŲØŖØ¯ŲŲ Ų
Ų Ø§ŲØĒŲ
ØąŲØą ŲØ¨Ų Ø§ŲØĒØ´Ø§Ų Ø§ŲØĨŲŲ
Ø§ØĄØŠ</string>
|
||||
<string name="revanced_swipe_change_video_title">ØĒŲ
ŲŲŲ ØĨŲŲ
Ø§ØĄØŠ Ø§ŲØĒŲ
ØąŲØą ŲØĒØēŲŲØą Ø§ŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_swipe_change_video_summary_on">ØŗŲØ¤Ø¯Ų Ø§ŲØĒŲ
ØąŲØą ŲŲ ŲØļØš Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ ØĨŲŲ Ø§ŲØĒØēŲŲØą ŲŲŲŲØ¯ŲŲ Ø§ŲØĒØ§ŲŲ/Ø§ŲØŗØ§Ø¨Ų</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">ŲŲ ŲØ¤Ø¯Ų Ø§ŲØĒŲ
ØąŲØą ŲŲ ŲØļØš Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ ØĨŲŲ Ø§ŲØĒØēŲŲØą ŲŲŲŲØ¯ŲŲ Ø§ŲØĒØ§ŲŲ/Ø§ŲØŗØ§Ø¨Ų</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">ØĒØšØˇŲŲ Ø§ŲØĒŲŲØąŲØŦŲŲ
ŲØŠ Ø§ŲØĒŲŲØ§ØĻŲØŠ</string>
|
||||
@@ -516,14 +576,14 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_navigation_button_labels_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø§ŲØĒØŗŲ
ŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_navigation_button_labels_summary_off">ŲØĒŲ
ØšØąØļ Ø§ŲØĒØŗŲ
ŲØ§ØĒ</string>
|
||||
<string name="revanced_disable_translucent_status_bar_title">ØĒØšØˇŲŲ Ø´ØąŲØˇ Ø§ŲØØ§ŲØŠ Ø§ŲØ´ŲاŲ</string>
|
||||
<string name="revanced_disable_translucent_status_bar_summary_on">Ø´ØąŲØˇ Ø§ŲØØ§ŲØŠ ØēŲØą Ų
ØšØĒŲ
ØŠ</string>
|
||||
<string name="revanced_disable_translucent_status_bar_summary_off">Ø´ØąŲØˇ Ø§ŲØØ§ŲØŠ ØēŲØą Ø´ŲØ§ŲØŠ ØŖŲ ØšŲ
ŲŲØŠ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_title">ØĒØšØˇŲŲ Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ Ø§ŲØ´ŲØ§Ų Ø§ŲŲØ§ØĒØ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš اŲŲØ§ØĒØ Ų
ØšØĒŲ
</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_off">ŲŲŲŲ Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš اŲŲØ§ØĒØ Ų
ØšØĒŲ
ŲØ§ ØŖŲ ŲØĩŲ Ø´ŲØ§Ų</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_title">ØĒØšØˇŲŲ Ø§ŲØ´ØąŲØˇ Ø§ŲØ¯Ø§ŲŲØŠ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš Ø§ŲØ¯Ø§ŲŲ Ų
ØšØĒŲ
</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_off">Ø´ØąŲØˇ Ø§ŲØĒØˇØ¨ŲŲ Ø§ŲŲ
ØĩŲØąŲ Ø§ŲØ´ŲØ§Ų ØēŲØą ØšŲ
ŲŲØŠ ØŖŲ ØšŲ
ŲŲØŠ</string>
|
||||
<string name="revanced_disable_translucent_status_bar_summary_on">Ø´ØąŲØˇ Ø§ŲØØ§ŲØŠ ØēŲØą Ø´ŲاŲ</string>
|
||||
<string name="revanced_disable_translucent_status_bar_summary_off">Ø´ØąŲØˇ Ø§ŲØØ§ŲØŠ Ų
ØšØĒŲ
ØŖŲ Ø´ŲØ§Ų</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_title">ØĒØšØˇŲŲ Ø§ŲØ´ØąŲØˇ Ø§ŲØ´ŲØ§Ų Ø§ŲŲØ§ØĒØ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš اŲŲØ§ØĒØ ØēŲØą Ø´ŲاŲ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_off">Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš اŲŲØ§ØĒØ Ų
ØšØĒŲ
Ø§Ų Ø´ŲØ§Ų</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_title">ØĒØšØˇŲŲ Ø§ŲØ´ØąŲØˇ Ø§ŲØ´ŲØ§Ų Ø§ŲØ¯Ø§ŲŲ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš Ø§ŲØ¯Ø§ŲŲ ØēŲØą Ø´ŲاŲ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_off">Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ ŲŲ Ø§ŲŲØļØš Ø§ŲØ¯Ø§ŲŲ Ų
ØšØĒŲ
Ø§Ų Ø´ŲØ§Ų</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
|
||||
<string name="revanced_hide_player_flyout_title">اŲŲØ§ØĻŲ
ØŠ اŲŲ
ŲØ¨ØĢŲØŠ</string>
|
||||
@@ -628,15 +688,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_player_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲ ØšØąØļ اŲŲ
ŲŲŲØ§ØĒ ŲŲ Ų
Ø´ØēŲ Shorts</string>
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">ØĨØŽŲØ§ØĄ Shorts ŲŲ Ų
ŲØŦØ˛ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Shorts ŲŲ Ų
ŲØŦØ˛ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">ŲØĒŲ
ØšØąØļ Shorts ŲŲ Ų
ŲØŦØ˛ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Ų
ØŽŲŲØŠ ŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ ŲØ§ŲŲŲØ¯ŲŲŲØ§ØĒ ذاØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">ØĒØšØąØļ ŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØąØĻŲØŗŲØŠ ŲØ§ŲŲŲØ¯ŲŲŲØ§ØĒ ذاØĒ Ø§ŲØĩŲØŠ</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">ØĨØŽŲØ§ØĄ Shorts ŲŲ Ų
ŲØŦØ˛ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Shorts ŲŲ Ų
ŲØŦØ˛ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">ŲØĒŲ
ØšØąØļ Shorts ŲŲ Ų
ŲØŦØ˛ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Ų
ØŽŲŲØŠ ŲŲ Ų
ŲØŦØ˛ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">ØĒØšØąØļ ŲŲ Ų
ŲØŦØ˛ Ø§ŲØ§Ø´ØĒØąØ§ŲØ§ØĒ</string>
|
||||
<string name="revanced_hide_shorts_search_title">ØĨØŽŲØ§ØĄ Shorts ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Shorts ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">ŲØĒŲ
ØšØąØļ Shorts ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Ų
ØŽŲŲØŠ ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">ØĒØšØąØļ ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ</string>
|
||||
<string name="revanced_hide_shorts_history_title">ØĨØŽŲØ§ØĄ Shorts ŲŲ ØŗØŦŲ Ø§ŲŲ
Ø´Ø§ŲØ¯ØŠ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Ų
ØŽŲŲØŠ ŲŲ ØŗØŦŲ Ø§ŲŲ
Ø´Ø§ŲØ¯ØŠ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">ØĒØšØąØļ ŲŲ ØŗØŦŲ Ø§ŲŲ
Ø´Ø§ŲØ¯ØŠ</string>
|
||||
<!-- 'join' should be translated using the same localized wording YouTube displays for the button. -->
|
||||
<string name="revanced_hide_shorts_join_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą Ø§ŲØ§ŲØļŲ
اŲ
</string>
|
||||
<string name="revanced_hide_shorts_join_button_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ Ø˛Øą Ø§ŲØ§ŲØļŲ
اŲ
</string>
|
||||
@@ -738,8 +801,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_on">ØĒŲ
ØĨØŽŲØ§ØĄ ŲŲØØ§ØĒ اŲŲ
Ø´ØēŲ Ø§ŲŲ
ŲØ¨ØĢŲØŠ</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_off">ŲØĒŲ
ØšØąØļ ŲŲØØ§ØĒ اŲŲ
Ø´ØēŲ Ø§ŲŲ
ŲØ¨ØĢŲØŠ</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
<string name="revanced_exit_fullscreen_title">Ø§ŲØŽØąŲØŦ Ų
Ų ŲØļØš Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ ØšŲØ¯ Ø§ŲØĒŲØ§ØĄ اŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_1">Ų
ØšØˇŲ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_2">Ø¨Ø§ŲØˇŲŲ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_3">Ø¨Ø§ŲØšØąØļ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_4">Ø¨Ø§ŲØˇŲŲ ŲØ§ŲØšØąØļ</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">ŲØĒØ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ ŲŲ Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">ŲØĒØ اŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_on">ŲØĒŲ
ŲØĒØ اŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ ŲØļØš Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_off">ŲØ§ ŲØĒŲ
ŲØĒØ اŲŲŲØ¯ŲŲŲØ§ØĒ ŲŲ ŲØļØš Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ</string>
|
||||
</patch>
|
||||
@@ -758,12 +828,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_ryd_failure_ryd_enabled_while_playing_video_then_user_voted">ØŖØšØ¯ ØĒØŲ
ŲŲ Ø§ŲŲŲØ¯ŲŲ ŲŲØĒØĩŲŲØĒ Ø¨Ų Return YouTube Dislike</string>
|
||||
<string name="revanced_ryd_enable_summary_on">ŲØĒŲ
ØšØąØļ ŲŲ
ŲØšØŦبŲŲ</string>
|
||||
<string name="revanced_ryd_enable_summary_off">ŲØ§ ŲØĒŲ
ØšØąØļ ŲŲ
ŲØšØŦبŲŲ</string>
|
||||
<string name="revanced_ryd_shorts_title">ØšØąØļ ŲŲ
ŲØšØŦŲŲ ŲŲ Ų
ŲØ§ØˇØš Shorts</string>
|
||||
<string name="revanced_ryd_shorts_summary_on">ŲØĒŲ
ØšØąØļ ŲŲ
ŲØšØŦŲŲ ŲŲ Ų
ŲØ§ØˇØš Shorts</string>
|
||||
<string name="revanced_ryd_shorts_title">ØšØąØļ ŲŲ
ŲØšØŦŲŲ ŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts</string>
|
||||
<string name="revanced_ryd_shorts_summary_on">ŲØĒŲ
ØšØąØļ ŲŲ
ŲØšØŦŲŲ ŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts</string>
|
||||
<string name="revanced_ryd_shorts_summary_on_disclaimer">"ØĨØ¨Ø¯Ø§ØĄØ§ØĒ ŲŲ
ŲØšØŦبŲŲ Ø§ŲØĒŲ ØĒØ¸ŲØą ØšŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts
|
||||
|
||||
Ø§ŲØĒŲŲŲØ¯: ŲØ¯ ŲØ§ ØĒØ¸ŲØą ØĨØ¨Ø¯Ø§ØĄØ§ØĒ ŲŲ
ŲØšØŦبŲŲ ŲŲ ŲØļØš Ø§ŲØĒØĩŲØ اŲŲ
ØĒØŽŲŲ"</string>
|
||||
<string name="revanced_ryd_shorts_summary_off">ØĒŲ
ØĨØŽŲØ§ØĄ ŲŲ
ŲØšØŦŲŲ ŲŲ Ų
ŲØ§ØˇØš Shorts</string>
|
||||
<string name="revanced_ryd_shorts_summary_off">ØĒŲ
ØĨØŽŲØ§ØĄ ŲŲ
ŲØšØŦŲŲ ŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts</string>
|
||||
<string name="revanced_ryd_dislike_percentage_title">ŲŲ
ŲØšØŦبŲŲ ŲŲŲ ŲØŗØ¨ØŠ Ų
ØĻŲŲØŠ</string>
|
||||
<string name="revanced_ryd_dislike_percentage_summary_on">ŲØšØąØļ ØšØ¯Ø¯ ŲŲ
ŲØšØŦبŲŲ ŲŲ ŲØŗØ¨ØŠ Ų
ØĻŲŲØŠ</string>
|
||||
<string name="revanced_ryd_dislike_percentage_summary_off">ŲØšØąØļ ØšØ¯Ø¯ ŲŲ
ŲØšØŦبŲŲ ŲŲ ØąŲŲŲŲ
</string>
|
||||
@@ -816,7 +886,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.sponsorblock.sponsorBlockResourcePatch">
|
||||
<string name="revanced_sb_enable_sb">ØĒŲ
ŲŲŲ SponsorBlock</string>
|
||||
<string name="revanced_sb_enable_sb_sum">Ų
اŲب𠨧بąŲØšŲØ§ØŠ ŲŲ ŲØ¸Ø§Ų
ØŦŲ
Ø§ØšŲ ŲØĒØŽØˇŲ Ø§ŲØŖØŦØ˛Ø§ØĄ اŲŲ
ŲŲ
ŲŲŲŲØŠ ŲŲ Ų
ŲØ§ØˇØš YouTube</string>
|
||||
<string name="revanced_sb_enable_sb_sum">SponsorBlock Ų
اŲب𠨧بąŲØšŲØ§ØŠ ŲŲ ŲØ¸Ø§Ų
ØŦŲ
Ø§ØšŲ ŲØĒØŽØˇŲ Ø§ŲØŖØŦØ˛Ø§ØĄ اŲŲ
ŲŲ
ŲŲŲŲØŠ ŲŲ Ų
ŲØ§ØˇØš YouTube</string>
|
||||
<string name="revanced_sb_appearance_category">اŲŲ
Ø¸ŲØą</string>
|
||||
<string name="revanced_sb_enable_voting">ØšØąØļ Ø˛Øą Ø§ŲØĒØĩŲŲØĒ</string>
|
||||
<string name="revanced_sb_enable_voting_sum_on">ŲØĒŲ
ØšØąØļ Ø˛Øą Ø§ŲØĒØĩŲŲØĒ ØšŲŲ Ø§ŲŲ
ŲØˇØš</string>
|
||||
@@ -895,7 +965,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_segments_filler">ØŽØ§ØąØŦ اŲŲ
ŲØļŲØš/اŲŲŲØ§ØĒ</string>
|
||||
<string name="revanced_sb_segments_filler_sum">ØĒŲ
ØĨØļØ§ŲØŠ Ų
Ø´Ø§ŲØ¯ Ų
ŲØĒŲØˇØŠ ØŽØ§ØąØŦ اŲŲ
ŲØļŲØš ØŖŲ Ø§ŲŲŲØ§ŲØŠ Ø§ŲØĒŲ ŲŲØŗØĒ Ų
ØˇŲŲØ¨ØŠ ŲŲŲŲ
اŲŲ
ØØĒŲŲ Ø§ŲØąØĻŲØŗŲ ŲŲŲŲØ¯ŲŲ. ŲØ§ ØĒØĒØļŲ
Ų Ų
ŲØ§ØˇØš ØĒŲŲØą ØĒŲØšØ¨ŲŲØą ØŖŲ ØĒŲØ§ØĩŲŲ Ø§ŲØŽŲŲŲØŠ</string>
|
||||
<string name="revanced_sb_segments_nomusic">اŲŲ
ŲØŗŲŲŲ: Ų
ŲØˇØš ØēŲØą Ų
ŲØŗŲŲŲ</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">ŲŲØˇ ŲŲØ§ØŗØĒ؎داŲ
ŲŲ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ø§ŲŲ
ŲØŗŲŲŲØŠ. ØŖŲØŗØ§Ų
Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ø§ŲŲ
ŲØŗŲŲŲØŠ Ø¨Ø¯ŲŲ Ų
ŲØŗŲŲŲØ ŲØ§ŲØĒŲ ŲŲ
ŲØĒŲ
ØĒØēØˇŲØĒŲØ§ باŲŲØšŲ Ų
Ų ŲØ¨Ų ŲØĻØŠ ØŖØŽØąŲ</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">ŲŲØˇ ŲŲØ§ØŗØĒ؎داŲ
ŲŲ Ø§ŲŲ
ŲØ§ØˇØš اŲŲ
ŲØŗŲŲŲØŠ. ØŖŲØŗØ§Ų
اŲŲ
ŲØ§ØˇØš اŲŲ
ŲØŗŲŲŲØŠ Ø¨Ø¯ŲŲ Ų
ŲØŗŲŲŲØ ŲØ§ŲØĒŲ ŲŲ
ŲØĒŲ
ØĒØēØˇŲØĒŲØ§ باŲŲØšŲ Ų
Ų ŲØ¨Ų ŲØĻØŠ ØŖØŽØąŲ</string>
|
||||
<string name="revanced_sb_skip_button_compact">ØĒØŽØˇŲ</string>
|
||||
<string name="revanced_sb_skip_button_compact_highlight">Ø§ŲØŖØ¨ØąØ˛</string>
|
||||
<string name="revanced_sb_skip_button_sponsor">ØĒØŽØˇŲ Ø§ŲØąØ§ØšŲ</string>
|
||||
@@ -1006,6 +1076,23 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_reset">ØĨؚاد؊ Ø§ŲØĒØšŲŲŲ</string>
|
||||
<string name="revanced_sb_about">ŲŲ
ØØŠ</string>
|
||||
<string name="revanced_sb_about_api_sum">ŲØĒŲ
ØĒŲŲŲØą Ø§ŲØ¨ŲØ§ŲاØĒ Ø¨ŲØ§ØŗØˇØŠ SponsorBlock API. اŲŲØą ŲŲØ§ ŲŲ
ØšØąŲØŠ Ø§ŲŲ
Ø˛ŲØ¯ ŲŲ
Ø´Ø§ŲØ¯ØŠ Ø§ŲØĒŲØ˛ŲŲØ§ØĒ ŲŲ
ŲØĩاØĒ ØŖØŽØąŲ</string>
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
<string name="revanced_change_form_factor_title">Ø´ŲŲ ŲŲ
ŲØ°ØŦ Ø§ŲØĒØŽØˇŲØˇ</string>
|
||||
<string name="revanced_change_form_factor_entry_1">Ø§ŲØ§ŲØĒØąØ§ØļŲ</string>
|
||||
<string name="revanced_change_form_factor_entry_2">Ø§ŲØŦŲŲØ§Ų</string>
|
||||
<string name="revanced_change_form_factor_entry_3">Ø§ŲØŦŲØ§Ø˛ اŲŲŲØŲ</string>
|
||||
<string name="revanced_change_form_factor_entry_4">Automotive</string>
|
||||
<string name="revanced_change_form_factor_user_dialog_message">"ØĒØĒØļŲ
Ų Ø§ŲØĒØēŲبਧØĒ:
|
||||
|
||||
ØĒØŽØˇŲØˇ Ø§ŲØŦŲØ§Ø˛ اŲŲŲØŲ
|
||||
âĸ ØĨØŽŲØ§ØĄ Ų
ŲØ´ŲØąØ§ØĒ اŲŲ
ØŦØĒŲ
Øš
|
||||
|
||||
ØĒØŽØˇŲØˇ Automotive
|
||||
âĸ ØĨØŽŲØ§ØĄ ŲØ§ØĻŲ
ØŠ ØŗØŦŲ Ø§ŲŲ
Ø´Ø§ŲØ¯ØŠ
|
||||
âĸ Ø§ØŗØĒؚاد؊ ØšŲØ§Ų
ØŠ Ø§ŲØĒØ¨ŲŲØ¨ \"Ø§ØŗØĒŲØ´Ø§Ų\"
|
||||
âĸ ŲØĒØ ŲŲØ¯ŲŲŲØ§ØĒ Shorts ŲŲ Ø§ŲŲ
Ø´ØēŲ Ø§ŲØšØ§Ø¯Ų
|
||||
âĸ ØĒŲØ¸ŲŲ
Ø§ŲØŽŲاØĩØŠ ØØŗØ¨ اŲŲ
ŲØļŲØšØ§ØĒ ŲØ§ŲŲŲØ§ØŠ"</string>
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<string name="revanced_spoof_app_version_title">ØŽŲØ¯Ø§Øš ØĨØĩØ¯Ø§Øą Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
@@ -1020,6 +1107,7 @@ Second \"item\" text"</string>
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
<string name="revanced_spoof_app_version_target_title">اŲŲØ¯Ų Ų
Ų ØĒØēŲŲØą ØĨØĩØ¯Ø§Øą Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Ø§ØŗØĒؚاد؊ ØŖŲŲŲŲØ§ØĒ Ų
Ø´ØēŲ Shorts اŲŲØ¯ŲŲ
ØŠ</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.26.42 - Ø§ØŗØĒؚاد؊ ØŖŲŲŲŲØ§ØĒ Ø§ŲØĒŲŲŲ ŲØ´ØąŲØˇ Ø§ŲØŖØ¯ŲاØĒ اŲŲØ¯ŲŲ
ØŠ</string>
|
||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_1">18.33.40 - Ø§ØŗØĒؚاد؊ RYD ØšŲŲ Shorts Ø¨ŲØļØš Ø§ŲØĒØŽŲŲ</string>
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_2">18.20.39 - Ø§ØŗØĒؚاد؊ ŲØ§ØĻŲ
ØŠ ØŗØąØšØŠ اŲŲŲØ¯ŲŲ Ø§ŲØšØąŲØļØŠ & Ø§ŲØŦŲØ¯ØŠ</string>
|
||||
@@ -1050,10 +1138,10 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_off">ØŗŲØĒŲ
Ø§ØŗØĒØĻŲØ§Ų ØĒØ´ØēŲŲ Ų
Ø´ØēŲ Shorts ØšŲØ¯ Ø¨Ø¯ØĄ ØĒØ´ØēŲŲ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
<string name="revanced_shorts_player_type_title">ŲØĒØ Ų
ŲØ§ØˇØš اŲŲShorts Ø¨Ø§ØŗØĒ؎داŲ
</string>
|
||||
<string name="revanced_shorts_player_type_title">ŲØĒØ ŲŲØ¯ŲŲŲØ§ØĒ Shorts Ø¨Ø§ØŗØĒ؎داŲ
</string>
|
||||
<string name="revanced_shorts_player_type_shorts">Ų
Ø´ØēŲ Shorts</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">Ų
Ø´ØēŲ ØšØ§Ø¯Ų</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">شاش؊ ŲØ§Ų
ŲØŠ - Ų
Ø´ØēŲ ØšØ§Ø¯Ų</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">اŲŲ
Ø´ØēŲ Ø§ŲØšØ§Ø¯Ų</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">اŲŲ
Ø´ØēŲ Ø§ŲØšØ§Ø¯Ų ŲŲ ŲØļØš Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
<string name="revanced_shorts_autoplay_title">Ø§ŲØĒØ´ØēŲŲ Ø§ŲØĒŲŲØ§ØĻŲ ŲŲŲØ¯ŲŲŲØ§ØĒ Shorts</string>
|
||||
@@ -1063,12 +1151,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_on">ØŗŲØĒŲ
ØĒØ´ØēŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts ØĒŲŲØ§ØĻŲŲØ§ ŲŲ Ø§ŲØŽŲŲŲØŠ</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_off">ØŗŲØĒŲ
ØĒŲØąØ§Øą ŲŲØ¯ŲŲŲØ§ØĒ Shorts ŲŲ Ø§ŲØŽŲŲŲØŠ</string>
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
<string name="revanced_tablet_layout_title">ØĒŲ
ŲŲŲ ØĒØĩŲ
ŲŲ
Ø§ŲØŦŲØ§Ø˛ اŲŲŲØŲ</string>
|
||||
<string name="revanced_tablet_layout_summary_on">ØĒŲ
ØĒŲ
ŲŲŲ ØĒØĩŲ
ŲŲ
Ø§ŲØŦŲØ§Ø˛ اŲŲŲØŲ</string>
|
||||
<string name="revanced_tablet_layout_summary_off">ØĒŲ
ØĒØšØˇŲŲ ØĒØĩŲ
ŲŲ
Ø§ŲØŦŲØ§Ø˛ اŲŲŲØŲ</string>
|
||||
<string name="revanced_tablet_layout_user_dialog_message">ŲØ§ ØĒØ¸ŲØą Ų
ŲØ´ŲØąØ§ØĒ اŲŲ
ØŦØĒŲ
Øš ØšŲŲ ØĒØŽØˇŲØˇØ§ØĒ Ø§ŲØŦŲØ§Ø˛ اŲŲŲØŲ</string>
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
<string name="revanced_miniplayer_screen_title">اŲŲ
Ø´ØēŲ Ø§ŲŲ
ØĩØēØą</string>
|
||||
<string name="revanced_miniplayer_screen_summary">ØĒØēŲŲØą ŲŲ
Øˇ اŲŲ
Ø´ØēŲ Ø§ŲŲ
ØĩØēØą Ø¯Ø§ØŽŲ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
@@ -1166,7 +1248,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_alt_thumbnail_stills_about_title">ŲŲØˇØ§ØĒ اŲŲŲØ¯ŲŲ Ø§ŲØĢØ§Ø¨ØĒØŠ</string>
|
||||
<string name="revanced_alt_thumbnail_stills_about_summary">ŲØĒŲ
Ø§ŲØĒŲØ§Øˇ اŲŲŲØˇØ§ØĒ Ø§ŲØĢØ§Ø¨ØĒØŠ Ų
Ų Ø¨Ø¯Ø§ŲØŠ/ŲØŗØˇ/ŲŲØ§ŲØŠ ŲŲ ŲŲØ¯ŲŲ. ŲØ°Ų Ø§ŲØĩŲØą Ų
دŲ
ØŦØŠ ŲŲ YouTube ŲŲØ§ ŲØĒŲ
Ø§ØŗØĒ؎داŲ
ØŖŲ ŲØ§ØŦŲØŠ Ø¨ØąŲ
ØŦØŠ ØĒØˇØ¨ŲŲØ§ØĒ ØŽØ§ØąØŦŲØŠ</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_title">Ø§ØŗØĒ؎دŲ
اŲŲŲØˇØ§ØĒ Ø§ŲØĢØ§Ø¨ØĒØŠ Ø§ŲØŗØąŲؚ؊</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_summary_on">Ø§ØŗØĒ؎داŲ
اŲŲŲØˇØ§ØĒ Ų
ØĒŲØŗØˇØŠ Ø§ŲØŦŲØ¯ØŠ. ØŗŲØĒŲ
ØĒØŲ
ŲŲ Ø§ŲŲ
ŲØĩØēŲبਧØĒ بشŲŲ ØŖØŗØąØšØ ŲŲŲŲ Ø§ŲØ¨ØĢ اŲŲ
Ø¨Ø§Ø´Øą Ų Ø§ŲŲ
ŲØ§ØˇØš Ø§ŲØĒŲ ŲŲ
ŲØĒŲ
ØĨØĩØ¯Ø§ØąŲØ§ ØŖŲ Ø§ŲŲØ¯ŲŲ
ØŠ ØŦØ¯ŲØ§ ŲØ¯ ØĒØšØąØļ Ų
ŲØĩØēŲبਧØĒ ŲØ§ØąØēØŠ</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_summary_on">Ø§ØŗØĒ؎داŲ
اŲŲŲØˇØ§ØĒ Ų
ØĒŲØŗØˇØŠ Ø§ŲØŦŲØ¯ØŠ. ØŗŲØĒŲ
ØĒØŲ
ŲŲ Ø§ŲŲ
ŲØĩØēŲبਧØĒ بشŲŲ ØŖØŗØąØšØ ŲŲŲŲ Ø§ŲØ¨ØĢ اŲŲ
Ø¨Ø§Ø´Øą Ų Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ Ø§ŲØĒŲ ŲŲ
ŲØĒŲ
ØĨØĩØ¯Ø§ØąŲØ§ ØŖŲ Ø§ŲŲØ¯ŲŲ
ØŠ ØŦØ¯ŲØ§ ŲØ¯ ØĒØšØąØļ Ų
ŲØĩØēŲبਧØĒ ŲØ§ØąØēØŠ</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_summary_off">Ø§ØŗØĒ؎داŲ
ŲŲØˇØ§ØĒ اŲŲŲØ¯ŲŲ Ø§ŲØĢØ§Ø¨ØĒØŠ بØŦŲØ¯ØŠ ؚاŲŲØŠ</string>
|
||||
<string name="revanced_alt_thumbnail_stills_time_title">ŲŲØĒ Ø§ŲŲŲØ¯ŲŲ ŲØŖØŽØ° اŲŲŲØˇØ§ØĒ Ø§ŲØĢØ§Ø¨ØĒØŠ Ų
ŲŲ</string>
|
||||
<string name="revanced_alt_thumbnail_stills_time_entry_1">Ø¨Ø¯Ø§ŲØŠ Ø§ŲŲŲØ¯ŲŲ</string>
|
||||
@@ -1232,12 +1314,13 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_force_original_audio_title">ŲØąØļ Ø§ŲØĩŲØĒ Ø§ŲØŖØĩŲŲ</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Ø§ØŗØĒ؎داŲ
Ø§ŲØĩŲØĒ Ø§ŲØŖØĩŲŲ</string>
|
||||
<string name="revanced_force_original_audio_summary_off">Ø§ØŗØĒ؎داŲ
Ø§ŲØĩŲØĒ Ø§ŲØ§ŲØĒØąØ§ØļŲ</string>
|
||||
<string name="revanced_force_original_audio_not_available">ŲØ§ØŗØĒ؎داŲ
ŲØ°Ų اŲŲ
ŲØ˛ØŠØ ŲŲ
بØĒØēŲŲØą Ų
ØØ§Ųا؊ بØĢ اŲŲ
ØØĒŲŲ ØĨŲŲ Ųب𠨧بšŲ
ŲŲ iOS</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
|
||||
<string name="revanced_video_quality_default_entry_1">ØĒŲŲØ§ØĻŲ</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_title">ØĒØ°ŲØą ØĒØēŲبਧØĒ ØŦŲØ¯ØŠ اŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_on">ØĒŲØˇØ¨Ų ØĒØēŲبਧØĒ Ø§ŲØŦŲØ¯ØŠ ØšŲŲ ØŦŲ
ŲØš Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_on">ØĒŲØˇØ¨Ų ØĒØēŲبਧØĒ Ø§ŲØŦŲØ¯ØŠ ØšŲŲ ØŦŲ
ب𠨧ŲŲŲØ¯ŲŲŲØ§ØĒ</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_off">ØĒŲØˇØ¨Ų ØĒØēŲبਧØĒ Ø§ŲØŦŲØ¯ØŠ ØšŲŲ Ø§ŲŲŲØ¯ŲŲ Ø§ŲØØ§ŲŲ ŲŲØˇ</string>
|
||||
<string name="revanced_video_quality_default_wifi_title">ØŦŲØ¯ØŠ اŲŲŲØ¯ŲŲ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ ØšŲŲ Ø´Ø¨ŲØŠ Wi-Fi</string>
|
||||
<string name="revanced_video_quality_default_mobile_title">ØŦŲØ¯ØŠ اŲŲŲØ¯ŲŲ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ ØšŲŲ Ø´Ø¨ŲØŠ Ø§ŲØŦŲŲŲØ§Ų</string>
|
||||
@@ -1259,6 +1342,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">ŲØŦب ØŖŲ ØĒŲŲŲ ØŗØąØšØ§ØĒ Ø§ŲØĒØ´ØēŲŲ Ø§ŲŲ
ØŽØĩØĩØŠ ØŖŲŲ Ų
Ų %s</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">ØŗØąØšØŠ Ø§ŲØĒØ´ØēŲŲ Ø§ŲŲ
ØŽØĩØĩØŠ ØēŲØą ØĩØ§ŲØØŠ</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">ØĒŲŲØ§ØĻŲ</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">\"ØŗØąØšØŠ اŲŲŲØą Ų
Øš Ø§ŲØ§ØŗØĒŲ
ØąØ§Øą اŲŲ
ØŽØĩØĩØŠ\"</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">ØŗØąØšØŠ Ø§ŲØĒØ´ØēŲŲ Ø¨ŲŲ 0-8</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">ØĒØ°ŲØą Ø§ŲØĒØēبਧØĒ ŲŲ ØŗØąØšØŠ Ø§ŲØĒØ´ØēŲŲ</string>
|
||||
@@ -1287,74 +1372,27 @@ Second \"item\" text"</string>
|
||||
ŲØ¯ ŲØ§ ŲØšŲ
Ų ØĒØ´ØēŲŲ Ø§ŲŲŲØ¯ŲŲ"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">ØĨŲŲØ§Ų ØĒØ´ØēŲŲ ŲØ°Ø§ Ø§ŲØĨؚداد ŲØ¯ ŲØŗØ¨Ø¨ Ų
شاŲŲ ŲŲ ØĒØ´ØēŲŲ Ø§ŲŲŲØ¯ŲŲ.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Ø§ŲØšŲ
ŲŲ Ø§ŲØ§ŲØĒØąØ§ØļŲ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ŲØąØļ AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ØĒŲ
ŲØąØļ ØĒØąŲ
ŲØ˛ اŲŲŲØ¯ŲŲ ØšŲŲ AVC (H.264)</string>
|
||||
<!-- 'no auth' means no authentication -->
|
||||
<string name="revanced_spoof_video_streams_client_type_android_vr_no_auth">Android VR (بدŲŲ Ų
ØĩØ§Ø¯ŲØŠ)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ŲØąØļ iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ŲØĒŲ
ŲØąØļ ØĒØąŲ
ŲØ˛ ŲŲØ¯ŲŲ ØšŲŲ AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ŲØĒŲ
ØĒØØ¯Ųد ØĒØąŲ
ŲØ˛ اŲŲŲØ¯ŲŲ ØĒŲŲØ§ØĻŲŲØ§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ŲØ¯ ŲØ¤Ø¯Ų ØĒŲ
ŲŲŲ ŲØ°Ø§ ØĨŲŲ ØĒØØŗŲŲ ØšŲ
Øą Ø§ŲØ¨ØˇØ§ØąŲØŠ ŲØĨØĩŲØ§Ø Ų
Ø´ŲŲØŠ ØĒŲØˇŲØš Ø§ŲØĒØ´ØēŲŲ.
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ŲØ¯ ŲØ¤Ø¯Ų ØĒŲ
ŲŲŲ ŲØ°Ø§ ØĨŲŲ ØĒØØŗŲŲ ØšŲ
Øą Ø§ŲØ¨ØˇØ§ØąŲØŠ ŲØĨØĩŲØ§Ø ØĒŲØˇŲØš Ø§ŲØĒØ´ØēŲŲ.
|
||||
|
||||
ŲØĒŲ
ØĒØš ØĒŲØŗŲŲ AVC Ø¨Ø¯ŲØŠ ŲØĩŲŲ ØĒØ¨ŲØē 1080PØ Ø¨ØąŲØ§Ų
ØŦ ØĒØąŲ
ŲØ˛ Ø§ŲØĩŲØĒ Opus ØēŲØą Ų
ØĒŲبਠبŗŲØŗØĒ؎دŲ
ØĒØ´ØēŲŲ Ø§ŲŲŲØ¯ŲŲ Ø§ŲŲ
Ø˛ŲØ¯ Ų
Ų Ø¨ŲØ§ŲاØĒ Ø§ŲØĨŲØĒØąŲØĒ Ų
ŲØ§ØąŲØŠŲ Ø¨ØĒŲØŗŲŲ VP9 ØŖŲ AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_title">Ø§ŲØĒØŖØĢبਧØĒ Ø§ŲØŦØ§ŲØ¨ŲØŠ ŲŲ
ØØ§Ųا؊ iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_summary">"âĸ ŲØ§ ŲŲ
ŲŲ ØĒØ´ØēŲŲ Ų
ŲØ§ØˇØš ŲŲØ¯ŲŲ Ø§ŲØŖØˇŲØ§Ų Ø§ŲØŽØ§ØĩØŠ.
|
||||
âĸ ØĒŲØĒŲŲ Ų
ŲØ§ØˇØš اŲŲŲØ¯ŲŲ Ų
Ø¨ŲØąŲا بŲ
ŲØ¯Ø§Øą 1 ØĢاŲŲØŠ."</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_title">Ø§ŲØĒØŖØĢبਧØĒ Ø§ŲØŦØ§ŲØ¨ŲØŠ ŲŲ
ØØ§Ųا؊ Android VR</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_summary">"âĸ Ų
ŲØˇØš ŲŲØ¯ŲŲ Ø§ŲØŖØˇŲØ§Ų ŲØĒØšŲ
Ų ØĒØ´ØēŲŲ
|
||||
âĸ ŲØ§ØĻŲ
ØŠ ŲØ§ØĻŲ
ØŠ Ø§ŲØĩŲØĒ Ų
ŲŲŲØ¯ØŠ
|
||||
âĸ ŲØ§ ŲØĒŲŲØą Ø¨ØŗØĒŲŲ Ų
ØĒŲŲØą
|
||||
âĸ ŲØ§ ŲØĒŲŲØą Ø¨Ø§ŲØĩŲØĒ Ø§ŲØŖØĩŲŲ ŲØ§ ŲØĒŲŲØą Ø§ŲØŖØĩŲŲ"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">ŲØēØŠ Ø§ŲØ¨ØĢ Ø§ŲØĩŲØĒŲ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">ŲØēØŠ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">Ø§ŲØšØąØ¨ŲØŠ</string>
|
||||
<string name="revanced_spoof_video_streams_language_AZ">Azerbaijani</string>
|
||||
<string name="revanced_spoof_video_streams_language_BG">Bulgarian</string>
|
||||
<string name="revanced_spoof_video_streams_language_BN">Bengali</string>
|
||||
<string name="revanced_spoof_video_streams_language_CA">Catalan</string>
|
||||
<string name="revanced_spoof_video_streams_language_CS">Czech</string>
|
||||
<string name="revanced_spoof_video_streams_language_DA">Danish</string>
|
||||
<string name="revanced_spoof_video_streams_language_DE">German</string>
|
||||
<string name="revanced_spoof_video_streams_language_EL">Greek</string>
|
||||
<string name="revanced_spoof_video_streams_language_EN">English</string>
|
||||
<string name="revanced_spoof_video_streams_language_ES">Spanish</string>
|
||||
<string name="revanced_spoof_video_streams_language_ET">Estonian</string>
|
||||
<string name="revanced_spoof_video_streams_language_FA">ŲØ§ØąØŗŲ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FI">Finnish</string>
|
||||
<string name="revanced_spoof_video_streams_language_FR">French</string>
|
||||
<string name="revanced_spoof_video_streams_language_GU">Gujarati</string>
|
||||
<string name="revanced_spoof_video_streams_language_HI">Hindi</string>
|
||||
<string name="revanced_spoof_video_streams_language_HR">Croatian</string>
|
||||
<string name="revanced_spoof_video_streams_language_HU">Hungarian</string>
|
||||
<string name="revanced_spoof_video_streams_language_ID"> Indonesian</string>
|
||||
<string name="revanced_spoof_video_streams_language_IT">Italian</string>
|
||||
<string name="revanced_spoof_video_streams_language_JA">Japanese</string>
|
||||
<string name="revanced_spoof_video_streams_language_KK">Kazakh</string>
|
||||
<string name="revanced_spoof_video_streams_language_KO">Korean</string>
|
||||
<string name="revanced_spoof_video_streams_language_LT">Lithuanian</string>
|
||||
<string name="revanced_spoof_video_streams_language_LV">Latvian</string>
|
||||
<string name="revanced_spoof_video_streams_language_MK">Macedonian</string>
|
||||
<string name="revanced_spoof_video_streams_language_MN">Mongolian</string>
|
||||
<string name="revanced_spoof_video_streams_language_MR">Marathi</string>
|
||||
<string name="revanced_spoof_video_streams_language_MS">Malay</string>
|
||||
<string name="revanced_spoof_video_streams_language_MY">Burmese</string>
|
||||
<string name="revanced_spoof_video_streams_language_NL">Dutch</string>
|
||||
<string name="revanced_spoof_video_streams_language_OR">Odia</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">Punjabi</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">Polish</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">Portuguese (Brazil)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">Portuguese (Portugal)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">Romanian</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Russian</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">Slovak</string>
|
||||
<string name="revanced_spoof_video_streams_language_SL">Slovene</string>
|
||||
<string name="revanced_spoof_video_streams_language_SR">Serbian</string>
|
||||
<string name="revanced_spoof_video_streams_language_SV">Swedish</string>
|
||||
<string name="revanced_spoof_video_streams_language_SW">Swahili</string>
|
||||
<string name="revanced_spoof_video_streams_language_TA">Tamil</string>
|
||||
<string name="revanced_spoof_video_streams_language_TE">Telugu</string>
|
||||
<string name="revanced_spoof_video_streams_language_TH">Thai</string>
|
||||
<string name="revanced_spoof_video_streams_language_TR">Turkish</string>
|
||||
<string name="revanced_spoof_video_streams_language_UK">Ukrainian</string>
|
||||
<string name="revanced_spoof_video_streams_language_UR">Urdu</string>
|
||||
<string name="revanced_spoof_video_streams_language_VI">Vietnamese</string>
|
||||
<string name="revanced_spoof_video_streams_language_ZH">Chinese</string>
|
||||
AVC ŲØ¯ŲŲ ØØ¯ ØŖŲØĩŲ ŲŲØ¯ŲØŠ 1080pØ ŲØ§ ŲØĒŲŲØą ØĒØąŲ
ŲØ˛ Ø§ŲØĩŲØĒ OpusØ ŲØŗŲŲ ŲØŗØĒ؎دŲ
ØĒØ´ØēŲŲ Ø§ŲŲŲØ¯ŲŲ Ø¨ŲØ§ŲاØĒ ØĨŲØĒØąŲØĒ ØŖŲØĢØą Ų
Ų VP9 ØŖŲ AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">Ø§ŲØĸØĢØ§Øą Ø§ŲØŦØ§ŲØ¨ŲØŠ ŲŲ
ØØ§Ųا؊ ŲŲŲØŠ iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"âĸ ŲØ¯ ŲØ§ ŲØĒŲ
ØĒØ´ØēŲŲ Ø§ŲØŖŲŲØ§Ų
ØŖŲ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ اŲŲ
دŲŲØšØŠ
|
||||
âĸ Ų
ØŗØĒŲŲ Ø§ŲØĩŲØĒ Ø§ŲØĢØ§Ø¨ØĒ ØēŲØą Ų
ØĒŲŲØą
|
||||
âĸ ØĒŲØĒŲŲ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ŲØ¨Ų ب 1 ØĢاŲŲØŠ"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Ø§ŲØĸØĢØ§Øą Ø§ŲØŦØ§ŲØ¨ŲØŠ ŲŲ
ØØ§Ųا؊ ŲŲŲØŠ Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"âĸ ŲØ§ØĻŲ
ØŠ اŲŲ
ŲØˇØš Ø§ŲØĩŲØĒŲ Ų
ŲŲŲØ¯ØŠ
|
||||
âĸ Ų
ØŗØĒŲŲ Ø§ŲØĩŲØĒ Ø§ŲØĢØ§Ø¨ØĒ ØēŲØą Ų
ØĒاØ
|
||||
âĸ ŲØąØļ Ø§ŲØĩŲØĒ Ø§ŲØŖØĩŲŲ ØēŲØą Ų
ØĒŲŲØą"</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">âĸ ŲØ§ ŲŲØŦد ØĒØąŲ
ŲØ˛ اŲŲŲØ¯ŲŲ AV1</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">ØšØąØļ ŲŲ ØĨØØĩØ§ØĄØ§ØĒ ØĒŲŲŲØŠ</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">ŲØĒŲ
ØšØąØļ Ųب𠨧بšŲ
ŲŲ ŲŲ ØĨØØĩØ§ØĄØ§ØĒ ØĒŲŲŲØŠ</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">ØĒŲ
ØĨØŽŲØ§ØĄ Ųب𠨧بšŲ
ŲŲ ŲŲ ØĨØØĩØ§ØĄØ§ØĒ ØĒŲŲŲØŠ</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">ŲØēØŠ Ø§ŲØ¨ØĢ Ø§ŲØĩŲØĒŲ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ ŲŲŲØ§ŲØš Ø§ŲØ§ŲØĒØąØ§ØļŲ VR</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -136,6 +136,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.panels.popup.playerPopupPanelsPatch">
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
</patch>
|
||||
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
||||
@@ -155,6 +157,8 @@ Second \"item\" text"</string>
|
||||
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
|
||||
<!-- Shown in the settings preferences, and translations can be any text length. -->
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
@@ -168,8 +172,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
</patch>
|
||||
<patch id="layout.theme.themePatch">
|
||||
@@ -220,6 +222,7 @@ Second \"item\" text"</string>
|
||||
<patch id="interaction.seekbar.enableSlideToSeekPatch">
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<!-- 'no auth' means no authentication -->
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,8 +22,8 @@ Second \"item\" text"</string>
|
||||
<resources>
|
||||
<app id="shared">
|
||||
<patch id="misc.checks.checkEnvironmentPatch">
|
||||
<string name="revanced_check_environment_failed_title">\"ĐŅавŅдСĐĩĐŊĐŊĐĩ ĐŋŅавĐĩŅĐēŅ Đ°ŅŅŅĐžĐ´Đ´ĐˇŅ ĐŊĐĩ ŅдаĐģĐžŅŅ\"</string>
|
||||
<string name="revanced_check_environment_dialog_open_official_source_button">\"ĐĐ´ĐēŅŅŅŅ Đ°ŅŅŅŅĐšĐŊŅ Đ˛ŅĐą-ŅаКŅ\"</string>
|
||||
<string name="revanced_check_environment_failed_title">ĐŅавĐĩŅĐēŅ ĐŊĐĩ ĐŋŅОКдСĐĩĐŊŅ</string>
|
||||
<string name="revanced_check_environment_dialog_open_official_source_button">ĐĐ´ĐēŅŅŅŅ Đ°ŅŅŅŅĐšĐŊŅ Đ˛ŅĐą-ŅаКŅ</string>
|
||||
<string name="revanced_check_environment_dialog_ignore_button">ĐĐŗĐŊаŅаваŅŅ</string>
|
||||
<string name="revanced_check_environment_failed_message"><h5>ĐŅŅа дадаŅаĐē вŅдавОŅĐŊа ĐŊĐĩ С\'ŅŅĐģŅĐĩŅŅа ĐŋаŅŅаĐŧ.</h5><br>ĐŅŅа дадаŅаĐē ĐŧĐžĐļа ĐŋŅаŅаваŅŅ ĐŊŅĐŋŅавŅĐģŅĐŊа, а ŅаĐēŅаĐŧа ĐŧĐžĐļа ĐąŅŅŅ <b>ĐŊĐĩĐąŅŅĐŋĐĩŅĐŊŅĐŧ айО ĐŊĐ°Đ˛Đ°Ņ ĐŊĐĩĐąŅŅĐŋĐĩŅĐŊŅĐŧ Ņ Đ˛ŅĐēаŅŅŅŅаĐŊĐŊŅ</b>.<br><br>ĐŅŅŅŅ ĐŋŅавĐĩŅĐēŅ Đ°ĐˇĐŊаŅаŅŅŅ, ŅŅĐž ĐŗŅŅа дадаŅаĐē ĐąŅĐģĐž ĐˇĐ°ĐŗĐ°Đ´Đ´ĐˇŅ ĐŋĐĩŅаŅОйĐģĐĩĐŊа айО аŅŅŅĐŧаĐŊа ад ĐēĐ°ĐŗĐžŅŅŅŅ ŅĐŊŅĐ°ĐŗĐ°:<br><br><small>%1$s</small><br>ĐаŅŅОКĐģŅва ŅŅĐēаĐŧĐĩĐŊĐ´ŅĐĩŅŅа <b>вŅдаĐģŅŅŅ ĐŗŅŅŅ Đ´Đ°Đ´Đ°ŅаĐē Ņ ĐŋĐĩŅаŅайŅŅŅ ŅĐŗĐž ŅаĐŧаŅŅОКĐŊа</b>, Đēай ĐŋĐĩŅаĐēаĐŊаŅŅа, ŅŅĐž Đ˛Ņ Đ˛ŅĐēаŅŅŅŅĐžŅваĐĩŅĐĩ ĐŋŅавĐĩŅаĐŊŅ Ņ ĐąŅŅĐŋĐĩŅĐŊŅ Đ´Đ°Đ´Đ°ŅаĐē.<p><br>ĐаĐģŅ ŅĐŗĐŊаŅаваŅŅ, ĐŗŅŅа ĐŋаĐŋŅŅŅĐ´ĐļаĐŊĐŊĐĩ ĐąŅдСĐĩ ĐŋаĐēаСаĐŊа ŅĐžĐģŅĐēŅ Đ´Đ˛Đ° ŅаСŅ.</string>
|
||||
<string name="revanced_check_environment_not_same_patching_device">ĐĐ´ĐēаŅŅĐēŅаваĐŊа ĐŊа ŅĐŊŅаК ĐŋŅŅĐģадСĐĩ</string>
|
||||
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">ĐаŅа ŅŅваŅŅĐŊĐŊŅ APK ĐŋаŅĐēОдĐļаĐŊа</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">ĐаĐģадŅ</string>
|
||||
<string name="revanced_settings_title">ReVanced</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">ĐŅ Ņ
ĐžŅаŅĐĩ ĐŋŅаŅŅĐŗĐŊŅŅŅ?</string>
|
||||
<string name="revanced_settings_reset">ĐĄĐēŅĐŊŅŅŅ</string>
|
||||
@@ -43,6 +44,62 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_import_reset">ĐаĐģĐ°Đ´Ņ ReVanced ŅĐēŅĐŊŅŅŅ Đ´Đ° ŅŅаĐŊдаŅŅĐŊŅŅ
</string>
|
||||
<string name="revanced_settings_import_success">ĐĐŧĐŋаŅŅаваĐŊа %d ĐŊаĐģад</string>
|
||||
<string name="revanced_settings_import_failure_parse">ĐаĐŧŅĐģĐēа ŅĐŧĐŋаŅŅŅ: %s</string>
|
||||
<string name="revanced_language_title">ĐОва ReVanced</string>
|
||||
<string name="revanced_language_user_dialog_message">"ĐĐĩŅаĐēĐģĐ°Đ´Ņ Đ´ĐģŅ ĐŊĐĩĐēаŅĐžŅŅŅ
ĐŧĐžŅ ĐŧĐžĐŗŅŅŅ ĐąŅŅŅ Đ°Đ´ŅŅŅĐŊŅĐŧŅ Đ°ĐąĐž ĐŊŅĐŋĐžŅĐŊŅĐŧŅ.
|
||||
|
||||
Đай дадаŅŅ ĐŊОвŅŅ ĐŧОвŅ, ĐŊавĐĩдаКŅĐĩ translate.revanced.app"</string>
|
||||
<string name="revanced_language_DEFAULT">ĐОва ĐŋŅĐ°ĐŗŅаĐŧŅ</string>
|
||||
<string name="revanced_language_AR">ĐŅайŅĐēаŅ</string>
|
||||
<string name="revanced_language_AZ">ĐСĐĩŅйаКдĐļаĐŊŅĐēŅ</string>
|
||||
<string name="revanced_language_BG">ĐаĐģĐŗĐ°ŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_BN">ĐĐĩĐŊĐŗĐ°ĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_CA">ĐаŅаĐģĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_CS">ЧŅŅŅĐēŅ</string>
|
||||
<string name="revanced_language_DA">ĐаŅĐēŅ</string>
|
||||
<string name="revanced_language_DE">ĐŅĐŧĐĩŅĐēŅ</string>
|
||||
<string name="revanced_language_EL">ĐŅŅŅĐēŅ</string>
|
||||
<string name="revanced_language_EN">ĐĐŊĐŗĐģŅĐšŅĐēаŅ</string>
|
||||
<string name="revanced_language_ES">ĐŅĐŋаĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_ET">ĐŅŅĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_FA">ĐĐĩŅŅŅĐ´ŅĐēаŅ</string>
|
||||
<string name="revanced_language_FI">ФŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_FR">ФŅаĐŊŅŅСŅĐēаŅ</string>
|
||||
<string name="revanced_language_GU">ĐŅĐ´ĐļаŅаŅŅ</string>
|
||||
<string name="revanced_language_HI">ĐĨŅĐŊдСŅ</string>
|
||||
<string name="revanced_language_HR">ĐĨаŅваŅĐēаŅ</string>
|
||||
<string name="revanced_language_HU">ĐĐĩĐŊĐŗĐĩŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_ID">ĐĐŊдаĐŊĐĩСŅĐšŅĐēаŅ</string>
|
||||
<string name="revanced_language_IT">ĐŅаĐģŅŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_JA">Đ¯ĐŋĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_KK">ĐаСаŅ
ŅĐēаŅ</string>
|
||||
<string name="revanced_language_KO">ĐаŅŅĐšŅĐēаŅ</string>
|
||||
<string name="revanced_language_LT">ĐŅŅĐžŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_LV">ĐаŅŅŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_MK">ĐаĐēĐĩĐ´ĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_MN">ĐаĐŊĐŗĐžĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_MR">ĐаĐģаŅĐģаĐŧ</string>
|
||||
<string name="revanced_language_MS">ĐаĐģаКŅĐēаŅ</string>
|
||||
<string name="revanced_language_MY">ĐŅŅĐŧаĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_NL">ĐŅĐ´ŅŅĐģаĐŊĐ´ŅĐēаŅ</string>
|
||||
<string name="revanced_language_OR">ĐĐ´ŅŅ</string>
|
||||
<string name="revanced_language_PA">ĐĐĩĐŊĐ´ĐļайŅ</string>
|
||||
<string name="revanced_language_PL">ĐĐžĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_PT">ĐаŅŅŅĐŗĐ°ĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_RO">Đ ŅĐŧŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_RU">Đ ŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_SK">ĐĄĐģаваŅĐēаŅ</string>
|
||||
<string name="revanced_language_SL">ĐĄĐģавĐĩĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_SR">ĐĄĐĩŅĐąŅĐēаŅ</string>
|
||||
<string name="revanced_language_SV">ШвĐĩĐ´ŅĐēаŅ</string>
|
||||
<string name="revanced_language_SW">ĐĄŅаŅ
ŅĐģŅ</string>
|
||||
<string name="revanced_language_TA">ĐĸаĐŧŅĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_language_TE">ĐĸŅĐģŅĐŗŅ</string>
|
||||
<string name="revanced_language_TH">ĐĸаКŅĐēаŅ</string>
|
||||
<string name="revanced_language_TR">ĐĸŅŅĐĩŅĐēаŅ</string>
|
||||
<string name="revanced_language_UK">ĐŖĐēŅаŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_language_UR">ĐŖŅĐ´Ņ</string>
|
||||
<string name="revanced_language_VI">Đ\'ĐĩŅĐŊаĐŧŅĐēаŅ</string>
|
||||
<string name="revanced_language_ZH">ĐŅŅаКŅĐēаŅ</string>
|
||||
<string name="revanced_pref_import_export_title">ĐĐŧĐŋаŅŅ / ĐĐēŅĐŋаŅŅ</string>
|
||||
<string name="revanced_pref_import_export_summary">ĐĐŧĐŋаŅŅ / ĐĐēŅĐŋаŅŅ ĐŊаĐģад ReVanced</string>
|
||||
<!-- Settings about dialog. -->
|
||||
@@ -77,13 +134,16 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_screen_01_ads_title">ĐĐą\"ŅвŅ</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">ĐĐģŅŅŅŅĐŊаŅŅŅĐŊŅŅ ĐŧŅĐŊŅŅŅŅŅŅ</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">ĐаŅĐŧŅŅŅ</string>
|
||||
<string name="revanced_settings_screen_04_player_title">ĐŅĐģĐĩŅ</string>
|
||||
<string name="revanced_settings_screen_05_general_title">ĐĐĩĐŊĐĩŅаĐģŅĐŊĐ°Ņ ĐŋĐģаĐŊŅŅĐžŅĐēа</string>
|
||||
<string name="revanced_settings_screen_04_general_title">ĐĐŗŅĐģŅĐŊаĐĩ</string>
|
||||
<string name="revanced_settings_screen_05_player_title">ĐĐģŅĐĩŅ</string>
|
||||
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
|
||||
<string name="revanced_settings_screen_07_seekbar_title">ĐаĐŊŅĐģŅ ĐŋĐžŅŅĐēŅ</string>
|
||||
<string name="revanced_settings_screen_08_swipe_controls_title">ĐĐģĐĩĐŧĐĩĐŊŅŅ ĐēŅŅаваĐŊĐŊŅ ĐŋаĐģŅŅаĐŧ</string>
|
||||
<string name="revanced_settings_screen_11_misc_title">РОСĐŊаĐĩ</string>
|
||||
<string name="revanced_settings_screen_12_video_title">ĐŅĐ´Ņа</string>
|
||||
<string name="revanced_restore_old_settings_menus_title">ĐĐ´ĐŊавŅŅŅ ŅŅаŅĐžĐĩ ĐŧĐĩĐŊŅ ĐŊаĐģад</string>
|
||||
<string name="revanced_restore_old_settings_menus_summary_on">ĐĄŅаŅŅŅ ĐŧĐĩĐŊŅ ĐŊаĐģад ĐŋаĐēаСваŅŅŅа</string>
|
||||
<string name="revanced_restore_old_settings_menus_summary_off">ĐĄŅаŅŅŅ ĐŧĐĩĐŊŅ ĐŊаĐģад ĐŊĐĩ ĐŋаĐēаСваŅŅŅа</string>
|
||||
</patch>
|
||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||
<string name="revanced_shorts_disable_background_playback_title">ĐĐ´ĐēĐģŅŅŅŅŅ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊĐĩ Shorts Ņ ŅĐžĐŊавŅĐŧ</string>
|
||||
@@ -446,6 +506,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_overlay_background_alpha_summary">ĐаŅĐŊаŅŅŅ ŅĐžĐŊŅ ĐŊаĐēĐģадаĐŊĐŊŅ ĐŋаĐģŅŅаĐŧ</string>
|
||||
<string name="revanced_swipe_threshold_title">ĐаŅĐžĐŗ вĐĩĐģŅŅŅĐŊŅ ĐŋаĐģŅŅаĐŧ</string>
|
||||
<string name="revanced_swipe_threshold_summary">ĐĐĩĐģŅŅŅĐŊŅ ĐŋаŅĐžĐŗĐ°Đ˛Đ°ĐŗĐ° СĐŊаŅŅĐŊĐŊŅ Đ´ĐģŅ ĐŋŅавŅдСĐĩĐŊĐŊŅ ĐŋаĐģŅŅаĐŧ</string>
|
||||
<string name="revanced_swipe_change_video_title">ĐŖĐēĐģŅŅŅŅŅ ĐˇŅĐŧĐĩĐŊŅ Đ˛ŅĐ´Ņа ĐŋŅаС ĐŋŅавŅдСĐĩĐŊĐŊĐĩ ĐŋаĐģŅŅаĐŧ</string>
|
||||
<string name="revanced_swipe_change_video_summary_on">ĐŅавŅдСĐĩĐŊĐŊĐĩ ĐŋаĐģŅŅаĐŧ Ņ ŅŅĐļŅĐŧĐĩ ĐŋĐžŅĐŊĐ°ĐŗĐ° ŅĐēŅаĐŊа СŅĐŧĐĩĐŊŅŅŅ Đ˛ŅĐ´Ņа ĐŊа ĐŊаŅŅŅĐŋĐŊаĐĩ/ĐŋаĐŋŅŅŅĐ´ĐŊŅĐĩ</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">ĐŅавŅдСĐĩĐŊĐŊĐĩ ĐŋаĐģŅŅаĐŧ Ņ ŅŅĐļŅĐŧĐĩ ĐŋĐžŅĐŊĐ°ĐŗĐ° ŅĐēŅаĐŊа ĐŊĐĩ СŅĐŧĐĩĐŊŅŅŅ Đ˛ŅĐ´Ņа ĐŊа ĐŊаŅŅŅĐŋĐŊаĐĩ/ĐŋаĐŋŅŅŅĐ´ĐŊŅĐĩ</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">ĐĐ´ĐēĐģŅŅŅŅŅ Đ°ŅŅаĐŧаŅŅŅĐŊŅŅ ŅŅŅŅŅ</string>
|
||||
@@ -629,15 +692,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_player_screen_summary">ĐĄŅ
аваŅŅ Đ°ĐąĐž ĐŋаĐēаСаŅŅ ĐēаĐŧĐŋаĐŊĐĩĐŊŅŅ Ņ ĐŋŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐēŅ Shorts</string>
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">ĐĄŅ
аваŅŅ ŅĐžŅŅŅ Ņ Ņ
аŅĐŊŅĐš ŅŅŅĐļŅŅ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Shorts Ņ ŅŅŅĐļŅŅ Ņ
аŅĐŊŅĐš ŅŅаŅĐžĐŊĐēŅ ŅŅ
аваĐŊŅ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Shorts Ņ ŅŅŅĐļŅŅ Ņ
аŅĐŊŅĐš ŅŅаŅĐžĐŊĐēŅ ĐŋаĐēаСаĐŊŅ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">ĐĄŅ
аваĐŊŅ Ņ ŅŅŅĐļŅŅ Ņ ĐˇĐ˛ŅСаĐŊŅŅ
вŅĐ´Ņа</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">ĐаĐēаСаĐŊŅ Ņ ŅŅŅĐļŅŅ Ņ ĐˇĐ˛ŅСаĐŊŅŅ
вŅĐ´Ņа</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">ĐĄŅ
аваŅŅ Shorts Ņ ŅŅŅĐļŅŅ ĐŋадĐŋŅŅĐēŅ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Shorts Ņ ŅŅŅĐļŅŅ ĐŋадĐŋŅŅĐēŅ ŅŅ
аваĐŊŅ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Shorts Ņ ŅŅŅĐļŅŅ ĐŋадĐŋŅŅĐēŅ ĐŋаĐēаСаĐŊŅ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">ĐĄŅ
аваĐŊа Ņ ŅŅŅĐļŅŅ ĐŋадĐŋŅŅаĐē</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">ĐаĐēаСаĐŊа Ņ ŅŅŅĐļŅŅ ĐŋадĐŋŅŅаĐē</string>
|
||||
<string name="revanced_hide_shorts_search_title">ĐĄŅ
аваŅŅ Shorts Ņ Đ˛ŅĐŊŅĐēаŅ
ĐŋĐžŅŅĐēŅ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Shorts Ņ Đ˛ŅĐŊŅĐēаŅ
ĐŋĐžŅŅĐēŅ ŅŅ
аваĐŊŅ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Shorts Ņ Đ˛ŅĐŊŅĐēаŅ
ĐŋĐžŅŅĐēŅ ĐŋаĐēаСаĐŊŅ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">ĐĄŅ
аваĐŊŅ Ņ Đ˛ŅĐŊŅĐēаŅ
ĐŋĐžŅŅĐēŅ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">ĐаĐēаСаĐŊа Ņ Đ˛ŅĐŊŅĐēаŅ
ĐŋĐžŅŅĐēŅ</string>
|
||||
<string name="revanced_hide_shorts_history_title">ĐĄŅ
аваŅŅ Shorts С ĐŗŅŅŅĐžŅŅŅ ĐŋŅĐ°ĐŗĐģŅдаŅ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">ĐĄŅ
аваĐŊа Ņ ĐŗŅŅŅĐžŅŅŅ ĐŋŅĐ°ĐŗĐģŅдаŅ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">ĐаĐēаСаĐŊŅ Ņ ĐŗŅŅŅĐžŅŅŅ ĐŋŅĐ°ĐŗĐģŅдаŅ</string>
|
||||
<!-- 'join' should be translated using the same localized wording YouTube displays for the button. -->
|
||||
<string name="revanced_hide_shorts_join_button_title">ĐĄŅ
аваŅŅ ĐēĐŊĐžĐŋĐēŅ Đ´Đ°ĐģŅŅŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_join_button_summary_on">ĐĐŊĐžĐŋĐēа ÂĢĐаĐģŅŅŅŅŅаÂģ ŅŅ
аваĐŊа</string>
|
||||
@@ -668,8 +734,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_on">ĐĐŊĐžĐŋĐēа вŅĐēаŅŅŅŅаĐŊĐŊŅ ŅайĐģĐžĐŊŅ ŅŅ
аваĐŊа</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_off">ĐĐŊĐžĐŋĐēа вŅĐēаŅŅŅŅаĐŊĐŊŅ ŅайĐģĐžĐŊŅ ĐŋаĐēаСаĐŊа</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_title">ĐĄŅ
аваŅŅ ĐēĐŊĐžĐŋĐēŅ ĐąŅĐ´ŅŅŅŅ
</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">ĐĐŊĐžĐŋĐēа âŦī¸ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēиâŦī¸ ŅĐēŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">ĐĐŊĐžĐŋĐēа âŦī¸ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēиâŦī¸ ĐžŅОйŅаĐļаĐĩŅŅŅ</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">ĐĐŊĐžĐŋĐēа ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēи ŅĐēŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">ĐĐŊĐžĐŋĐēа ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēи ĐžŅОйŅаĐļаĐĩŅŅŅ</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_title">ĐĄĐēŅŅŅŅ ĐēĐŊĐžĐŋĐēŅ Ņ ĐˇĐĩĐģŅĐŊŅĐŧ ŅĐēŅаĐŊĐžĐŧ Shorts</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_on">ĐĐŊĐžĐŋĐēа Ņ ĐˇĐĩĐģŅĐŊŅĐŧ ŅĐēŅаĐŊĐžĐŧ Shorts ŅĐēŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_off">ĐĐŊĐžĐŋĐēа Ņ ĐˇĐĩĐģŅĐŊŅĐŧ ŅĐēŅаĐŊĐžĐŧ Shorts ĐžŅОйŅаĐļаĐĩŅŅŅ</string>
|
||||
@@ -739,6 +805,13 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_on">ĐŖŅĐŋĐģŅваĐģŅĐŊŅŅ ĐŋаĐŊŅĐģŅ ĐŋŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐēа ŅŅ
аваĐŊŅŅ</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_off">ĐаĐēаСваŅŅŅа ŅŅĐŋĐģŅваĐģŅĐŊŅŅ ĐŋаĐŊŅĐģŅ ĐŋŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐēа</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
<string name="revanced_exit_fullscreen_title">ĐŅĐšŅŅŅ Đˇ ĐŋĐžŅĐŊаŅĐēŅаĐŊĐŊĐ°ĐŗĐ° ŅŅĐļŅĐŧŅ Ņ ĐēаĐŊŅŅ Đ˛ŅĐ´Ņа</string>
|
||||
<string name="revanced_exit_fullscreen_entry_1">ĐĐ´ĐēĐģŅŅаĐŊа</string>
|
||||
<string name="revanced_exit_fullscreen_entry_2">ĐаŅŅŅŅŅ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_3">ĐаĐŊĐ´ŅаŅŅ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_4">ĐаŅŅŅŅŅ Ņ ĐģаĐŊĐ´ŅаŅŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">ĐŅĐēŅŅваŅŅ Đ˛Đ¸Đ´ĐĩĐž ĐŊа вĐĩŅŅ ŅĐēŅаĐŊ в ĐŋĐžŅŅŅĐĩŅĐŊĐžĐŧ ŅĐĩĐļиĐŧĐĩ</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_on">ĐидĐĩĐž ĐžŅĐēŅŅваŅŅŅŅ ĐŊа вĐĩŅŅ ŅĐēŅаĐŊ</string>
|
||||
@@ -1008,6 +1081,23 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_reset">ĐĄĐēŅĐŊŅŅŅ</string>
|
||||
<string name="revanced_sb_about">ĐŅа ĐŋŅĐ°ĐŗŅаĐŧŅ</string>
|
||||
<string name="revanced_sb_about_api_sum">ĐадСĐĩĐŊŅŅ ĐŋŅадаŅŅаŅĐģŅŅŅŅа API SponsorBlock. ĐаŅŅŅĐŊŅŅĐĩ ŅŅŅ, Đēай давĐĩдаŅŅа йОĐģŅŅ Ņ ĐŋĐ°ĐŗĐģŅдСĐĩŅŅ ŅĐŋаĐŧĐŋĐžŅĐēŅ Đ´ĐģŅ ŅĐŊŅŅŅ
ĐŋĐģаŅŅĐžŅĐŧаŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
<string name="revanced_change_form_factor_title">ФаŅĐŧĐ°Ņ ŅĐēŅаĐŊа</string>
|
||||
<string name="revanced_change_form_factor_entry_1">Đа СĐŧаŅŅаĐŊĐŊŅ</string>
|
||||
<string name="revanced_change_form_factor_entry_2">ĐĸŅĐģĐĩŅĐžĐŊ</string>
|
||||
<string name="revanced_change_form_factor_entry_3">ĐĐģаĐŊŅŅŅ</string>
|
||||
<string name="revanced_change_form_factor_entry_4">ĐŅŅаĐŧайŅĐģŅĐŊŅ</string>
|
||||
<string name="revanced_change_form_factor_user_dialog_message">"ĐĐŧĐĩĐŊŅ ŅĐēĐģŅŅаŅŅŅ:
|
||||
|
||||
РаŅĐēĐģадĐēа ĐŋĐģаĐŊŅŅŅа
|
||||
âĸ ĐавĐĩдаĐŧĐģĐĩĐŊĐŊŅ ŅŅĐŋĐžĐģŅĐŊаŅŅŅ ŅŅ
аваĐŊŅ
|
||||
|
||||
РаŅĐēĐģадĐēа аŅŅаĐŧайŅĐģŅ
|
||||
âĸ ĐĐĩĐŊŅ ĐŗŅŅŅĐžŅŅŅ ĐŋŅĐ°ĐŗĐģŅĐ´Đ°Ņ ŅŅ
аваĐŊа
|
||||
âĸ ĐĐ´ĐŊĐžŅĐģĐĩĐŊа ŅĐēĐģадĐēа ÂĢĐаŅĐģĐĩдаваŅŅÂģ
|
||||
âĸ Đ ĐžĐģŅĐēŅ Shorts адĐēŅŅваŅŅŅа Ņ ĐˇĐ˛ŅŅаКĐŊŅĐŧ ĐŋŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐēŅ
|
||||
âĸ ĐĄŅŅĐļĐēа аŅĐŗĐ°ĐŊŅСаваĐŊа Đŋа ŅŅĐŧаŅ
Ņ ĐēаĐŊаĐģаŅ
"</string>
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<string name="revanced_spoof_app_version_title">ĐĐĩŅŅŅŅ ĐŋŅĐ°ĐŗŅаĐŧŅ Spoof</string>
|
||||
@@ -1022,6 +1112,7 @@ Second \"item\" text"</string>
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
<string name="revanced_spoof_app_version_target_title">ĐадŅОйĐēа ĐŧŅŅаваК вĐĩŅŅŅŅ ĐŋŅĐ°ĐŗŅаĐŧŅ</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 â ĐĐžŅŅŅаĐŊОвиŅŅ ŅŅаŅŅĐĩ СĐŊаŅĐēи ĐŋĐģĐĩĐĩŅа Shorts</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.26.42 - ĐĐ´ĐŊаŅĐģĐĩĐŊĐŊĐĩ ŅŅаŅŅŅ
СĐŊаŅĐēĐžŅ ĐŊавŅĐŗĐ°ŅŅŅ</string>
|
||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_1">18.33.40 - ĐĐ´ĐŊаŅĐģĐĩĐŊĐŊĐĩ RYD ĐŊа Shorts Ņ ŅŅĐļŅĐŧĐĩ ŅĐŊĐēĐžĐŗĐŊŅŅа</string>
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_2">18.20.39 - ĐĐ´ĐŊавŅŅŅ Ņ
ŅŅĐēаŅŅŅ ŅŅŅĐžĐēĐ°ĐŗĐ° вŅĐ´Ņа & ŅĐēаŅĐŊаĐĩ ĐŧĐĩĐŊŅ</string>
|
||||
@@ -1065,12 +1156,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_on">Shorts в ŅĐžĐŊОвОĐŧ ŅĐĩĐļиĐŧĐĩ ĐąŅĐ´ŅŅ Đ˛ĐžŅĐŋŅОиСвОдиŅŅŅŅ Đ°Đ˛ŅĐžĐŧаŅиŅĐĩŅĐēи</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_off">Shorts в ŅĐžĐŊОвОĐŧ ŅĐĩĐļиĐŧĐĩ ĐąŅĐ´ŅŅ ĐŋОвŅĐžŅŅŅŅŅŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
<string name="revanced_tablet_layout_title">ĐŖĐēĐģŅŅŅŅŅ ĐŧаĐēĐĩŅ ĐŋĐģаĐŊŅŅŅа</string>
|
||||
<string name="revanced_tablet_layout_summary_on">ĐаĐēĐĩŅ ĐŋĐģаĐŊŅŅŅа ŅĐēĐģŅŅаĐŊŅ</string>
|
||||
<string name="revanced_tablet_layout_summary_off">ĐаĐēĐĩŅ ĐŋĐģаĐŊŅŅŅа адĐēĐģŅŅаĐŊŅ</string>
|
||||
<string name="revanced_tablet_layout_user_dialog_message">ĐавĐĩдаĐŧĐģĐĩĐŊĐŊŅ Ņ ŅŅĐŋĐžĐģŅĐŊаŅŅŅ ĐŊĐĩ адĐģŅŅŅŅĐžŅваŅŅŅа ĐŊа ĐŋĐģаĐŊŅŅŅĐĩ</string>
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
<string name="revanced_miniplayer_screen_title">ĐŅĐŊŅ-ĐŋĐģŅĐĩŅ</string>
|
||||
<string name="revanced_miniplayer_screen_summary">ĐĐŧŅĐŊŅŅĐĩ ŅŅŅĐģŅ ĐŧŅĐŊŅĐŧŅСаваĐŊĐ°ĐŗĐ° ĐŋĐģŅĐĩŅа Ņ ĐŋŅĐ°ĐŗŅаĐŧĐĩ</string>
|
||||
@@ -1234,6 +1319,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_force_original_audio_title">ĐŅĐŧŅŅаĐŊаĐĩ аŅŅĐŗŅĐŊаĐģŅĐŊаĐĩ аŅĐ´ŅŅ</string>
|
||||
<string name="revanced_force_original_audio_summary_on">ĐŅĐēаŅŅŅŅаĐŊĐŊĐĩ аŅŅĐŗŅĐŊаĐģŅĐŊĐ°ĐŗĐ° аŅĐ´ŅŅ</string>
|
||||
<string name="revanced_force_original_audio_summary_off">ĐŅĐēаŅŅŅŅаĐŊĐŊĐĩ аŅĐ´ŅŅ Đŋа СĐŧаŅŅаĐŊĐŊŅ</string>
|
||||
<string name="revanced_force_original_audio_not_available">Đай вŅĐēаŅŅŅŅĐžŅваŅŅ ĐŗŅŅŅŅ ŅŅĐŊĐēŅŅŅ, СĐŧĐĩĐŊŅŅĐĩ ŅĐŋаŅŅĐŊĐŗ ĐŋаŅĐžĐēŅ ĐŊа ŅŅĐŋ ĐēĐģŅĐĩĐŊŅа iOS</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
|
||||
@@ -1261,6 +1347,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">ĐĐĩŅŅаĐŊдаŅŅĐŊŅŅ Ņ
ŅŅĐēаŅŅŅ ĐŋавŅĐŊĐŊŅ ĐąŅŅŅ ĐŧĐĩĐŊŅ ĐˇĐ° %s</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">ĐĐĩŅаĐŋŅаŅĐ´ĐŊŅŅ ĐŊĐĩŅŅаĐŊдаŅŅĐŊŅŅ Ņ
ŅŅĐēаŅŅŅ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊŅ</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">ĐŅŅĐž</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">ĐŖĐģаŅĐŊŅ Ņ
ŅŅĐēаŅŅŅ ĐŊаŅŅŅĐēŅ Ņ ŅŅŅŅĐŧаĐŊĐŊŅ</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">ĐĨŅŅĐēаŅŅŅ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊŅ ĐŧŅĐļ 0-8</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">ĐаĐŋĐžĐŧĐŊŅŅĐĩ СĐŧĐĩĐŊŅ Ņ
ŅŅĐēаŅŅŅ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊŅ</string>
|
||||
@@ -1289,74 +1377,27 @@ Second \"item\" text"</string>
|
||||
ĐŅĐ°ĐšĐŗŅаваĐŊĐŊĐĩ вŅĐ´Ņа ĐŧĐžĐļа ĐŊĐĩ ĐŋŅаŅаваŅŅ"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">ĐĐ´ĐēĐģŅŅŅĐŊĐŊĐĩ ĐŗŅŅаК ĐŊаĐģĐ°Đ´Ņ ĐŧĐžĐļа вŅĐēĐģŅĐēаŅŅ ĐŋŅайĐģĐĩĐŧŅ Đˇ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊĐĩĐŧ вŅĐ´Ņа.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">ĐĐģиĐĩĐŊŅ ĐŋĐž ŅĐŧĐžĐģŅаĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ĐŅиĐŊŅдиŅĐĩĐģŅĐŊĐž AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ĐидĐĩĐžĐēОдĐĩĐē ĐŋŅиĐŊŅдиŅĐĩĐģŅĐŊĐž ŅŅŅаĐŊОвĐģĐĩĐŊ в AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ĐидĐĩĐžĐēОдĐĩĐē ĐžĐŋŅĐĩĐ´ĐĩĐģŅĐĩŅŅŅ Đ°Đ˛ŅĐžĐŧаŅиŅĐĩŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ĐŖĐēĐģŅŅŅĐŊĐŊĐĩ ĐŗŅŅĐ°ĐŗĐ° ĐŧĐžĐļа ĐŋаĐģĐĩĐŋŅŅŅŅ ŅŅŅĐŧŅĐŊ ŅĐģŅĐļĐąŅ ĐąĐ°ŅаŅŅŅ Ņ Đ˛ŅĐŋŅавŅŅŅ ĐˇĐ°ŅĐēаĐŊĐŊĐĩ вŅĐ´Ņа.
|
||||
<!-- 'no auth' means no authentication -->
|
||||
<string name="revanced_spoof_video_streams_client_type_android_vr_no_auth">Android VR (ĐŊŅĐŧа аŅŅŅĐŊŅŅŅŅĐēаŅŅŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ĐŅĐŧŅŅŅŅŅ iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ĐŅĐ´ŅаĐēaĐ´ŅĐē СаŅŅĐēŅаваĐŊŅ Ņ AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ĐŅĐ´ŅаĐēaĐ´ŅĐē вŅСĐŊаŅаĐĩŅŅа аŅŅаĐŧаŅŅŅĐŊа</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ĐŖĐēĐģŅŅŅĐŊĐŊĐĩ ĐŗŅŅĐ°ĐŗĐ° ĐŧĐžĐļа ĐŋаĐģĐĩĐŋŅŅŅŅ ŅĐ°Ņ Đ°ŅŅаĐŊĐžĐŧĐŊаК ĐŋŅаŅŅ Ņ Đ˛ŅĐŋŅавŅŅŅ ĐˇĐ°ŅĐēаĐŊĐŊĐĩ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊŅ.
|
||||
|
||||
AVC ĐŧаĐĩ ĐŧаĐēŅŅĐŧаĐģŅĐŊŅŅ ŅаСдСŅĐģŅĐģŅĐŊаŅŅŅ 1080p, аŅĐ´ŅŅĐēадŅĐēĐ°Ņ Opus ĐŊĐĩдаŅŅŅĐŋĐŊŅ, Ņ Đ˛ŅĐ´Ņа ĐąŅдСĐĩ вŅĐēаŅŅŅŅĐžŅваŅŅ ĐąĐžĐģŅŅ ĐĐŊŅŅŅĐŊŅŅ-даĐŊŅŅ
, ŅŅĐŧ VP9 айО AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_title">ĐайОŅĐŊŅŅ ŅŅĐĩĐēŅŅ ĐŋадĐŧĐĩĐŊŅ iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_summary">"âĸ ĐŅŅваŅĐŊŅŅ Đ´ĐˇŅŅŅŅŅŅ Đ˛ŅĐ´Ņа ĐŧĐžĐŗŅŅŅ ĐŊĐĩ ĐŋŅĐ°ĐšĐŗŅаваŅŅа
|
||||
AVC ĐŧаĐĩ ĐŧаĐēŅŅĐŧаĐģŅĐŊаĐĩ даСвОĐģ 1080p, аŅĐ´ŅŅĐēадŅĐē Opus ĐŊĐĩдаŅŅŅĐŋĐŊŅ, а ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊĐĩ вŅĐ´Ņа ĐąŅдСĐĩ вŅĐēаŅŅŅŅĐžŅваŅŅ ĐąĐžĐģŅŅ ŅĐŊŅŅŅĐŊŅŅ-даĐŊŅŅ
, ŅŅĐŧ VP9 айО AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">ĐайОŅĐŊŅŅ ŅŅĐĩĐēŅŅ ĐŋадŅОйĐēŅ iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"âĸ ФŅĐģŅĐŧŅ Đ°ĐąĐž ĐŋĐģаŅĐŊŅŅ Đ˛ŅĐ´Ņа ĐŧĐžĐŗŅŅŅ ĐŊĐĩ ĐŋŅĐ°ĐšĐŗŅаваŅŅа
|
||||
âĸ ĐĄŅайŅĐģŅĐŊĐ°Ņ ĐŗŅŅĐŊаŅŅŅ ĐŊĐĩдаŅŅŅĐŋĐŊаŅ
|
||||
âĸ ĐŅĐ´Ņа СаĐēаĐŊŅваŅŅŅа ĐŊа 1 ŅĐĩĐēŅĐŊĐ´Ņ ŅаĐŊĐĩĐš"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_title">ĐОйОŅĐŊŅĐĩ ŅŅŅĐĩĐēŅŅ ĐŋОдĐŧĐĩĐŊŅ Android VR</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_summary">"âĸ ĐСŅŅŅŅŅŅ Đ˛ŅĐ´Ņа ĐŧĐžĐŗŅŅŅ ĐŊĐĩ ĐŋŅĐ°ĐšĐŗŅаваŅŅа
|
||||
âĸ ĐĐĩĐŊŅ ĐŗŅĐēавŅŅ
даŅĐžĐļаĐē адŅŅŅĐŊŅŅаĐĩ
|
||||
<string name="revanced_spoof_video_streams_about_android_title">ĐОйŅŅĐŊŅŅ ŅŅĐĩĐēŅŅ ĐŋадŅОйĐēŅ Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"âĸ ĐĐĩĐŊŅ ĐŗŅĐēавОК даŅĐžĐļĐēŅ Đ°Đ´ŅŅŅĐŊŅŅаĐĩ
|
||||
âĸ ĐĄŅайŅĐģŅĐŊŅ ĐŗŅĐē ĐŊĐĩдаŅŅŅĐŋĐŊŅ
|
||||
âĸ ĐŅŅĐŧŅŅОваĐĩ вŅĐēаŅŅŅŅаĐŊĐŊĐĩ аŅŅĐŗŅĐŊаĐģŅĐŊĐ°ĐŗĐ° аŅĐ´ŅŅ ĐŊĐĩдаŅŅŅĐŋĐŊа"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Đ¯ĐˇŅĐē ĐŋĐžŅĐžĐēа аŅдиО ĐŋĐž ŅĐŧĐžĐģŅаĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">Đ¯ĐˇŅĐē ĐŋŅиĐģĐžĐļĐĩĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">ĐŅайŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_AZ">ĐСĐĩŅйаКдĐļаĐŊŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_BG">ĐĐžĐģĐŗĐ°ŅŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_BN">ĐĐĩĐŊĐŗĐ°ĐģŅŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_CA">ĐаŅаĐģĐžĐŊŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_CS">ЧĐĩŅŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_DA">ĐаŅŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_DE">ĐĐĩĐŧĐĩŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_EL">ĐŅĐĩŅĐĩŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_EN">ĐĐŊĐŗĐģŅĐšŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ES">ĐŅĐŋаĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ET">ĐŅŅĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FA">ФаŅŅŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FI">ФŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FR">ФŅаĐŊŅŅСŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_GU">ĐŅŅŅаŅŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_HI">ĐĨŅĐŊĐ´Ņ</string>
|
||||
<string name="revanced_spoof_video_streams_language_HR">ĐĨĐžŅваŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_HU">ĐĐĩĐŊĐŗĐĩŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ID">ĐĐŊдаĐŊĐĩСŅĐšŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_IT">ĐŅаĐģŅŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_JA">Đ¯ĐŋĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_KK">ĐаСаŅ
ŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_KO">ĐĐžŅŅĐšŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_LT">ĐŅŅĐžŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_LV">ĐаŅŅŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MK">ĐаĐēĐĩĐ´ĐžĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MN">ĐĐžĐŊĐŗĐžĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MR">ĐаŅаŅŅ
Ņ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MS">ĐаĐģаКŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MY">ĐŅŅĐŧаĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_NL">ĐŅĐ´ŅĐģаĐŊĐ´ŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_OR">ĐŅŅŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">ĐаĐŊĐ´ĐļайŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">ĐĐžĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">ĐаŅŅŅĐŗĐ°ĐģŅŅĐēĐ°Ņ (ĐŅаСŅĐģŅŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">ĐаŅŅŅĐŗĐ°ĐģŅŅĐēĐ°Ņ (ĐаŅŅŅĐŗĐ°ĐģŅŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">Đ ŅĐŧŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Đ ŅŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">ĐĄĐģОваŅĐēиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SL">ĐĄĐģОвĐĩĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SR">ĐĄĐĩŅĐąŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SV">ШвĐĩŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SW">ĐĄŅаŅ
ŅĐģŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TA">ĐĸаĐŧŅĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TE">ĐĸŅĐģŅĐŗŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TH">ĐĸаКŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TR">ĐĸŅŅŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_UK">ĐŖĐēŅаŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_UR">ĐŖŅĐ´Ņ</string>
|
||||
<string name="revanced_spoof_video_streams_language_VI">ĐŅĐĩŅĐŊаĐŧŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ZH">ĐŅŅаКŅĐēаŅ</string>
|
||||
âĸ ĐŅŅĐŧŅŅОваĐĩ аŅŅĐŗŅĐŊаĐģŅĐŊаĐĩ аŅĐ´ŅŅ ĐŊĐĩдаŅŅŅĐŋĐŊа"</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">âĸ ĐŅĐŧа вŅĐ´ŅаĐēŅдаваĐŊĐŊŅ AV1</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">ĐаĐēаСаŅŅ Ņ ŅŅаŅŅŅŅŅŅŅ Đ´ĐģŅ ŅĐŋĐĩŅŅŅĐģŅŅŅаŅ</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">ĐĸŅĐŋ ĐēĐģŅĐĩĐŊŅа адĐģŅŅŅŅĐžŅваĐĩŅŅа Ņ ŅŅаŅŅŅŅŅŅŅ Đ´ĐģŅ ŅĐŋĐĩŅŅŅĐģŅŅŅаŅ</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">ĐĐģŅĐĩĐŊŅ ŅŅ
аваĐŊŅ Ņ ŅŅаŅŅŅŅŅŅŅ Đ´ĐģŅ ŅĐŋĐĩŅŅŅĐģŅŅŅаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">ĐОва ĐŗŅĐēавОК даŅĐžĐļĐēŅ Đŋа СĐŧаŅŅаĐŊĐŊŅ Đ´ĐģŅ VR</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">ĐаŅаŅа ĐŊа ĐēĐžĐŧĐŋиĐģаŅĐ¸Ņ ĐŊа APK Đĩ ĐŋОвŅĐĩĐ´ĐĩĐŊа</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">ĐаŅŅŅОКĐēи</string>
|
||||
<string name="revanced_settings_title">ReVanced</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">ĐŅĐēаŅĐĩ Đģи да ĐŋŅОдŅĐģĐļиŅĐĩ?</string>
|
||||
<string name="revanced_settings_reset">ĐŅСŅŅаĐŊОви</string>
|
||||
@@ -43,6 +44,62 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_import_reset">ĐаŅŅŅОКĐēиŅĐĩ ĐŊа ReVanced ĐąŅŅ
а ĐŊŅĐģиŅаĐŊи</string>
|
||||
<string name="revanced_settings_import_success">ĐĄĐģĐĩĐ´ĐŊиŅĐĩ ĐŊаŅŅŅОКĐēи ĐąŅŅ
а иĐŧĐŋĐžŅŅиŅаĐŊи ŅŅĐŋĐĩŅĐŊĐž: %d</string>
|
||||
<string name="revanced_settings_import_failure_parse">ĐĐŧĐŋĐžŅŅиŅаĐŊĐĩŅĐž ĐąĐĩŅĐĩ ĐŊĐĩŅŅĐŋĐĩŅĐŊĐž: %s</string>
|
||||
<string name="revanced_language_title">ĐСиĐē ĐŊа ReVanced</string>
|
||||
<string name="revanced_language_user_dialog_message">"ĐŅĐĩвОдиŅĐĩ ĐŊа ĐŊŅĐēОи ĐĩСиŅи ĐŧĐžĐļĐĩ да ĐģиĐŋŅĐ˛Đ°Ņ Đ¸Đģи да Ņа ĐŊĐĩĐŋŅĐģĐŊи.
|
||||
|
||||
Đа да ĐŋŅĐĩвĐĩĐ´ĐĩŅĐĩ ĐŊОви ĐĩСиŅи, ĐŋĐžŅĐĩŅĐĩŅĐĩ translate.revanced.app"</string>
|
||||
<string name="revanced_language_DEFAULT">ĐСиĐē ĐŊа ĐŋŅиĐģĐžĐļĐĩĐŊиĐĩŅĐž</string>
|
||||
<string name="revanced_language_AR">аŅайŅĐēи</string>
|
||||
<string name="revanced_language_AZ">ĐСĐĩŅйаКдĐļаĐŊŅĐēи</string>
|
||||
<string name="revanced_language_BG">ĐąŅĐģĐŗĐ°ŅŅĐēи</string>
|
||||
<string name="revanced_language_BN">ĐąĐĩĐŊĐŗĐ°ĐģŅĐēи</string>
|
||||
<string name="revanced_language_CA">ĐēаŅаĐģĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_language_CS">ЧĐĩŅĐēи</string>
|
||||
<string name="revanced_language_DA">ĐаŅŅĐēи</string>
|
||||
<string name="revanced_language_DE">ĐĐĩĐŧŅĐēи</string>
|
||||
<string name="revanced_language_EL">ĐŅŅŅĐēи</string>
|
||||
<string name="revanced_language_EN">ĐĐŊĐŗĐģиКŅĐēи</string>
|
||||
<string name="revanced_language_ES">ĐŅĐŋаĐŊŅĐēи</string>
|
||||
<string name="revanced_language_ET">ĐŅŅĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_language_FA">ĐĐĩŅŅиКŅĐēи</string>
|
||||
<string name="revanced_language_FI">ФиĐŊĐģаĐŊĐ´ŅĐēи</string>
|
||||
<string name="revanced_language_FR">ФŅĐĩĐŊŅĐēи</string>
|
||||
<string name="revanced_language_GU">ĐŅĐ´ĐļаŅаŅи</string>
|
||||
<string name="revanced_language_HI">ĐĨиĐŊди</string>
|
||||
<string name="revanced_language_HR">ĐĨŅŅваŅŅĐēи</string>
|
||||
<string name="revanced_language_HU">ĐŖĐŊĐŗĐ°ŅŅĐēи</string>
|
||||
<string name="revanced_language_ID">ĐĐŊĐ´ĐžĐŊĐĩСиКŅĐēи</string>
|
||||
<string name="revanced_language_IT">ĐŅаĐģиаĐŊŅĐēи</string>
|
||||
<string name="revanced_language_JA">Đ¯ĐŋĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_language_KK">ĐаСаŅ
ŅĐēи</string>
|
||||
<string name="revanced_language_KO">ĐĐžŅĐĩĐšŅĐēи</string>
|
||||
<string name="revanced_language_LT">ĐиŅОвŅĐēи</string>
|
||||
<string name="revanced_language_LV">ĐаŅвиКŅĐēи</string>
|
||||
<string name="revanced_language_MK">ĐаĐēĐĩĐ´ĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_language_MN">ĐĐžĐŊĐŗĐžĐģŅĐēи</string>
|
||||
<string name="revanced_language_MR">ĐаŅаŅŅ
и</string>
|
||||
<string name="revanced_language_MS">ĐаĐģаКŅĐēи</string>
|
||||
<string name="revanced_language_MY">ĐиŅĐŧаĐŊŅĐēи</string>
|
||||
<string name="revanced_language_NL">ĐĨĐžĐģаĐŊĐ´ŅĐēи</string>
|
||||
<string name="revanced_language_OR">ĐдиŅ</string>
|
||||
<string name="revanced_language_PA">ĐĐĩĐŊĐ´Đļайи</string>
|
||||
<string name="revanced_language_PL">ĐĐžĐģŅĐēи</string>
|
||||
<string name="revanced_language_PT">ĐĐžŅŅŅĐŗĐ°ĐģŅĐēи</string>
|
||||
<string name="revanced_language_RO">Đ ŅĐŧŅĐŊŅĐēи</string>
|
||||
<string name="revanced_language_RU">Đ ŅŅĐēи</string>
|
||||
<string name="revanced_language_SK">ĐĄĐģОваŅĐēи</string>
|
||||
<string name="revanced_language_SL">ĐĄĐģОвĐĩĐŊŅĐēи</string>
|
||||
<string name="revanced_language_SR">ĐĄŅŅĐąŅĐēи</string>
|
||||
<string name="revanced_language_SV">ШвĐĩĐ´ŅĐēи</string>
|
||||
<string name="revanced_language_SW">ĐĄŅаŅ
иĐģи</string>
|
||||
<string name="revanced_language_TA">ĐĸаĐŧиĐģŅĐēи</string>
|
||||
<string name="revanced_language_TE">ĐĸĐĩĐģŅĐŗŅ</string>
|
||||
<string name="revanced_language_TH">ĐĸаКĐģаĐŊĐ´ŅĐēи</string>
|
||||
<string name="revanced_language_TR">ĐĸŅŅŅĐēи</string>
|
||||
<string name="revanced_language_UK">ĐŖĐēŅаиĐŊŅĐēи</string>
|
||||
<string name="revanced_language_UR">ĐŖŅĐ´Ņ</string>
|
||||
<string name="revanced_language_VI">ĐиĐĩŅĐŊаĐŧŅĐēи</string>
|
||||
<string name="revanced_language_ZH">ĐиŅаКŅĐēи</string>
|
||||
<string name="revanced_pref_import_export_title">ĐĐŧĐŋĐžŅŅиŅаĐŊĐĩ / ĐĐēŅĐŋĐžŅŅиŅаĐŊĐĩ</string>
|
||||
<string name="revanced_pref_import_export_summary">ĐĐŧĐŋĐžŅŅиŅаĐŊĐĩ / ĐĐēŅĐŋĐžŅŅиŅаĐŊĐĩ ĐŊа ReVanced ĐŊаŅŅŅОКĐēиŅĐĩ</string>
|
||||
<!-- Settings about dialog. -->
|
||||
@@ -77,12 +134,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_screen_01_ads_title">Đ ĐĩĐēĐģаĐŧи</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">ĐĐģŅĐĩŅĐŊаŅивĐŊи ĐŧиĐŊиаŅŅŅи</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">ĐĐžŅĐžĐē</string>
|
||||
<string name="revanced_settings_screen_04_player_title">ĐĐģĐĩĐšŅŅ</string>
|
||||
<string name="revanced_settings_screen_05_general_title">ĐĐąŅĐž ĐžŅĐžŅĐŧĐģĐĩĐŊиĐĩ</string>
|
||||
<string name="revanced_settings_screen_04_general_title">ĐĐąŅ</string>
|
||||
<string name="revanced_settings_screen_05_player_title">ĐĐģĐĩŅŅ</string>
|
||||
<string name="revanced_settings_screen_07_seekbar_title">ĐĐĩĐŊŅа Са ĐŋŅĐžĐŗŅĐĩŅ ĐŊа видĐĩĐžŅĐž</string>
|
||||
<string name="revanced_settings_screen_08_swipe_controls_title">ĐĐžĐŊŅŅĐžĐģи Ņ ĐŋĐģŅĐˇĐŗĐ°ĐŊĐĩ</string>
|
||||
<string name="revanced_settings_screen_11_misc_title">РаСĐŊи</string>
|
||||
<string name="revanced_settings_screen_12_video_title">ĐидĐĩĐž</string>
|
||||
<string name="revanced_restore_old_settings_menus_title">ĐŅСŅŅаĐŊОвŅваĐŊĐĩ ĐŊа ŅŅаŅиŅĐĩ ĐŧĐĩĐŊŅŅа Са ĐŊаŅŅŅОКĐēи</string>
|
||||
<string name="revanced_restore_old_settings_menus_summary_on">ĐĄŅаŅиŅĐĩ ĐŧĐĩĐŊŅŅа Ņ ĐŊаŅŅŅОКĐēи ŅĐĩ ĐŋĐžĐēаСваŅ</string>
|
||||
<string name="revanced_restore_old_settings_menus_summary_off">ĐĄŅаŅиŅĐĩ ĐŧĐĩĐŊŅŅа Ņ ĐŊаŅŅŅОКĐēи ĐŊĐĩ ŅĐĩ ĐŋĐžĐēаСваŅ</string>
|
||||
</patch>
|
||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||
<string name="revanced_shorts_disable_background_playback_title">ĐŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ ĐŊа Shorts в ŅĐžĐŊОв ŅĐĩĐļиĐŧ</string>
|
||||
@@ -445,6 +505,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_overlay_background_alpha_summary">ĐидиĐŧĐžŅŅŅа ĐŊа ŅĐžĐŊа ĐŊа ĐŋĐģŅĐˇĐŗĐ°ŅиŅĐĩ ĐēĐžĐŊŅŅĐžĐģи.</string>
|
||||
<string name="revanced_swipe_threshold_title">ĐŅĐ°Đŗ ĐŊа вĐĩĐģиŅиĐŊаŅа ĐŊа ĐŋĐģŅĐˇĐŗĐ°ĐŊĐĩ</string>
|
||||
<string name="revanced_swipe_threshold_summary">ĐŅĐ°Đŗ ĐŋŅĐĩди да ŅĐĩ ĐžŅŅŅĐĩŅŅви ĐŋĐģŅĐˇĐŗĐ°ĐŊĐĩŅĐž</string>
|
||||
<string name="revanced_swipe_change_video_title">ĐĐēĐģŅŅваĐŊĐĩ ĐŊа ĐŋŅĐĩвĐēĐģŅŅваĐŊĐĩ ĐŊа видĐĩĐžŅĐž ŅŅĐĩС ĐŋĐģŅСваĐŊĐĩ</string>
|
||||
<string name="revanced_swipe_change_video_summary_on">ĐĐģŅСваĐŊĐĩŅĐž в ŅĐĩĐļиĐŧ ĐŊа ŅŅĐģ ĐĩĐēŅаĐŊ ŅĐĩ ĐŋŅĐĩвĐēĐģŅŅи ĐēŅĐŧ ŅĐģĐĩдваŅĐžŅĐž/ĐŋŅĐĩдиŅĐŊĐž видĐĩĐž</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">ĐĐģŅСваĐŊĐĩŅĐž в ŅĐĩĐļиĐŧ ĐŊа ŅŅĐģ ĐĩĐēŅаĐŊ ĐŊŅĐŧа да ĐŋŅĐĩвĐēĐģŅŅи ĐēŅĐŧ ŅĐģĐĩдваŅĐžŅĐž/ĐŋŅĐĩдиŅĐŊĐž видĐĩĐž</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">ĐвŅĐžĐŧаŅиŅĐŊи ĐĄŅĐąŅиŅŅи</string>
|
||||
@@ -628,15 +691,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_player_screen_summary">ĐĄĐēŅиваĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅи в Shorts ĐŋĐģĐĩĐšŅŅа</string>
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">ĐĄĐēŅиваĐŊĐĩ ĐŊа Shorts в ĐŊаŅаĐģĐŊаŅа ĐģĐĩĐŊŅа</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Shorts в ĐŊаŅаĐģĐŊаŅа ĐģĐĩĐŊŅа Ņа ŅĐēŅиŅи</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Shorts в ĐŊаŅаĐģĐŊаŅа ĐģĐĩĐŊŅа Ņа ĐŋĐžĐēаСаĐŊи</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">ĐĄĐēŅĐ¸Ņ Đ˛ ĐŊаŅаĐģĐŊĐ¸Ņ ĐēаĐŊаĐģ и ŅвŅŅСаĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">ĐĐžĐēаСаĐŊ в ĐŊаŅаĐģĐŊĐ¸Ņ ĐēаĐŊаĐģ и ŅвŅŅСаĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Shorts в ŅаСдĐĩĐģ âĐйОĐŊаĐŧĐĩĐŊŅиâ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Shorts в ŅаСдĐĩĐģ âĐйОĐŊаĐŧĐĩĐŊŅиâ Ņа ŅĐēŅиŅи</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Shorts в ŅаСдĐĩĐģ âĐйОĐŊаĐŧĐĩĐŊŅиâ ŅĐĩ ĐŋĐžĐēаСваŅ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">ĐĄĐēŅиŅĐž в айОĐŊаĐŧĐĩĐŊŅĐŊаŅа ĐĩĐŧиŅиŅ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">ĐĐžĐēаСаĐŊĐž в айОĐŊаĐŧĐĩĐŊŅĐŊаŅа ĐĩĐŧиŅиŅ</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts в ŅĐĩСŅĐģŅаŅиŅĐĩ ĐžŅ ŅŅŅŅĐĩĐŊĐĩŅĐž</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Shorts в ŅĐĩСŅĐģŅаŅиŅĐĩ ĐžŅ ŅŅŅŅĐĩĐŊĐĩŅĐž Ņа ŅĐēŅиŅи</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Shorts в ŅĐĩСŅĐģŅаŅиŅĐĩ ĐžŅ ŅŅŅŅĐĩĐŊĐĩŅĐž ŅĐĩ ĐŋĐžĐēаСваŅ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">ĐĄĐēŅиŅи в ŅĐĩСŅĐģŅаŅиŅĐĩ ĐžŅ ŅŅŅŅĐĩĐŊĐĩŅĐž</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">ĐĐžĐēаСаĐŊĐž в ŅĐĩСŅĐģŅаŅиŅĐĩ ĐžŅ ŅŅŅŅĐĩĐŊĐĩŅĐž</string>
|
||||
<string name="revanced_hide_shorts_history_title">ĐĄĐēŅиваĐŊĐĩ ĐŊа ŅĐžŅŅиŅĐĩ в иŅŅĐžŅиŅŅа ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">ĐĄĐēŅиŅĐž в иŅŅĐžŅиŅŅа ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">ĐĐžĐēаСва ŅĐĩ в иŅŅĐžŅиŅŅа ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string>
|
||||
<!-- 'join' should be translated using the same localized wording YouTube displays for the button. -->
|
||||
<string name="revanced_hide_shorts_join_button_title">ĐŅŅĐžĐŊ Са ĐŋŅиŅŅĐĩдиĐŊŅваĐŊĐĩ</string>
|
||||
<string name="revanced_hide_shorts_join_button_summary_on">ĐŅŅĐžĐŊа Са ĐŋŅиŅŅĐĩдиĐŊŅваĐŊĐĩ Đĩ ŅĐēŅиŅ</string>
|
||||
@@ -738,6 +804,13 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_on">ĐСŅĐēаŅаŅиŅĐĩ ĐŋаĐŊĐĩĐģи ĐŊа ĐŋĐģĐĩĐšŅŅа Ņа ŅĐēŅиŅи</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_off">ĐСŅĐēаŅаŅиŅĐĩ ĐŋаĐŊĐĩĐģи ĐŊа ĐŋĐģĐĩĐšŅŅа ŅĐĩ ĐŋĐžĐēаСваŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
<string name="revanced_exit_fullscreen_title">ĐСŅ
Од ĐžŅ ŅĐĩĐļиĐŧ ĐŊа ŅŅĐģ ĐĩĐēŅаĐŊ в ĐēŅĐ°Ņ ĐŊа видĐĩĐžŅĐž</string>
|
||||
<string name="revanced_exit_fullscreen_entry_1">ĐĐĩаĐēŅивиŅаĐŊĐž</string>
|
||||
<string name="revanced_exit_fullscreen_entry_2">ĐĐžŅŅŅĐĩŅ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_3">ĐĐĩКСаĐļ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_4">ĐĐžŅŅŅĐĩŅ Đ¸ ĐŋĐĩКСаĐļ</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">ĐŅваŅŅĐŊĐĩ ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ в ĐŋĐžŅŅŅĐĩŅĐĩĐŊ ŅĐĩĐļиĐŧ ĐŊа ŅŅĐģ ĐĩĐēŅаĐŊ</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_on">ĐидĐĩĐžĐēĐģиĐŋОвĐĩŅĐĩ ŅĐĩ ĐžŅваŅŅŅ ĐŊа ŅŅĐģ ĐĩĐēŅаĐŊ</string>
|
||||
@@ -1006,6 +1079,23 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_reset">ĐŅСŅŅаĐŊОви</string>
|
||||
<string name="revanced_sb_about">Đа ĐŋŅĐžĐŗŅаĐŧаŅа</string>
|
||||
<string name="revanced_sb_about_api_sum">ĐаĐŊĐŊиŅĐĩ Ņа ĐŋŅĐĩĐ´ĐžŅŅавĐĩĐŊи ĐžŅ SponsorBlock API. ĐĐžĐēĐžŅĐŊĐĩŅĐĩ ŅŅĐē Са ĐŋОвĐĩŅĐĩ иĐŊŅĐžŅĐŧаŅĐ¸Ņ Đ¸ иСŅĐĩĐŗĐģиŅĐŊиŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
<string name="revanced_change_form_factor_title">ФОŅĐŧĐ°Ņ ĐŊа ĐĩĐēŅаĐŊа /ĐĸайĐģĐĩŅ, ĐĸĐĩĐģŅĐžĐŊ, .../</string>
|
||||
<string name="revanced_change_form_factor_entry_1">ĐĐž ĐŋОдŅаСйиŅаĐŊĐĩ</string>
|
||||
<string name="revanced_change_form_factor_entry_2">ĐĸĐĩĐģĐĩŅĐžĐŊ</string>
|
||||
<string name="revanced_change_form_factor_entry_3">ĐĸайĐģĐĩŅ</string>
|
||||
<string name="revanced_change_form_factor_entry_4">ĐвŅĐžĐŧОйиĐģ</string>
|
||||
<string name="revanced_change_form_factor_user_dialog_message">"ĐŅĐžĐŧĐĩĐŊиŅĐĩ вĐēĐģŅŅваŅ:
|
||||
|
||||
ĐŅĐžŅĐŧĐģĐĩĐŊиĐĩ Са ŅайĐģĐĩŅ
|
||||
âĸ ĐŅĐąĐģиĐēаŅииŅĐĩ ĐŊа ОйŅĐŊĐžŅŅŅа Ņа ŅĐēŅиŅи
|
||||
|
||||
ĐŅĐžŅĐŧĐģĐĩĐŊиĐĩ Са авŅĐžĐŧОйиĐģ
|
||||
âĸ ĐĐĩĐŊŅŅĐž âĐŅŅĐžŅĐ¸Ņ ĐŊа ĐŗĐģĐĩдаĐŊĐĩâ Đĩ ŅĐēŅиŅĐž
|
||||
âĸ РаСдĐĩĐģŅŅ âĐ Đ°ĐˇĐŗĐģĐĩдаКâ Đĩ вŅСŅŅаĐŊОвĐĩĐŊ
|
||||
âĸ Shorts ŅĐĩ ĐžŅваŅŅŅ Đ˛ ОйиĐēĐŊОвĐĩĐŊĐ¸Ņ ĐŋĐģĐĩĐšŅŅ
|
||||
âĸ ĐĐĩĐŊŅаŅа Đĩ ĐžŅĐŗĐ°ĐŊиСиŅаĐŊа ĐŋĐž ŅĐĩĐŧи и ĐēаĐŊаĐģ"</string>
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<string name="revanced_spoof_app_version_title">ĐОдĐģŅĐŗĐ˛Đ°ĐŊĐĩ Са вĐĩŅŅиŅŅа ĐŊа ĐŋŅиĐģĐžĐļĐĩĐŊиĐĩŅĐž</string>
|
||||
@@ -1020,6 +1110,7 @@ Second \"item\" text"</string>
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
<string name="revanced_spoof_app_version_target_title">ĐОдĐģŅĐŗĐ˛Đ°ĐŊĐĩ Са вĐĩŅŅиŅŅа ĐŊа</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - ĐŅСŅŅаĐŊОвĐĩŅĐĩ ŅŅаŅиŅĐĩ иĐēĐžĐŊи ĐŊа Shorts в ĐŋĐģĐĩĐšŅŅа</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.26.42 - ĐŅСŅŅаĐŊОвŅваĐŊĐĩ ĐŊа ŅŅаŅи иĐēĐžĐŊи ĐŊа ĐŊĐ°Đ˛Đ¸ĐŗĐ°ŅиŅŅа и ĐģĐĩĐŊŅаŅа Ņ Đ¸ĐŊŅŅŅŅĐŧĐĩĐŊŅи</string>
|
||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_1">18.33.40 - ĐŅСŅŅаĐŊОвĐĩŅĐĩ RYD в ŅĐĩĐļиĐŧ âиĐŊĐēĐžĐŗĐŊиŅĐžâ ĐŊа Shorts</string>
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_2">18.20.39 - ĐŅСŅŅаĐŊОвŅваĐŊĐĩ ĐŊа видĐĩĐž ŅĐēĐžŅĐžŅŅ & в ĐŧĐĩĐŊŅŅĐž Са ĐēаŅĐĩŅŅвО</string>
|
||||
@@ -1063,12 +1154,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_on">Shorts ŅĐĩ ŅĐĩ вŅСĐŋŅОиСвĐĩĐļĐ´Đ°Ņ Đ°Đ˛ŅĐžĐŧаŅиŅĐŊĐž ĐĩдиĐŊ ŅĐģĐĩĐ´ Đ´ŅŅĐŗ вŅв ŅĐžĐŊОв ŅĐĩĐļиĐŧ</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_off">Shorts ŅĐĩ ŅĐĩ ĐŋОвŅĐžŅи вŅв ŅĐžĐŊОв ŅĐĩĐļиĐŧ</string>
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
<string name="revanced_tablet_layout_title">ĐĐēĐģŅŅи ŅĐĩĐļиĐŧ Са ŅайĐģĐĩŅ</string>
|
||||
<string name="revanced_tablet_layout_summary_on">Đ ĐĩĐļиĐŧ Са ŅайĐģĐĩŅ Đĩ вĐēĐģ.</string>
|
||||
<string name="revanced_tablet_layout_summary_off">Đ ĐĩĐļиĐŧ Са ŅайĐģĐĩŅ Đĩ иСĐēĐģ.</string>
|
||||
<string name="revanced_tablet_layout_user_dialog_message">ĐŅĐąĐģиĐēаŅииŅĐĩ в ОйŅĐŊĐžŅŅŅа ĐŊĐĩ ŅĐĩ ĐŋĐžĐēĐ°ĐˇĐ˛Đ°Ņ ĐŊа ĐžŅĐžŅĐŧĐģĐĩĐŊĐ¸Ņ ĐˇĐ° ŅайĐģĐĩŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
<string name="revanced_miniplayer_screen_title">ĐиĐŊиĐŧиСиŅаĐŊ ĐĩĐēŅаĐŊ Са вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ</string>
|
||||
<string name="revanced_miniplayer_screen_summary">ĐŅĐžĐŧĐĩĐŊĐĩŅĐĩ ŅŅиĐģа ĐŊа ĐŧиĐŊиĐŧиСиŅаĐŊĐ¸Ņ ĐĩĐēŅаĐŊ Са вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ</string>
|
||||
@@ -1232,6 +1317,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_force_original_audio_title">ĐŅиĐŊŅдиŅĐĩĐģĐŊĐž ĐžŅĐ¸ĐŗĐ¸ĐŊаĐģĐŊĐž аŅдиО</string>
|
||||
<string name="revanced_force_original_audio_summary_on">ĐСĐŋĐžĐģСваĐŊĐĩ ĐŊа ĐžŅĐ¸ĐŗĐ¸ĐŊаĐģĐŊĐž аŅдиО</string>
|
||||
<string name="revanced_force_original_audio_summary_off">ĐСĐŋĐžĐģСваĐŊĐĩ ĐŊа аŅдиО ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ</string>
|
||||
<string name="revanced_force_original_audio_not_available">Đа да иСĐŋĐžĐģСваŅĐĩ ŅаСи ŅŅĐŊĐēŅиŅ, ĐŋŅĐžĐŧĐĩĐŊĐĩŅĐĩ иĐŧиŅаŅиŅŅа ĐŊа ĐŋĐžŅĐžŅĐŊĐž ĐŋŅĐĩдаваĐŊĐĩ ĐŊа ŅиĐŋ ĐēĐģиĐĩĐŊŅ ĐŊа iOS</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
|
||||
@@ -1259,6 +1345,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">ĐĐĩŅŅĐžĐŊаĐģиСиŅаĐŊиŅĐĩ ŅĐēĐžŅĐžŅŅи ŅŅŅйва да Ņа ĐŋĐž-ĐŧаĐģĐēи ĐžŅ %s</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">ĐĐĩваĐģидĐŊи ĐŋĐĩŅŅĐžĐŊаĐģиСиŅаĐŊи ŅĐēĐžŅĐžŅŅи ĐŊа вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">ĐвŅĐž</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">ĐĐĩŅŅĐžĐŊаĐģиСиŅаĐŊа ŅĐēĐžŅĐžŅŅ ĐŋŅи Đ´ĐžĐēĐžŅваĐŊĐĩ и СадŅŅĐļаĐŊĐĩ</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">ĐĄĐēĐžŅĐžŅŅ ĐŊа вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ ĐŧĐĩĐļĐ´Ņ 0-8</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">ĐаĐŋĐžĐŧĐŊи ĐŋŅĐžĐŧĐĩĐŊиŅĐĩ в ŅĐēĐžŅĐžŅŅŅа ĐŊа вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ</string>
|
||||
@@ -1287,74 +1375,27 @@ Second \"item\" text"</string>
|
||||
ĐŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ ĐŧĐžĐļĐĩ да ĐŊĐĩ ŅайОŅи"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">ĐĐĩаĐēŅивиŅаĐŊĐĩŅĐž ĐŊа ŅаСи ĐŊаŅŅŅОКĐēа ŅĐĩ дОвĐĩĐ´Đĩ Đ´Đž ĐŋŅОйĐģĐĩĐŧи Ņ Đ˛ŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž ĐŊа видĐĩĐž.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">ĐĐģиĐĩĐŊŅ ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ĐŅиĐŊŅдиŅĐĩĐģĐŊĐž AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ĐидĐĩĐž ĐēОдĐĩĐē ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ AVC (H.264)</string>
|
||||
<!-- 'no auth' means no authentication -->
|
||||
<string name="revanced_spoof_video_streams_client_type_android_vr_no_auth">Android VR (bez avtorizaciq)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ĐŅиĐŊŅдиŅĐĩĐģĐŊĐž иСĐŋĐžĐģСваĐŊĐĩ ĐŊа AVC (H.264) ĐŊа iOS</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ĐидĐĩĐž ĐēОдĐĩĐēŅŅ Đĩ ĐŋŅиĐŊŅдиŅĐĩĐģĐŊĐž СададĐĩĐŊ ĐŊа AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ĐидĐĩĐž ĐēОдĐĩĐēŅŅ ŅĐĩ ĐžĐŋŅĐĩĐ´ĐĩĐģŅ Đ°Đ˛ŅĐžĐŧаŅиŅĐŊĐž</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ĐĐēŅивиŅаĐŊĐĩŅĐž ĐŊа ŅОва ĐŧĐžĐļĐĩ да ĐŋОдОйŅи ĐļивОŅа ĐŊа йаŅĐĩŅиŅŅа и да ĐŋĐžĐŋŅави СаĐĩĐēваĐŊĐĩŅĐž ĐŊа вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž.
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ĐĐēĐģŅŅваĐŊĐĩŅĐž ĐŊа ŅОва ĐŧĐžĐļĐĩ да ĐŋОдОйŅи ĐļивОŅа ĐŊа йаŅĐĩŅиŅŅа и да ĐŋĐžĐŋŅави СаĐĩĐēваĐŊĐĩŅĐž ĐŋŅи вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ.
|
||||
|
||||
AVC иĐŧа ĐŧаĐēŅиĐŧаĐģĐŊа ŅаСдĐĩĐģиŅĐĩĐģĐŊа ŅĐŋĐžŅОйĐŊĐžŅŅ ĐžŅ 1080p, аŅдиО ĐēОдĐĩĐēŅŅ Opus ĐŊĐĩ Đĩ ĐŊаĐģиŅĐĩĐŊ, а видĐĩОвŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž ŅĐĩ иСĐŋĐžĐģСва ĐŋОвĐĩŅĐĩ иĐŊŅĐĩŅĐŊĐĩŅ Đ´Đ°ĐŊĐŊи ĐžŅ VP9 иĐģи AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_title">CŅŅаĐŊиŅĐŊи ĐĩŅĐĩĐēŅи ĐžŅ ĐŋОдĐŧŅĐŊаŅа ĐŊа iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_summary">"âĸ ĐŅСĐŧĐžĐļĐŊĐž Đĩ ŅаŅŅĐŊиŅĐĩ Đ´ĐĩŅŅĐēи видĐĩĐžĐēĐģиĐŋОвĐĩ да ĐŊĐĩ ŅĐĩ вŅСĐŋŅОиСвĐĩĐļдаŅ
|
||||
AVC иĐŧа ĐŧаĐēŅиĐŧаĐģĐŊа ŅĐĩСОĐģŅŅĐ¸Ņ ĐžŅ 1080p, Opus аŅдиО ĐēОдĐĩĐē ĐŊĐĩ Đĩ ĐŊаĐģиŅĐĩĐŊ и вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž ĐŊа видĐĩĐž ŅĐĩ иСĐŋĐžĐģСва ĐŋОвĐĩŅĐĩ иĐŊŅĐĩŅĐŊĐĩŅ Đ´Đ°ĐŊĐŊи ĐžŅ VP9 иĐģи AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">ĐŅĐĩĐēŅи ĐŊа иСĐŧаĐŧаŅа в iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"âĸ ФиĐģĐŧи иĐģи ĐŋĐģаŅĐĩĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ ĐŧĐžĐļĐĩ да ĐŊĐĩ ŅĐĩ вŅСĐŋŅОиСвĐĩĐļдаŅ
|
||||
âĸ ĐĄŅайиĐģĐĩĐŊ СвŅĐē ĐŊĐĩ Đĩ ĐŊаĐģиŅĐĩĐŊ
|
||||
âĸ ĐидĐĩĐžĐēĐģиĐŋОвĐĩŅĐĩ СавŅŅŅĐ˛Đ°Ņ 1 ŅĐĩĐēŅĐŊда ĐŋĐž-ŅаĐŊĐž"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_title">ĐĄŅŅаĐŊиŅĐŊи ĐĩŅĐĩĐēŅи ĐžŅ ĐŋОдĐŋŅавŅĐŊĐĩ ĐŊа Android VR</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_summary">"âĸ ĐĐžĐļĐĩ да вŅСĐŊиĐēĐŊĐ°Ņ ĐŋŅОйĐģĐĩĐŧи ĐŋŅи вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩ ĐŊа Đ´ĐĩŅŅĐēи видĐĩĐžĐēĐģиĐŋОвĐĩ
|
||||
âĸ ĐиĐŋŅва ĐŧĐĩĐŊŅ ĐˇĐ° аŅдиО ĐŋĐĩŅĐŊи
|
||||
âĸ ĐĐĩ Đĩ ĐŊаĐģиŅĐŊĐž ŅŅайиĐģĐŊĐž ĐŊивО ĐŊа СвŅĐēа
|
||||
âĸ ĐĐĩ Đĩ ĐŊаĐģиŅĐŊа ĐžĐŋŅĐ¸Ņ ĐˇĐ° ĐžŅĐ¸ĐŗĐ¸ĐŊаĐģĐŊĐž аŅдиО"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">ĐСиĐē ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ ĐŊа аŅдиО ĐŋĐžŅĐžĐēа</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">ĐСиĐē ĐŊа ĐŋŅиĐģĐžĐļĐĩĐŊиĐĩŅĐž</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">ĐŅайŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_AZ">ĐСĐĩŅйаКдĐļаĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_BG">ĐŅĐģĐŗĐ°ŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_BN">ĐĐĩĐŊĐŗĐ°ĐģŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_CA">ĐаŅаĐģĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_CS">ЧĐĩŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_DA">ĐаŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_DE">ĐĐĩĐŧŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_EL">ĐŅŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_EN">ĐĐŊĐŗĐģиКŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_ES">ĐŅĐŋаĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_ET">ĐŅŅĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_FA">ĐĐĩŅŅиКŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_FI">ФиĐŊĐģаĐŊĐ´ŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_FR">ФŅĐĩĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_GU">ĐŅĐ´ĐļаŅаŅи</string>
|
||||
<string name="revanced_spoof_video_streams_language_HI">ĐĨиĐŊди</string>
|
||||
<string name="revanced_spoof_video_streams_language_HR">ĐĨŅŅваŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_HU">ĐŖĐŊĐŗĐ°ŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_ID">ĐĐŊĐ´ĐžĐŊĐĩСиКŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_IT">ĐŅаĐģиаĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_JA">Đ¯ĐŋĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_KK">ĐаСаŅ
ŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_KO">ĐĐžŅĐĩĐšŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_LT">ĐиŅОвŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_LV">ĐаŅвиКŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_MK">ĐаĐēĐĩĐ´ĐžĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_MN">ĐĐžĐŊĐŗĐžĐģŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_MR">ĐаŅаŅŅ
и</string>
|
||||
<string name="revanced_spoof_video_streams_language_MS">ĐаĐģаКŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_MY">ĐиŅĐŧаĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_NL">ĐĨĐžĐģаĐŊĐ´ŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_OR">ĐŅиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">ĐĐĩĐŊĐ´ĐļайŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">ĐĐžĐģŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">ĐĐžŅŅŅĐŗĐ°ĐģŅĐēи (ĐŅаСиĐģиŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">ĐĐžŅŅŅĐŗĐ°ĐģŅĐēи (ĐĐžŅŅŅĐŗĐ°ĐģиŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">Đ ŅĐŧŅĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Đ ŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">ĐĄĐģОваŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_SL">ĐĄĐģОвĐĩĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_SR">ĐĄŅŅĐąŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_SV">ШвĐĩĐ´ŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_SW">ĐĄŅаŅ
иĐģи</string>
|
||||
<string name="revanced_spoof_video_streams_language_TA">ĐĸаĐŧиĐģŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_TE">ĐĸĐĩĐģŅĐŗŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TH">ĐĸаКĐģаĐŊĐ´ŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_TR">ĐĸŅŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_UK">ĐŖĐēŅаиĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_UR">ĐŖŅĐ´Ņ</string>
|
||||
<string name="revanced_spoof_video_streams_language_VI">ĐиĐĩŅĐŊаĐŧŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_ZH">ĐиŅаКŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Strani4ni efekti na fal6ivoto predstavqne na Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"âĸ Lipsva menju za audio pisti
|
||||
âĸ Ne e nali4na stabilna glasnost
|
||||
âĸ Ne e nali4na forsirana originalna audio pista"</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">âĸ ĐĐĩС AV1 видĐĩĐž ĐēОдĐĩĐē</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Poka6i v Statistiki za nerds</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">TipŅŅ na klienta se poka6va v Statistiki za nerds</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">KlientŅŅ e skriŅ v Statistiki za nerds</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Ezik po ĐŋОдŅаСйиŅаĐŊĐĩ za audio potok v VR</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK āϤā§āϰāĻŋāϰ āϤāĻžāϰāĻŋāĻ āϤā§āϰā§āĻāĻŋāĻĒā§āϰā§āĻŖ</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">āϏā§āĻāĻŋāĻāϏ</string>
|
||||
<string name="revanced_settings_title">ReVanced</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">āĻāĻĒāύāĻŋ āĻāĻŋ āĻāĻāĻŋā§ā§ āϝā§āϤ⧠āĻāĻā§āĻā§āĻ?</string>
|
||||
<string name="revanced_settings_reset">āĻāĻŦāĻžāϰ āϏā§āĻ āĻāϰā§āύ</string>
|
||||
@@ -43,6 +44,62 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_import_reset">ReVanced āϏā§āĻāĻŋāĻ āĻĄāĻŋāĻĢāϞā§āĻ āϏā§āĻ āĻāϰāĻž āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_settings_import_success">%d āϏā§āĻāĻŋāĻ āĻāĻŽāĻĻāĻžāύāĻŋ āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_settings_import_failure_parse">āĻāĻŽāĻĻāĻžāύāĻŋ āĻāϰāĻž āϝāĻžā§āύāĻŋ: %s</string>
|
||||
<string name="revanced_language_title">ReVanced āĻāĻžāώāĻž</string>
|
||||
<string name="revanced_language_user_dialog_message">"āĻāĻŋāĻā§ āĻāĻžāώāĻžāϰ āĻāύā§āϝ āĻ
āύā§āĻŦāĻžāĻĻ āĻ
āύā§āĻĒāϏā§āĻĨāĻŋāϤ āĻŦāĻž āĻ
āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤
|
||||
|
||||
āύāϤā§āύ āĻāĻžāώāĻž āĻ
āύā§āĻŦāĻžāĻĻ āĻāϰāϤ⧠translate.revanced.app āĻĻā§āĻā§āύ"</string>
|
||||
<string name="revanced_language_DEFAULT">āĻ
ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύā§āϰ āĻāĻžāώāĻž</string>
|
||||
<string name="revanced_language_AR">āĻāϰāĻŦāĻŋ</string>
|
||||
<string name="revanced_language_AZ">āĻāĻāĻžāϰāĻŦāĻžāĻāĻāĻžāύāĻŋ</string>
|
||||
<string name="revanced_language_BG">āĻŦā§āϞāĻā§āϰāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_BN">āĻŦāĻžāĻāϞāĻž</string>
|
||||
<string name="revanced_language_CA">āĻāĻžāϤāĻžāϞāĻžāύ</string>
|
||||
<string name="revanced_language_CS">āĻā§āĻ</string>
|
||||
<string name="revanced_language_DA">āĻĄā§āϝāĻžāύāĻŋāĻļ</string>
|
||||
<string name="revanced_language_DE">āĻāĻžāϰā§āĻŽāĻžāύ</string>
|
||||
<string name="revanced_language_EL">āĻā§āϰāĻŋāĻ</string>
|
||||
<string name="revanced_language_EN">āĻāĻāϰā§āĻāĻŋ</string>
|
||||
<string name="revanced_language_ES">āϏā§āĻĒā§āϝāĻžāύāĻŋāĻļ</string>
|
||||
<string name="revanced_language_ET">āĻāϏā§āϤā§āύāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_FA">āĻĢāĻžāϰā§āϏāĻŋ</string>
|
||||
<string name="revanced_language_FI">āĻĢāĻŋāύāĻŋāĻļ</string>
|
||||
<string name="revanced_language_FR">āĻĢāϰāĻžāϏāĻŋ</string>
|
||||
<string name="revanced_language_GU">āĻā§āĻāϰāĻžāĻāĻŋ</string>
|
||||
<string name="revanced_language_HI">āĻšāĻŋāύā§āĻĻāĻŋ</string>
|
||||
<string name="revanced_language_HR">āĻā§āϰā§āϝāĻŧā§āĻļā§āϝāĻŧ</string>
|
||||
<string name="revanced_language_HU">āĻšāĻžāĻā§āĻā§āϰāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_ID">āĻāύā§āĻĻā§āύā§āĻļāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_IT">āĻāϤāĻžāϞā§āϝāĻŧ</string>
|
||||
<string name="revanced_language_JA">āĻāĻžāĻĒāĻžāύāĻŋ</string>
|
||||
<string name="revanced_language_KK">āĻāĻžāĻāĻžāĻ</string>
|
||||
<string name="revanced_language_KO">āĻā§āϰāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_LT">āϞāĻŋāĻĨā§ā§āĻžāύāĻŋā§āĻžāύ</string>
|
||||
<string name="revanced_language_LV">āϞāĻžāϤāĻāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_MK">āĻŽā§āϝāĻžāϏā§āĻĄā§āύāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_MN">āĻŽāĻā§āĻā§āϞā§āϝāĻŧ</string>
|
||||
<string name="revanced_language_MR">āĻŽāĻžāϰāĻžāĻ āĻŋ</string>
|
||||
<string name="revanced_language_MS">āĻŽāĻžāϞāϝāĻŧ</string>
|
||||
<string name="revanced_language_MY">āĻŦāϰā§āĻŽāĻŋ</string>
|
||||
<string name="revanced_language_NL">āĻĄāĻžāĻ</string>
|
||||
<string name="revanced_language_OR">āĻāĻĄāĻŧāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_language_PA">āĻĒāĻžāĻā§āĻāĻžāĻŦāĻŋ</string>
|
||||
<string name="revanced_language_PL">āĻĒā§āϞāĻŋāĻļ</string>
|
||||
<string name="revanced_language_PT">āĻĒāϰā§āϤā§āĻāĻŋāĻ</string>
|
||||
<string name="revanced_language_RO">āϰā§āĻŽāĻžāύā§āϝāĻŧ</string>
|
||||
<string name="revanced_language_RU">āϰā§āĻļ</string>
|
||||
<string name="revanced_language_SK">āϏā§āϞā§āĻāĻžāĻ</string>
|
||||
<string name="revanced_language_SL">āϏā§āϞā§āĻā§āύ</string>
|
||||
<string name="revanced_language_SR">āϏāĻžāϰā§āĻŦāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_language_SV">āϏā§āĻāĻĄāĻŋāĻļ</string>
|
||||
<string name="revanced_language_SW">āϏā§āϝāĻŧāĻžāĻšāĻŋāϞāĻŋ</string>
|
||||
<string name="revanced_language_TA">āϤāĻžāĻŽāĻŋāϞ</string>
|
||||
<string name="revanced_language_TE">āϤā§āϞā§āĻā§</string>
|
||||
<string name="revanced_language_TH">āĻĨāĻžāĻ</string>
|
||||
<string name="revanced_language_TR">āϤā§āϰā§āĻāĻŋ</string>
|
||||
<string name="revanced_language_UK">āĻāĻāĻā§āϰā§āύā§āϝāĻŧ</string>
|
||||
<string name="revanced_language_UR">āĻāϰā§āĻĻā§</string>
|
||||
<string name="revanced_language_VI">āĻāĻŋāϝāĻŧā§āϤāύāĻžāĻŽā§</string>
|
||||
<string name="revanced_language_ZH">āĻāĻžāĻāύāĻŋāĻ</string>
|
||||
<string name="revanced_pref_import_export_title">āĻāĻŽāĻĻāĻžāύāĻŋ āĻāĻŦāĻ āϰāĻĒā§āϤāĻžāύāĻŋ</string>
|
||||
<string name="revanced_pref_import_export_summary">ReVanced āϏā§āĻāĻŋāĻ āĻāĻŽāĻĻāĻžāύāĻŋ āĻŦāĻž āϰāĻĒā§āϤāĻžāύāĻŋ āĻāϰā§āύ</string>
|
||||
<!-- Settings about dialog. -->
|
||||
@@ -77,13 +134,16 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_settings_screen_01_ads_title">āĻŦāĻŋāĻā§āĻāĻžāĻĒāύ</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">āĻŦāĻŋāĻāϞā§āĻĒ āĻĨāĻžāĻŽā§āĻŦāύā§āĻāϞ</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">āĻĢāĻŋāĻĄ</string>
|
||||
<string name="revanced_settings_screen_04_player_title">āĻĒā§āϞā§ā§āĻžāϰ</string>
|
||||
<string name="revanced_settings_screen_05_general_title">āϏāĻžāϧāĻžāϰāĻŖ āϞā§-āĻāĻāĻ</string>
|
||||
<string name="revanced_settings_screen_04_general_title">āϏāĻžāϧāĻžāϰāĻŖ</string>
|
||||
<string name="revanced_settings_screen_05_player_title">āĻĒā§āϞā§āϝāĻŧāĻžāϰ</string>
|
||||
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
|
||||
<string name="revanced_settings_screen_07_seekbar_title">āϏāĻŋāĻāĻŦāĻžāϰ</string>
|
||||
<string name="revanced_settings_screen_08_swipe_controls_title">āϏā§āϝāĻŧāĻžāĻāĻĒ āĻāύā§āĻā§āϰā§āϞ</string>
|
||||
<string name="revanced_settings_screen_11_misc_title">āĻŦāĻŋāĻŦāĻŋāϧ</string>
|
||||
<string name="revanced_settings_screen_12_video_title">āĻāĻŋāĻĄāĻŋāĻ</string>
|
||||
<string name="revanced_restore_old_settings_menus_title">āĻĒā§āϰāĻžāύ⧠āϏā§āĻāĻŋāĻāϏ āĻŽā§āύ⧠āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§āύ</string>
|
||||
<string name="revanced_restore_old_settings_menus_summary_on">āĻĒā§āϰāĻžāϤāύ āϏā§āĻāĻŋāĻāϏ āĻŽā§āύ⧠āĻĻā§āĻāĻžāύ⧠āĻšāĻā§āĻā§</string>
|
||||
<string name="revanced_restore_old_settings_menus_summary_off">āĻĒā§āϰāĻžāϤāύ āϏā§āĻāĻŋāĻāϏ āĻŽā§āύ⧠āĻĻā§āĻāĻžāύ⧠āĻšāĻā§āĻā§ āύāĻž</string>
|
||||
</patch>
|
||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||
<string name="revanced_shorts_disable_background_playback_title">Shorts āĻŦā§āϝāĻžāĻāĻā§āϰāĻžāĻāύā§āĻĄ āĻĒā§āϞ⧠āĻ
āĻā§āώāĻŽ āĻāϰā§āύ</string>
|
||||
@@ -446,6 +506,9 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_swipe_overlay_background_alpha_summary">āϏā§ā§āĻžāĻāĻĒ āĻāĻāĻžāϰāϞ⧠āĻŦā§āϝāĻžāĻāĻā§āϰāĻžāĻāύā§āĻĄā§āϰ āĻĻā§āĻļā§āϝāĻŽāĻžāύāϤāĻž</string>
|
||||
<string name="revanced_swipe_threshold_title">āϏā§ā§āĻžāĻāĻĒ āĻĨā§āϰā§āĻļāĻšā§āϞā§āĻĄ āĻāϰ āĻŽāĻžāϤā§āϰāĻž</string>
|
||||
<string name="revanced_swipe_threshold_summary">āϏā§ā§āĻžāĻāĻĒ āĻāϰāĻžāϰ āĻĨā§āϰā§āĻļāĻšā§āϞā§āĻĄā§āϰ āĻĒāϰāĻŋāĻŽāĻžāĻŖ</string>
|
||||
<string name="revanced_swipe_change_video_title">āĻāĻŋāĻĄāĻŋāĻ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāϤ⧠āϏā§āϝāĻŧāĻžāĻāĻĒ āĻāϰ⧠āϏāĻā§āώāĻŽ āĻāϰā§āύ</string>
|
||||
<string name="revanced_swipe_change_video_summary_on">āĻĢā§āϞāϏā§āĻā§āϰāĻŋāύ āĻŽā§āĻĄā§ āϏā§āϝāĻŧāĻžāĻāĻĒ āĻāϰāϞ⧠āĻĒāϰāĻŦāϰā§āϤā§/āĻĒā§āϰā§āĻŦāĻŦāϰā§āϤ⧠āĻāĻŋāĻĄāĻŋāĻāϤ⧠āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻšāĻŦā§</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">āĻĢā§āϞāϏā§āĻā§āϰāĻŋāύ āĻŽā§āĻĄā§ āϏā§āϝāĻŧāĻžāĻāĻĒ āĻāϰāϞ⧠āĻĒāϰāĻŦāϰā§āϤ⧠/āĻĒā§āϰā§āĻŦāĻŦāϰā§āϤ⧠āĻāĻŋāĻĄāĻŋāĻāϤ⧠āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻšāĻŦā§ āύāĻž</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">āϏā§āĻŦā§āĻāĻā§āϰāĻŋā§ āĻā§āϝāĻžāĻĒāĻļāύ āĻŦāύā§āϧ āĻāϰā§āύ</string>
|
||||
@@ -629,15 +692,18 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_shorts_player_screen_summary">Shorts āĻĒā§āϞā§āϝāĻŧāĻžāϰ⧠āĻāĻĒāĻžāĻĻāĻžāύ āϞā§āĻāĻžāύ⧠āĻŦāĻž āĻĻā§āĻāĻžāύā§</string>
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">āĻĒā§āϰāϧāĻžāύ āĻĢāĻŋāĻĄā§ Shorts āϞā§āĻāĻžāύ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">āĻĒā§āϰāϧāĻžāύ āĻĢāĻŋāĻĄā§ Shorts āϞā§āĻāĻŋā§ā§ āϰā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">āĻĒā§āϰāϧāĻžāύ āĻĢāĻŋāĻĄā§ Shorts āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">āĻŦāĻžāĻĄāĻŧāĻŋāϰ āĻĢāĻŋāĻĄ āĻāĻŦāĻ āϏāĻŽā§āĻĒāϰā§āĻāĻŋāϤ āĻāĻŋāĻĄāĻŋāĻāϤ⧠āϞā§āĻāĻžāύ⧠āĻšāϝāĻŧā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">āĻŦāĻžāĻĄāĻŧāĻŋāϰ āĻĢāĻŋāĻĄ āĻāĻŦāĻ āϏāĻŽā§āĻĒāϰā§āĻāĻŋāϤ āĻāĻŋāĻĄāĻŋāĻāϤ⧠āĻĻā§āĻāĻžāύ⧠āĻšāϝāĻŧā§āĻā§</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">āϏāĻĻāϏā§āϝāϤāĻž āĻĢāĻŋāĻĄā§ Shorts āϞā§āĻāĻžāύ</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">āϏāĻĻāϏā§āϝāϤāĻž āĻĢāĻŋāĻĄā§ Shorts āϞā§āĻāĻŋā§ā§ āϰā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">āϏāĻĻāϏā§āϝāϤāĻž āĻĢāĻŋāĻĄā§ Shorts āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">āϏāĻžāĻŦāϏā§āĻā§āϰāĻŋāĻĒāĻļāύ āĻĢāĻŋāĻĄā§ āϞā§āĻāĻžāύ⧠āĻāĻā§</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">āϏāĻžāĻŦāϏā§āĻā§āϰāĻŋāĻĒāĻļāύ āĻĢāĻŋāĻĄā§ āĻĻā§āĻāĻžāύ⧠āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_search_title">āĻ
āύā§āϏāύā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧠Shorts āϞā§āĻāĻžāύ</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">āĻ
āύā§āϏāύā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧠Shorts āϞā§āĻāĻŋā§ā§ āϰā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">āĻ
āύā§āϏāύā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧠Shorts āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">āĻ
āύā§āϏāύā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧠āϞā§āĻāĻžāύā§</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">āϏāĻžāϰā§āĻ āϰā§āĻāĻžāϞā§āĻā§ āĻĻā§āĻāĻžāύ⧠āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_shorts_history_title">ShortsāĻā§āϞāĻŋāĻā§ āĻāϝāĻŧāĻžāĻ āĻāϤāĻŋāĻšāĻžāϏ⧠āϞā§āĻāĻžāύ</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">āĻāϝāĻŧāĻžāĻ āĻšāĻŋāϏā§āĻā§āϰāĻŋāϤ⧠āϞā§āĻāĻžāύā§</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">āĻāϝāĻŧāĻžāĻ āĻāϤāĻŋāĻšāĻžāϏ⧠āĻĻā§āĻāĻžāύā§</string>
|
||||
<!-- 'join' should be translated using the same localized wording YouTube displays for the button. -->
|
||||
<string name="revanced_hide_shorts_join_button_title">āĻā§ā§āύ āĻāϰā§āύ āĻŦā§āϤāĻžāĻŽ āϞā§āĻāĻžāύ</string>
|
||||
<string name="revanced_hide_shorts_join_button_summary_on">āĻā§ā§āύ āĻāϰā§āύ āĻŦā§āϤāĻžāĻŽ āϞā§āĻāĻŋā§ā§ āϰā§ā§āĻā§</string>
|
||||
@@ -739,6 +805,13 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_hide_player_popup_panels_summary_on">āĻĒā§āϞā§ā§āĻžāϰ āĻĒāĻĒāĻāĻĒ āĻĒā§āϝāĻžāύā§āϞāĻā§āϞ⧠āϞā§āĻāĻŋā§ā§ āϰā§ā§āĻā§</string>
|
||||
<string name="revanced_hide_player_popup_panels_summary_off">āĻĒā§āϞā§ā§āĻžāϰ āĻĒāĻĒāĻāĻĒ āĻĒā§āϝāĻžāύā§āϞāĻā§āϞ⧠āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšā§ā§āĻā§</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
<string name="revanced_exit_fullscreen_title">āĻāĻŋāĻĄāĻŋāĻ āĻļā§āώ āĻšāĻāϝāĻŧāĻžāϰ āϏāĻŽāϝāĻŧ āĻĒā§āϰā§āĻŖ āĻĒāϰā§āĻĻāĻž āĻŽā§āĻĄ āĻĨā§āĻā§ āĻŦā§āϰāĻŋāϝāĻŧā§ āϝāĻžāύ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_1">āύāĻŋāώā§āĻā§āϰāĻŋāϝāĻŧ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_2">āĻāύā§āĻā§āĻŽāĻŋāĻ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_3">āϞā§āϝāĻžāύā§āĻĄāϏā§āĻā§āĻĒ</string>
|
||||
<string name="revanced_exit_fullscreen_entry_4">āĻāύā§āĻā§āĻŽāĻŋāĻ āĻāĻŦāĻ āϞā§āϝāĻžāύā§āĻĄāϏā§āĻā§āĻĒ</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">āĻĒā§āϰā§āĻŖ āĻĒāϰā§āĻĻāĻžāϝāĻŧ āĻāĻŋāĻĄāĻŋāĻ āĻā§āϞā§āύ</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_on">āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϰā§āĻŖ āĻĒāϰā§āĻĻāĻžāϝāĻŧ āĻā§āϞāĻŦā§</string>
|
||||
@@ -1007,6 +1080,23 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_sb_reset">āĻĒā§āύāϰāĻžāϝāĻŧ āϏā§āĻ āĻāϰā§āύ</string>
|
||||
<string name="revanced_sb_about">āϏāĻŽā§āĻĒāϰā§āĻāĻŋāϤ</string>
|
||||
<string name="revanced_sb_about_api_sum">āĻĄā§āĻāĻž SponsorBlock API āĻĻā§āĻŦāĻžāϰāĻž āϏāϰāĻŦāϰāĻžāĻš āĻāϰāĻž āĻšāϝāĻŧāĨ¤ āĻāϰāĻ āĻāĻžāύāϤ⧠āĻāĻŦāĻ āĻ
āύā§āϝāĻžāύā§āϝ āĻĒā§āϞā§āϝāĻžāĻāĻĢāϰā§āĻŽā§āϰ āĻĄāĻžāĻāύāϞā§āĻĄ āĻĻā§āĻāϤ⧠āĻāĻāĻžāύ⧠āĻā§āϝāĻžāĻĒ āĻāϰā§āύ</string>
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
<string name="revanced_change_form_factor_title">āϞā§āĻāĻāĻ āĻĢāϰā§āĻŽ āĻĢā§āϝāĻžāĻā§āĻāϰ</string>
|
||||
<string name="revanced_change_form_factor_entry_1">āĻĄāĻŋāĻĢāϞā§āĻ</string>
|
||||
<string name="revanced_change_form_factor_entry_2">āĻĢā§āύ</string>
|
||||
<string name="revanced_change_form_factor_entry_3">āĻā§āϝāĻžāĻŦāϞā§āĻ</string>
|
||||
<string name="revanced_change_form_factor_entry_4">āϏā§āĻŦāϝāĻŧāĻāĻāĻžāϞāĻŋāϤ</string>
|
||||
<string name="revanced_change_form_factor_user_dialog_message">"āĻĒāϰāĻŋāĻŦāϰā§āϤāύāĻā§āϞ⧠āĻšāϞ:
|
||||
|
||||
āĻā§āϝāĻžāĻŦāϞā§āĻ āϞā§āĻāĻāĻ
|
||||
âĸ āĻāĻŽāĻŋāĻāύāĻŋāĻāĻŋ āĻĒā§āϏā§āĻ āĻā§āĻĒāύ
|
||||
|
||||
āϏā§āĻŦāϝāĻŧāĻāĻāĻžāϞāĻŋāϤ āϞā§āĻāĻāĻ
|
||||
âĸ āĻāĻĄāĻŧāĻŋāϰ āĻāϤāĻŋāĻšāĻžāϏ āĻŽā§āύ⧠āĻā§āĻĒāύ
|
||||
âĸ āĻāĻā§āϏāĻĒā§āϞā§āϰ āĻā§āϝāĻžāĻŦ āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§
|
||||
âĸ āĻļāϰā§āĻāϏ āύāĻŋāϝāĻŧāĻŽāĻŋāϤ āĻĒā§āϞā§āϝāĻŧāĻžāϰ⧠āĻā§āϞā§
|
||||
âĸ āĻĢāĻŋāĻĄ āĻŦāĻŋāώāϝāĻŧ āĻāĻŦāĻ āĻā§āϝāĻžāύā§āϞ āĻĻā§āĻŦāĻžāϰāĻž āϏāĻāĻāĻ āĻŋāϤ āĻšāϝāĻŧ"</string>
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<string name="revanced_spoof_app_version_title">āĻ
ā§āϝāĻžāĻĒ āϏāĻāϏā§āĻāϰāĻŖ āϏā§āĻĒā§āĻĢ āĻāϰā§āύ</string>
|
||||
@@ -1021,6 +1111,7 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
<string name="revanced_spoof_app_version_target_title">āϏā§āĻĒā§āĻĢ āĻ
ā§āϝāĻžāĻĒ āϏāĻāϏā§āĻāϰāĻŖ āϞāĻā§āώā§āϝ</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - āĻĒā§āϰāύ⧠Shorts āĻĒā§āϞā§āϝāĻŧāĻžāϰ āĻāĻāĻāύ āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§āύ</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.26.42 - āĻĒā§āϰā§āύ⧠āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻŦāĻ āĻā§āϞāĻŦāĻžāϰ āĻāĻāĻāύ āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§āύ</string>
|
||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_1">18.33.40 - āĻāĻĻā§āĻŽāĻŦā§āĻļāĻŋ āĻŽā§āĻĄā§ RYD āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§</string>
|
||||
<string name="revanced_spoof_app_version_target_legacy_entry_2">18.20.39 - āĻĒā§āϰāĻļā§āĻŦāϏā§āϤ āĻāĻŋāĻĄāĻŋāĻ āϏā§āĻĒāĻŋāĻĄ āĻāĻŦāĻ āĻā§āĻŖāĻŽāĻžāύ āĻŽā§āύ⧠āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§</string>
|
||||
@@ -1064,12 +1155,6 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_shorts_autoplay_background_summary_on">āĻĒāĻāĻā§āĻŽāĻŋāϤ⧠Shorts āĻ
āĻā§āĻĒā§āϞ⧠āĻšāĻŦā§</string>
|
||||
<string name="revanced_shorts_autoplay_background_summary_off">āĻĒāĻāĻā§āĻŽāĻŋāϤ⧠Shorts āĻĒā§āύāϰāĻžāĻŦā§āϤā§āϤāĻŋ āĻšāĻŦā§</string>
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
<string name="revanced_tablet_layout_title">āĻā§āϝāĻžāĻŦāϞā§āĻ āϞā§āĻāĻāĻ āϏāĻā§āϰāĻŋā§ āĻāϰā§āύ</string>
|
||||
<string name="revanced_tablet_layout_summary_on">āĻā§āϝāĻžāĻŦāϞā§āĻ āϞā§āĻāĻāĻ āϏāĻā§āϰāĻŋā§ āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_tablet_layout_summary_off">āĻā§āϝāĻžāĻŦāϞā§āĻ āϞā§āĻāĻāĻ āύāĻŋāώā§āĻā§āϰāĻŋā§ āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_tablet_layout_user_dialog_message">āĻā§āϝāĻžāĻŦāϞā§āĻ āϞā§āĻāĻāĻā§ āĻāĻŽāĻŋāĻāύāĻŋāĻāĻŋ āĻĒā§āϏā§āĻ āĻĻā§āĻāĻžāĻŦā§ āύāĻž</string>
|
||||
</patch>
|
||||
<patch id="layout.miniplayer.miniplayerPatch">
|
||||
<string name="revanced_miniplayer_screen_title">āĻŽāĻŋāύāĻŋāĻĒā§āϞā§ā§āĻžāϰ</string>
|
||||
<string name="revanced_miniplayer_screen_summary">āĻ
ā§āϝāĻžāĻĒā§āϰ āĻŽāϧā§āϝāĻāĻžāϰ āĻŽāĻŋāύāĻŋāĻŽāĻžāĻāĻāĻĄ āĻĒā§āϞā§ā§āĻžāϰ āĻāϰ āϧāϰāĻŖ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰā§āύ</string>
|
||||
@@ -1234,6 +1319,7 @@ DeArrow āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āĻāĻžāύāϤ⧠āĻāĻāĻžāύ⧠āĻ
|
||||
<string name="revanced_force_original_audio_title">āĻŽā§āϞ āĻ
āĻĄāĻŋāĻ āĻŦāϞāĻĒā§āϰā§āĻŦāĻ āĻāĻžāϞ⧠āĻāϰā§āύ</string>
|
||||
<string name="revanced_force_original_audio_summary_on">āĻŽā§āϞ āĻ
āĻĄāĻŋāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻā§</string>
|
||||
<string name="revanced_force_original_audio_summary_off">āĻĄāĻŋāĻĢāϞā§āĻ āĻ
āĻĄāĻŋāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻā§</string>
|
||||
<string name="revanced_force_original_audio_not_available">āĻāĻ āĻŦā§āĻļāĻŋāώā§āĻā§āϝāĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āĻāύā§āϝ, iOS āĻā§āϞāĻžā§ā§āύā§āĻ āĻĒā§āϰāĻāĻžāϰ⧠āϏā§āĻā§āϰāĻŋāĻŽ āϏā§āĻĒā§āĻĢāĻŋāĻ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰā§āύ</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
|
||||
@@ -1261,6 +1347,8 @@ DeArrow āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āĻāĻžāύāϤ⧠āĻāĻāĻžāύ⧠āĻ
|
||||
<string name="revanced_custom_playback_speeds_invalid">āĻāĻžāϏā§āĻāĻŽ āĻāϤāĻŋ %s āĻāϰ āĻā§āϝāĻŧā§ āĻāĻŽ āĻšāϤ⧠āĻšāĻŦā§</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">āĻ
āĻŦā§āϧ āĻāĻžāϏā§āĻāĻŽ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āĻāϤāĻŋ</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">āϏā§āĻŦāϤāϏā§āĻĢā§āϰā§āϤāĻāĻžāĻŦā§</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">āĻāĻžāϏā§āĻāĻŽ āĻā§āϝāĻžāĻĒ āĻāύā§āĻĄ āĻšā§āϞā§āĻĄ āϏā§āĻĒāĻŋāĻĄ</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">ā§Ļ-ā§Ž āĻāϰ āĻŽāϧā§āϝ⧠āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āϏā§āĻĒāĻŋāĻĄ</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">āĻĒā§āϞā§āĻŦā§āϝāĻžāĻā§āϰ āϏā§āĻĒāĻŋāĻĄ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻŽāύ⧠āϰāĻžāĻā§āύ</string>
|
||||
@@ -1289,73 +1377,27 @@ DeArrow āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āĻāĻžāύāϤ⧠āĻāĻāĻžāύ⧠āĻ
|
||||
āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āĻāĻžāĻ āύāĻžāĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">āĻāĻ āϏā§āĻāĻŋāĻāĻāĻŋ āĻŦāύā§āϧ āĻāϰāĻžāϰ āĻĢāϞ⧠āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āϤā§āϰā§āĻāĻŋ āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">āĻĄāĻŋāĻĢāϞā§āĻ āĻā§āϞāĻžā§ā§āύā§āĻ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">AVC (H.264) āĻĢā§āϰā§āϏ āĻāϰā§āύ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ AVC (H.264) āϤ⧠āĻŦāĻžāϧā§āϝ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āύāĻŋāϰā§āϧāĻžāϰāĻŋāϤ āĻšāĻā§āĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"āĻāĻāĻŋ āϏāĻā§āϰāĻŋāϝāĻŧ āĻāϰāĻž āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āϞāĻžāĻāĻĢ āĻāύā§āύāϤ āĻāϰāϤ⧠āĻĒāĻžāϰ⧠āĻāĻŦāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āĻšā§āĻāĻāĻ āĻāĻžāĻāϝāĻŧāĻž āĻ āĻŋāĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
|
||||
<!-- 'no auth' means no authentication -->
|
||||
<string name="revanced_spoof_video_streams_client_type_android_vr_no_auth">Android VR (āϏā§āĻŦā§āĻā§āϤāĻŋ āĻāĻžāĻĄāĻŧāĻž)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) āĻŦāĻžāϧā§āϝāϤāĻžāĻŽā§āϞāĻ āĻāϰā§āύ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ AVC (H.264) āĻ āĻŦāĻžāϧā§āϝāϤāĻžāĻŽā§āϞāĻ āĻāϰāĻž āĻšā§ā§āĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āύāĻŋāϰā§āϧāĻžāϰāĻŋāϤ āĻšā§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"āĻāĻāĻŋ āϏāĻā§āώāĻŽ āĻāϰāϞ⧠āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āϞāĻžāĻāĻĢ āĻāύā§āύāϤ āĻšāϤ⧠āĻĒāĻžāϰ⧠āĻāĻŦāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āϏā§āĻāĻžāĻāĻžāϰāĻŋāĻ āϏāĻŽāϏā§āϝāĻž āϏāĻŽāĻžāϧāĻžāύ āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤
|
||||
|
||||
AVC-āĻāϰ āϏāϰā§āĻŦā§āĻā§āĻ āϰā§āĻā§āϞāĻŋāĻāĻļāύ 1080p, Opus āĻ
āĻĄāĻŋāĻ āĻā§āĻĄā§āĻ āĻāĻĒāϞāĻŦā§āϧ āύāϝāĻŧ āĻāĻŦāĻ āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ VP9 āĻŦāĻž AV1 āĻāϰ āϤā§āϞāύāĻžāϝāĻŧ āĻāϰāĻ āĻāύā§āĻāĻžāϰāύā§āĻ āĻĄā§āĻāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦā§āĨ¤"</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_title">iOS āϏā§āĻĒā§āĻĢāĻŋāĻ āĻāϰ āĻĒāĻžāϰā§āĻļā§āĻŦ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_summary">"âĸ āĻŦā§āϏāϰāĻāĻžāϰāĻŋ āĻļāĻŋāĻļā§ āĻāĻŋāĻĄāĻŋāĻ āĻāϞāϤ⧠āύāĻžāĻ āĻĒāĻžāϰā§<br>âĸ āĻāĻŋāĻĄāĻŋāĻāĻā§āϞāĻŋ 1 āϏā§āĻā§āύā§āĻĄ āĻāĻā§ āĻļā§āώ āĻšā§"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_title">Android VR āϏā§āĻĒā§āĻĢāĻŋāĻ āĻāϰ āĻĒāĻžāϰā§āĻļā§āĻŦ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_vr_summary">"âĸ āĻļāĻŋāĻļā§āĻĻā§āϰ āĻāĻŋāĻĄāĻŋāĻ āĻāĻžāϞ⧠āύāĻžāĻ āĻšāϤ⧠āĻĒāĻžāϰā§
|
||||
âĸ āĻ
āĻĄāĻŋāĻ āĻā§āϰā§āϝāĻžāĻ āĻŽā§āύ⧠āĻ
āύā§āĻĒāϏā§āĻĨāĻŋāϤ
|
||||
âĸ āϏā§āĻĨāĻŋāϤāĻŋāĻļā§āϞ āĻāϞāĻŋāĻāĻŽ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāĻā§āĻā§ āύāĻž
|
||||
âĸ āĻāϏāϞ āĻ
āĻĄāĻŋāĻ āĻā§āϰāĻĒā§āϰā§āĻŦāĻ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāĻā§āĻā§ āύāĻž"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">āĻĄāĻŋāĻĢāϞā§āĻ āĻ
āĻĄāĻŋāĻ āϏā§āĻā§āϰāĻŋāĻŽ āĻāĻžāώāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">āĻ
ā§āϝāĻžāĻĒ āĻāĻžāώāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">āĻāϰāĻŦāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_AZ">āĻāĻāĻžāϰāĻŦāĻžāĻāĻāĻžāύāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_BG">āĻŦā§āϞāĻā§āϰāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_BN">āĻŦāĻžāĻāϞāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_CA">āĻāĻžāϤāĻžāϞāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_CS">āĻā§āĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DA">āĻĄā§āύāĻŋāĻļ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DE">āĻāĻžāϰā§āĻŽāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_EL">āĻā§āϰā§āĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_EN">āĻāĻāϰā§āĻāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ES">āϏā§āĻĒā§āϝāĻžāύāĻŋāĻļ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ET">āĻāϏā§āϤā§āύāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FA">āĻĢāĻžāϰā§āϏāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FI">āĻĢāĻŋāύāϞā§āϝāĻžāύā§āĻĄ</string>
|
||||
<string name="revanced_spoof_video_streams_language_FR">āĻĢāϰāĻžāϏāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_GU">āĻā§āĻāϰāĻžāĻāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_HI">āĻšāĻŋāύā§āĻĻāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_HR">āĻā§āϰā§āϝāĻŧā§āĻļāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_HU">āĻšāĻžāĻā§āĻā§āϰāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ID">āĻāύā§āĻĻā§āύā§āĻļāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_IT">āĻāϤāĻžāϞā§āϝāĻŧ</string>
|
||||
<string name="revanced_spoof_video_streams_language_JA">āĻāĻžāĻĒāĻžāύāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_KK">āĻāĻžāĻāĻžāĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_KO">āĻā§āϰāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_LT">āϞāĻŋāĻĨā§āϝāĻŧāĻžāύāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_LV">āϞāĻžāϤāĻāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MK">āĻŽā§āϝāĻžāϏā§āĻĄā§āύāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MN">āĻŽāĻā§āĻā§āϞāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MR">āĻŽāĻžāϰāĻžāĻ āĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MS">āĻŽāĻžāϞāϝāĻŧ</string>
|
||||
<string name="revanced_spoof_video_streams_language_MY">āĻŦāĻžāϰā§āĻŽāĻŋāĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_NL">āĻĄāĻžāĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_OR">āĻāĻĄāĻŧāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">āĻĒāĻā§āĻāĻžāĻŦāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">āĻĒā§āϞāĻŋāĻļ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">āĻĒāϰā§āϤā§āĻāĻŋāĻ (āĻŦā§āϰāĻžāĻāĻŋāϞ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">āĻĒāϰā§āϤā§āĻāĻŋāĻ (āĻĒāϰā§āϤā§āĻāĻžāϞ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">āϰā§āĻŽāĻžāύā§āϝāĻŧ</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">āϰāĻžāĻļāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">āϏā§āϞā§āĻāĻžāĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SL">āϏā§āϞā§āĻā§āύāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SR">āϏāĻžāϰā§āĻŦāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SV">āϏā§āĻāĻĄāĻŋāĻļ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SW">āϏā§āϝāĻŧāĻžāĻšāĻŋāϞāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TA">āϤāĻžāĻŽāĻŋāϞ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TE">āϤā§āϞā§āĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_language_TH">āĻĨāĻžāĻ</string>
|
||||
<string name="revanced_spoof_video_streams_language_TR">āϤā§āϰā§āĻāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_UK">āĻāĻāĻā§āϰā§āύā§āϝāĻŧ</string>
|
||||
<string name="revanced_spoof_video_streams_language_UR">āĻāϰā§āĻĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_language_VI">āĻāĻŋāϝāĻŧā§āϤāύāĻžāĻŽāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_ZH">āĻā§āύāĻž</string>
|
||||
AVC-āĻāϰ āϏāϰā§āĻŦā§āĻā§āĻ āϰā§āĻā§āϞāĻŋāĻāĻļāύ āĻšāϞ 1080p, Opus āĻ
āĻĄāĻŋāĻ āĻā§āĻĄā§āĻ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻž āĻāĻŦāĻ VP9 āĻŦāĻž AV1-āĻāϰ āϤā§āϞāύāĻžāϝāĻŧ āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻā§ āĻŦā§āĻļāĻŋ āĻāύā§āĻāĻžāϰāύā§āĻ āĻĄā§āĻāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāĻŦā§ã"</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">āĻāĻāĻāĻāϏ āϏā§āĻĒā§āĻĢāĻŋāĻāϝāĻŧā§āϰ āĻĒāĻžāϰā§āĻļā§āĻŦ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"âĸ āĻŽā§āĻāĻŋ āĻŦāĻž āĻ
āϰā§āĻĨ āĻĒā§āϰāĻĻāĻžāύā§āϰ āĻāĻŋāĻĄāĻŋāĻ āĻāĻžāϞ⧠āύāĻžāĻ āĻšāϤ⧠āĻĒāĻžāϰā§
|
||||
âĸ āϏā§āĻĨāĻŋāϰ āĻāϞāĻŋāĻāĻŽ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻž
|
||||
âĸ āĻāĻŋāĻĄāĻŋāĻāĻā§āϞāĻŋ 1 āϏā§āĻā§āύā§āĻĄ āĻāĻā§ āĻļā§āώ āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧ"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Android āϏā§āĻĒā§āĻĢāĻŋāĻāϝāĻŧā§āϰ āĻĒāĻžāϰā§āĻļā§āĻŦāĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"âĸ āĻ
āĻĄāĻŋāĻ āĻā§āϰā§āϝāĻžāĻ āĻŽā§āύ⧠āύā§āĻ
|
||||
âĸ āϏā§āĻĨāĻŋāϰ āĻāϞāĻŋāĻāĻŽ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻž
|
||||
âĸ āĻŽā§āϞ āĻ
āĻĄāĻŋāĻ āĻā§āϰ āĻāϰ⧠āĻāĻžāϞ⧠āĻāϰāĻž āϝāĻžāϝāĻŧ āύāĻž"</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">âĸ āĻā§āύ⧠AV1 āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ āύā§āĻ</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">āϏā§āĻā§āϝāĻžāĻāϏ āĻĢāϰ āύāĻžāϰā§āĻĄāϏ⧠āĻĻā§āĻāĻžāύ</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">āϏā§āĻā§āϝāĻžāĻāϏ āĻĢāϰ āύāĻžāϰā§āĻĄāϏ⧠āĻā§āϞāĻžāϝāĻŧā§āύā§āĻ āĻĒā§āϰāĻāĻžāϰ āĻĻā§āĻāĻžāύ⧠āĻšāĻŦā§</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">āϏā§āĻā§āϝāĻžāĻāϏ āĻĢāϰ āύāĻžāϰā§āĻĄāϏ⧠āĻā§āϞāĻžāϝāĻŧā§āύā§āĻ āϞā§āĻāĻžāύ⧠āĻšāĻŦā§</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">VR āĻĄāĻŋāĻĢāϞā§āĻ āĻ
āĻĄāĻŋāĻ āϏā§āĻā§āϰāĻŋāĻŽ āĻāĻžāώāĻž</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user