Compare commits

..

67 Commits

Author SHA1 Message Date
semantic-release-bot
36036b082d chore: Release v5.33.0-dev.12 [skip ci]
# [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04)

### Bug Fixes

* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([1bc63e5](1bc63e50a7))
2025-08-04 19:19:31 +00:00
LisoUseInAIKyrios
1bc63e50a7 fix(YouTube - Video quality): Fix dialog quality list check mark not always shown 2025-08-04 15:17:00 -04:00
semantic-release-bot
4b2b5e3029 chore: Release v5.33.0-dev.11 [skip ci]
# [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04)

### Bug Fixes

* **YouTube - Video quality:** Fix 144p default not always used ([9afa7d2](9afa7d2ac6))
2025-08-04 19:03:03 +00:00
LisoUseInAIKyrios
9afa7d2ac6 fix(YouTube - Video quality): Fix 144p default not always used 2025-08-04 15:00:14 -04:00
semantic-release-bot
1a8146dbc8 chore: Release v5.33.0-dev.10 [skip ci]
# [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04)

### Bug Fixes

* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([178eed7](178eed7fcd))
2025-08-04 17:23:50 +00:00
LisoUseInAIKyrios
178eed7fcd fix(YouTube - Video quality): Fix wrong qualities sometimes shown in player button dialog 2025-08-04 13:21:02 -04:00
semantic-release-bot
621292644c chore: Release v5.33.0-dev.9 [skip ci]
# [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04)

### Bug Fixes

* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([1dd01cf](1dd01cf54a))
2025-08-04 01:27:12 +00:00
LisoUseInAIKyrios
1dd01cf54a fix(YouTube - Force original audio): Disable a/b feature flag that forces localized audio (#5582) 2025-08-03 21:23:27 -04:00
semantic-release-bot
8c31374c53 chore: Release v5.33.0-dev.8 [skip ci]
# [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03)

### Bug Fixes

* **NFC Tools:** Remove broken patch that is no longer supported ([#5584](https://github.com/ReVanced/revanced-patches/issues/5584)) ([2e177a8](2e177a8839))
2025-08-03 23:44:42 +00:00
LisoUseInAIKyrios
2e177a8839 fix(NFC Tools): Remove broken patch that is no longer supported (#5584) 2025-08-03 19:41:54 -04:00
github-actions[bot]
cfffd422f8 chore: Sync translations (#5586) 2025-08-03 19:41:07 -04:00
github-actions[bot]
37aab8382e chore: Sync translations (#5585) 2025-08-03 19:38:17 -04:00
semantic-release-bot
f4950ec2ea chore: Release v5.33.0-dev.7 [skip ci]
# [5.33.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.6...v5.33.0-dev.7) (2025-08-03)

### Features

* **YouTube:** Add player button to change video quality ([#5435](https://github.com/ReVanced/revanced-patches/issues/5435)) ([7bdc328](7bdc32867a))
2025-08-03 15:26:39 +00:00
MarcaD
7bdc32867a feat(YouTube): Add player button to change video quality (#5435)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2025-08-03 11:23:46 -04:00
semantic-release-bot
6e60ac6963 chore: Release v5.33.0-dev.6 [skip ci]
# [5.33.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.5...v5.33.0-dev.6) (2025-07-31)

### Bug Fixes

* **YouTube - Video quality:** Use 1080p enhanced bitrate for Premium users ([#5565](https://github.com/ReVanced/revanced-patches/issues/5565)) ([1adbd56](1adbd563b2))
2025-07-31 18:30:03 +00:00
LisoUseInAIKyrios
1adbd563b2 fix(YouTube - Video quality): Use 1080p enhanced bitrate for Premium users (#5565) 2025-07-31 14:27:17 -04:00
github-actions[bot]
9ccf13b680 chore: Sync translations (#5567) 2025-07-31 14:27:05 -04:00
semantic-release-bot
7b8ca9c018 chore: Release v5.33.0-dev.5 [skip ci]
# [5.33.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.4...v5.33.0-dev.5) (2025-07-31)

### Bug Fixes

* **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([b1d164b](b1d164b446))
2025-07-31 10:35:51 +00:00
github-actions[bot]
ae6dd23d08 chore: Sync translations (#5564) 2025-07-31 06:33:31 -04:00
LisoUseInAIKyrios
b1d164b446 fix(YouTube - Litho filter): Correctly filter identifier of older YouTube targets 2025-07-31 06:33:12 -04:00
dependabot[bot]
87c39dd485 chore(deps-dev): Bump semantic-release from 24.2.6 to 24.2.7 (#5545) 2025-07-30 10:31:08 -04:00
semantic-release-bot
1549ac12aa chore: Release v5.33.0-dev.4 [skip ci]
# [5.33.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.3...v5.33.0-dev.4) (2025-07-30)

### Performance Improvements

* **YouTube:** Filter identifier callback only on root component creation ([#5558](https://github.com/ReVanced/revanced-patches/issues/5558)) ([5d08fdd](5d08fdddb8))
2025-07-30 13:21:43 +00:00
LisoUseInAIKyrios
5d08fdddb8 perf(YouTube): Filter identifier callback only on root component creation (#5558) 2025-07-30 09:18:20 -04:00
semantic-release-bot
98114e5bde chore: Release v5.33.0-dev.3 [skip ci]
# [5.33.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.2...v5.33.0-dev.3) (2025-07-30)

### Bug Fixes

* **YouTube - Playback speed:** Use old speed menu for player button if enabled ([a4817df](a4817dfdd0))
2025-07-30 10:06:04 +00:00
LisoUseInAIKyrios
a4817dfdd0 fix(YouTube - Playback speed): Use old speed menu for player button if enabled 2025-07-30 06:03:21 -04:00
semantic-release-bot
d4f05351e1 chore: Release v5.33.0-dev.2 [skip ci]
# [5.33.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.1...v5.33.0-dev.2) (2025-07-29)

### Features

* **ORF ON:** Add `Remove root detection` patch ([#5551](https://github.com/ReVanced/revanced-patches/issues/5551)) ([d92362b](d92362b0d9))
2025-07-29 08:33:08 +00:00
abichinger
d92362b0d9 feat(ORF ON): Add Remove root detection patch (#5551) 2025-07-29 04:30:43 -04:00
github-actions[bot]
afc7c75df1 chore: Sync translations (#5555) 2025-07-29 04:29:42 -04:00
semantic-release-bot
f0d4e9bfb4 chore: Release v5.33.0-dev.1 [skip ci]
# [5.33.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0-dev.1) (2025-07-28)

### Features

* **YouTube - Playback speed:** Add "Restore old playback speed menu" option ([#5552](https://github.com/ReVanced/revanced-patches/issues/5552)) ([e9e4cf3](e9e4cf39b6))
2025-07-28 18:47:44 +00:00
LisoUseInAIKyrios
e9e4cf39b6 feat(YouTube - Playback speed): Add "Restore old playback speed menu" option (#5552) 2025-07-28 22:44:18 +04:00
semantic-release-bot
0579a9f760 chore: Release v5.32.0 [skip ci]
# [5.32.0](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.32.0) (2025-07-27)

### Bug Fixes

* **Messenger - Hide inbox ads:** Support the latest app version ([8ec857a](8ec857a175))
* **YouTube  - Hide layout components:** Fix "Hide ticket shelf" ([#5516](https://github.com/ReVanced/revanced-patches/issues/5516)) ([9ddb3ac](9ddb3ac39d))
* **YouTube - GmsCore support:** Fix search suggestions when logged out by using correct search provider ([#5483](https://github.com/ReVanced/revanced-patches/issues/5483)) ([e4e81b8](e4e81b89ea))

### Features

* **Prime Video:** Add `Playback speed` patch ([#5444](https://github.com/ReVanced/revanced-patches/issues/5444)) ([f46dbcd](f46dbcd084))
* **YouTube - External downloads:** Improve the selection of the external downloader package ([#5504](https://github.com/ReVanced/revanced-patches/issues/5504)) ([cfd7780](cfd77800d6))
* **YT Music:** Support latest versions ([#5524](https://github.com/ReVanced/revanced-patches/issues/5524)) ([1258555](125855540b))
2025-07-27 13:17:58 +00:00
LisoUseInAIKyrios
1c0acef3f3 chore: Merge branch dev to main (#5479) 2025-07-27 17:14:36 +04:00
github-actions[bot]
2419adb77b chore: Sync translations (#5544) 2025-07-27 17:14:11 +04:00
semantic-release-bot
9e4113555b chore: Release v5.32.0-dev.5 [skip ci]
# [5.32.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.4...v5.32.0-dev.5) (2025-07-26)

### Features

* **YT Music:** Support latest versions ([#5524](https://github.com/ReVanced/revanced-patches/issues/5524)) ([1258555](125855540b))
2025-07-26 06:30:30 +00:00
netceil
125855540b feat(YT Music): Support latest versions (#5524) 2025-07-26 10:27:47 +04:00
github-actions[bot]
a8eee825e6 chore: Sync translations (#5538) 2025-07-26 10:27:17 +04:00
semantic-release-bot
63859f0ef9 chore: Release v5.32.0-dev.4 [skip ci]
# [5.32.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.3...v5.32.0-dev.4) (2025-07-25)

### Bug Fixes

* **Messenger - Hide inbox ads:** Support the latest app version ([8ec857a](8ec857a175))
2025-07-25 06:53:39 +00:00
github-actions[bot]
1c9000dbda chore: Sync translations (#5531) 2025-07-25 10:51:05 +04:00
LisoUseInAIKyrios
8ec857a175 fix(Messenger - Hide inbox ads): Support the latest app version 2025-07-25 10:46:10 +04:00
semantic-release-bot
f56c7868f5 chore: Release v5.32.0-dev.3 [skip ci]
# [5.32.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.2...v5.32.0-dev.3) (2025-07-24)

### Features

* **YouTube - External downloads:** Improve the selection of the external downloader package ([#5504](https://github.com/ReVanced/revanced-patches/issues/5504)) ([cfd7780](cfd77800d6))
2025-07-24 07:31:13 +00:00
MarcaD
cfd77800d6 feat(YouTube - External downloads): Improve the selection of the external downloader package (#5504)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2025-07-24 11:28:16 +04:00
semantic-release-bot
707deaef0b chore: Release v5.32.0-dev.2 [skip ci]
# [5.32.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.1...v5.32.0-dev.2) (2025-07-23)

### Bug Fixes

* **YouTube  - Hide layout components:** Fix "Hide ticket shelf" ([#5516](https://github.com/ReVanced/revanced-patches/issues/5516)) ([9ddb3ac](9ddb3ac39d))
2025-07-23 12:05:24 +00:00
ILoveOpenSourceApplications
9ddb3ac39d fix(YouTube - Hide layout components): Fix "Hide ticket shelf" (#5516) 2025-07-23 16:02:53 +04:00
github-actions[bot]
a7d3b7c287 chore: Sync translations (#5519) 2025-07-23 16:02:21 +04:00
LisoUseInAIKyrios
30bac0397e chore(YouTube): Fix string typo 2025-07-20 15:38:40 +04:00
semantic-release-bot
c5fc187a35 chore: Release v5.32.0-dev.1 [skip ci]
# [5.32.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.3-dev.1...v5.32.0-dev.1) (2025-07-16)

### Features

* **Prime Video:** Add `Playback speed` patch ([#5444](https://github.com/ReVanced/revanced-patches/issues/5444)) ([f46dbcd](f46dbcd084))
2025-07-16 19:30:50 +00:00
Sujitha Wijewantha
f46dbcd084 feat(Prime Video): Add Playback speed patch (#5444) 2025-07-16 23:27:55 +04:00
github-actions[bot]
2136573cb6 chore: Sync translations (#5484) 2025-07-16 23:27:18 +04:00
MarcaD
86ec08993c refactor(YouTube - Settings): Back button/gesture closes search instead of exiting (#5439) 2025-07-16 23:26:20 +04:00
semantic-release-bot
44da5a71c5 chore: Release v5.31.3-dev.1 [skip ci]
## [5.31.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.31.3-dev.1) (2025-07-16)

### Bug Fixes

* **YouTube - GmsCore support:** Fix search suggestions when logged out by using correct search provider ([#5483](https://github.com/ReVanced/revanced-patches/issues/5483)) ([e4e81b8](e4e81b89ea))
2025-07-16 19:16:27 +00:00
sm455
e4e81b89ea fix(YouTube - GmsCore support): Fix search suggestions when logged out by using correct search provider (#5483) 2025-07-16 23:13:22 +04:00
LisoUseInAIKyrios
165df659a1 chore(YouTube): Add string contexts 2025-07-16 12:02:47 +04:00
LisoUseInAIKyrios
bb87afe0f6 ci: Revert "Group all Dependabot update into one PR (#5336)"
This reverts commit e019f83232.
2025-07-16 11:54:40 +04:00
semantic-release-bot
ac5fb17937 chore: Release v5.31.2 [skip ci]
## [5.31.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.1...v5.31.2) (2025-07-14)

### Bug Fixes

* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([c972267](c972267cd8))
* **YouTube - Disable double tap actions:** Remove old incompatible targets ([294b2dc](294b2dce2e))
* **YouTube - Hide layout components:** Hide quick actions does not work ([#5423](https://github.com/ReVanced/revanced-patches/issues/5423)) ([cc6984e](cc6984e919))
* **YouTube - Hide layout components:** Show correct custom header logo if 'Hide YouTube Doodles' is enabled ([#5431](https://github.com/ReVanced/revanced-patches/issues/5431)) ([19bc5b6](19bc5b63c5))
* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([f994264](f994264d9c))
2025-07-14 12:02:46 +00:00
oSumAtrIX
e88356b3c5 chore: Merge branch dev to main (#5428) 2025-07-14 13:59:59 +02:00
github-actions[bot]
dead9c2d94 chore: Sync translations (#5449)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-07-14 13:59:35 +02:00
semantic-release-bot
ca640b2839 chore: Release v5.31.2-dev.5 [skip ci]
## [5.31.2-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.4...v5.31.2-dev.5) (2025-07-14)

### Bug Fixes

* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([c972267](c972267cd8))
2025-07-14 11:58:39 +00:00
oSumAtrIX
c972267cd8 fix(Spotify - Spoof client): Fix login failing by spoofing login request in addition (#5448) 2025-07-14 13:55:37 +02:00
ILoveOpenSourceApplications
d0d2c13d16 refactor(YouTube): Sort and standardize strings (#5442) 2025-07-14 15:01:10 +04:00
semantic-release-bot
e7b4ab53cf chore: Release v5.31.2-dev.4 [skip ci]
## [5.31.2-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.3...v5.31.2-dev.4) (2025-07-13)

### Bug Fixes

* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([f994264](f994264d9c))
2025-07-13 10:59:17 +00:00
MarcaD
f994264d9c fix(YouTube - Settings): Back button/gesture closes search instead of exiting (#5418) 2025-07-13 14:56:30 +04:00
github-actions[bot]
eb61c1f5d1 chore: Sync translations (#5437) 2025-07-13 14:55:36 +04:00
semantic-release-bot
e578347277 chore: Release v5.31.2-dev.3 [skip ci]
## [5.31.2-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.2...v5.31.2-dev.3) (2025-07-13)

### Bug Fixes

* **YouTube - Disable double tap actions:** Remove old incompatible targets ([294b2dc](294b2dce2e))
2025-07-13 06:18:39 +00:00
LisoUseInAIKyrios
294b2dce2e fix(YouTube - Disable double tap actions): Remove old incompatible targets 2025-07-13 10:15:16 +04:00
github-actions[bot]
aa37105ea3 chore: Sync translations (#5436) 2025-07-13 10:03:04 +04:00
semantic-release-bot
eb57a2697b chore: Release v5.31.2-dev.2 [skip ci]
## [5.31.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.1...v5.31.2-dev.2) (2025-07-12)

### Bug Fixes

* **YouTube - Hide layout components:** Show correct custom header logo if 'Hide YouTube Doodles' is enabled ([#5431](https://github.com/ReVanced/revanced-patches/issues/5431)) ([19bc5b6](19bc5b63c5))
2025-07-12 14:37:52 +00:00
LisoUseInAIKyrios
19bc5b63c5 fix(YouTube - Hide layout components): Show correct custom header logo if 'Hide YouTube Doodles' is enabled (#5431) 2025-07-12 18:34:29 +04:00
180 changed files with 5676 additions and 2868 deletions

View File

@@ -1,26 +1,22 @@
version: 2 version: 2
multi-ecosystem-groups:
dependency:
schedule:
interval: "weekly"
target-branch: dev
labels: [ ]
updates: updates:
- package-ecosystem: github-actions - package-ecosystem: github-actions
multi-ecosystem-group: "dependency" labels: []
directory: / directory: /
patterns: target-branch: dev
- "*" schedule:
interval: monthly
- package-ecosystem: npm - package-ecosystem: npm
multi-ecosystem-group: "dependency" labels: []
directory: / directory: /
patterns: target-branch: dev
- "*" schedule:
interval: monthly
- package-ecosystem: gradle - package-ecosystem: gradle
multi-ecosystem-group: "dependency" labels: []
directory: / directory: /
patterns: target-branch: dev
- "*" schedule:
interval: monthly

View File

@@ -1,3 +1,184 @@
# [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04)
### Bug Fixes
* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([295f0f2](https://github.com/ReVanced/revanced-patches/commit/295f0f216b5e8aa9d68457862e73e312b7342703))
# [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04)
### Bug Fixes
* **YouTube - Video quality:** Fix 144p default not always used ([2f7483a](https://github.com/ReVanced/revanced-patches/commit/2f7483a2d789c28a243b58bb7a252c0d590858ee))
# [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04)
### Bug Fixes
* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([7378ae3](https://github.com/ReVanced/revanced-patches/commit/7378ae3c5fc88f91bf5cd6db47c6cd170a8c5a4f))
# [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04)
### Bug Fixes
* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([9fe13ee](https://github.com/ReVanced/revanced-patches/commit/9fe13ee1af104c009efd19b826adef375e48e191))
# [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03)
### Bug Fixes
* **NFC Tools:** Remove broken patch that is no longer supported ([#5584](https://github.com/ReVanced/revanced-patches/issues/5584)) ([cd3a6be](https://github.com/ReVanced/revanced-patches/commit/cd3a6be75c6bd3cc33c0b17a044bd6147f27b5ce))
# [5.33.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.6...v5.33.0-dev.7) (2025-08-03)
### Features
* **YouTube:** Add player button to change video quality ([#5435](https://github.com/ReVanced/revanced-patches/issues/5435)) ([d5f51bf](https://github.com/ReVanced/revanced-patches/commit/d5f51bf400dd22626ff65d7563b6fde70d53fb25))
# [5.33.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.5...v5.33.0-dev.6) (2025-07-31)
### Bug Fixes
* **YouTube - Video quality:** Use 1080p enhanced bitrate for Premium users ([#5565](https://github.com/ReVanced/revanced-patches/issues/5565)) ([bd3ace0](https://github.com/ReVanced/revanced-patches/commit/bd3ace0bd04ccd0369adb49d63aa0cf986402346))
# [5.33.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.4...v5.33.0-dev.5) (2025-07-31)
### Bug Fixes
* **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([bf29d69](https://github.com/ReVanced/revanced-patches/commit/bf29d6909e389819bad878ad3b94bbc90d823cc9))
# [5.33.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.3...v5.33.0-dev.4) (2025-07-30)
### Performance Improvements
* **YouTube:** Filter identifier callback only on root component creation ([#5558](https://github.com/ReVanced/revanced-patches/issues/5558)) ([ccac46e](https://github.com/ReVanced/revanced-patches/commit/ccac46eebc2e14b094454e37ef4461d48a62c53f))
# [5.33.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.2...v5.33.0-dev.3) (2025-07-30)
### Bug Fixes
* **YouTube - Playback speed:** Use old speed menu for player button if enabled ([1e8f436](https://github.com/ReVanced/revanced-patches/commit/1e8f4368e117f4b278c24709231cb32546e46dc0))
# [5.33.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.1...v5.33.0-dev.2) (2025-07-29)
### Features
* **ORF ON:** Add `Remove root detection` patch ([#5551](https://github.com/ReVanced/revanced-patches/issues/5551)) ([6c6aa35](https://github.com/ReVanced/revanced-patches/commit/6c6aa35411a139dddc3a15dd757fbeded5d1a0a3))
# [5.33.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0-dev.1) (2025-07-28)
### Features
* **YouTube - Playback speed:** Add "Restore old playback speed menu" option ([#5552](https://github.com/ReVanced/revanced-patches/issues/5552)) ([b01f15b](https://github.com/ReVanced/revanced-patches/commit/b01f15b9acb0427aed99b0141ae271831b7936bf))
# [5.32.0](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.32.0) (2025-07-27)
### Bug Fixes
* **Messenger - Hide inbox ads:** Support the latest app version ([2959c02](https://github.com/ReVanced/revanced-patches/commit/2959c0214dfa703ee623ef1f89bded7f78c9d252))
* **YouTube - Hide layout components:** Fix "Hide ticket shelf" ([#5516](https://github.com/ReVanced/revanced-patches/issues/5516)) ([3b85c71](https://github.com/ReVanced/revanced-patches/commit/3b85c71433325fff49e01c77c7b9ff8ddd0a7068))
* **YouTube - GmsCore support:** Fix search suggestions when logged out by using correct search provider ([#5483](https://github.com/ReVanced/revanced-patches/issues/5483)) ([e86fdc8](https://github.com/ReVanced/revanced-patches/commit/e86fdc86b161a6077960b85149e83bacbac664e7))
### Features
* **Prime Video:** Add `Playback speed` patch ([#5444](https://github.com/ReVanced/revanced-patches/issues/5444)) ([22cf313](https://github.com/ReVanced/revanced-patches/commit/22cf313a7b99b69e17b9d488c514802043a5dc10))
* **YouTube - External downloads:** Improve the selection of the external downloader package ([#5504](https://github.com/ReVanced/revanced-patches/issues/5504)) ([5de9aa9](https://github.com/ReVanced/revanced-patches/commit/5de9aa9fad4f24186da045fb188f8718d6f63d7a))
* **YT Music:** Support latest versions ([#5524](https://github.com/ReVanced/revanced-patches/issues/5524)) ([551dcf0](https://github.com/ReVanced/revanced-patches/commit/551dcf01ca9c489a779196b49c8744727d79d6bc))
# [5.32.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.4...v5.32.0-dev.5) (2025-07-26)
### Features
* **YT Music:** Support latest versions ([#5524](https://github.com/ReVanced/revanced-patches/issues/5524)) ([551dcf0](https://github.com/ReVanced/revanced-patches/commit/551dcf01ca9c489a779196b49c8744727d79d6bc))
# [5.32.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.3...v5.32.0-dev.4) (2025-07-25)
### Bug Fixes
* **Messenger - Hide inbox ads:** Support the latest app version ([2959c02](https://github.com/ReVanced/revanced-patches/commit/2959c0214dfa703ee623ef1f89bded7f78c9d252))
# [5.32.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.2...v5.32.0-dev.3) (2025-07-24)
### Features
* **YouTube - External downloads:** Improve the selection of the external downloader package ([#5504](https://github.com/ReVanced/revanced-patches/issues/5504)) ([5de9aa9](https://github.com/ReVanced/revanced-patches/commit/5de9aa9fad4f24186da045fb188f8718d6f63d7a))
# [5.32.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.1...v5.32.0-dev.2) (2025-07-23)
### Bug Fixes
* **YouTube - Hide layout components:** Fix "Hide ticket shelf" ([#5516](https://github.com/ReVanced/revanced-patches/issues/5516)) ([3b85c71](https://github.com/ReVanced/revanced-patches/commit/3b85c71433325fff49e01c77c7b9ff8ddd0a7068))
# [5.32.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.3-dev.1...v5.32.0-dev.1) (2025-07-16)
### Features
* **Prime Video:** Add `Playback speed` patch ([#5444](https://github.com/ReVanced/revanced-patches/issues/5444)) ([22cf313](https://github.com/ReVanced/revanced-patches/commit/22cf313a7b99b69e17b9d488c514802043a5dc10))
## [5.31.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.31.3-dev.1) (2025-07-16)
### Bug Fixes
* **YouTube - GmsCore support:** Fix search suggestions when logged out by using correct search provider ([#5483](https://github.com/ReVanced/revanced-patches/issues/5483)) ([e86fdc8](https://github.com/ReVanced/revanced-patches/commit/e86fdc86b161a6077960b85149e83bacbac664e7))
## [5.31.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.1...v5.31.2) (2025-07-14)
### Bug Fixes
* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([4e59ddc](https://github.com/ReVanced/revanced-patches/commit/4e59ddc62388d09f71b89593fc8b76933d9facea))
* **YouTube - Disable double tap actions:** Remove old incompatible targets ([857053e](https://github.com/ReVanced/revanced-patches/commit/857053e29b72ded10a84b0ac693fa107705342d9))
* **YouTube - Hide layout components:** Hide quick actions does not work ([#5423](https://github.com/ReVanced/revanced-patches/issues/5423)) ([9c66729](https://github.com/ReVanced/revanced-patches/commit/9c6672946d44001e106bdac9041e2d79ef3f6ab2))
* **YouTube - Hide layout components:** Show correct custom header logo if 'Hide YouTube Doodles' is enabled ([#5431](https://github.com/ReVanced/revanced-patches/issues/5431)) ([20cc141](https://github.com/ReVanced/revanced-patches/commit/20cc141e61f75de1a1749247c4f4aed167dee8ea))
* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([134b278](https://github.com/ReVanced/revanced-patches/commit/134b278baa7b90d2c4b06200cabacabf55ebc055))
## [5.31.2-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.4...v5.31.2-dev.5) (2025-07-14)
### Bug Fixes
* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([4e59ddc](https://github.com/ReVanced/revanced-patches/commit/4e59ddc62388d09f71b89593fc8b76933d9facea))
## [5.31.2-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.3...v5.31.2-dev.4) (2025-07-13)
### Bug Fixes
* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([134b278](https://github.com/ReVanced/revanced-patches/commit/134b278baa7b90d2c4b06200cabacabf55ebc055))
## [5.31.2-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.2...v5.31.2-dev.3) (2025-07-13)
### Bug Fixes
* **YouTube - Disable double tap actions:** Remove old incompatible targets ([857053e](https://github.com/ReVanced/revanced-patches/commit/857053e29b72ded10a84b0ac693fa107705342d9))
## [5.31.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.1...v5.31.2-dev.2) (2025-07-12)
### Bug Fixes
* **YouTube - Hide layout components:** Show correct custom header logo if 'Hide YouTube Doodles' is enabled ([#5431](https://github.com/ReVanced/revanced-patches/issues/5431)) ([20cc141](https://github.com/ReVanced/revanced-patches/commit/20cc141e61f75de1a1749247c4f4aed167dee8ea))
## [5.31.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.1...v5.31.2-dev.1) (2025-07-12) ## [5.31.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.1...v5.31.2-dev.1) (2025-07-12)

View File

@@ -0,0 +1,207 @@
package app.revanced.extension.primevideo.videoplayer;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.RectF;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import java.util.Arrays;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import com.amazon.video.sdk.player.Player;
public class PlaybackSpeedPatch {
private static Player player;
private static final float[] SPEED_VALUES = {0.5f, 0.7f, 0.8f, 0.9f, 0.95f, 1.0f, 1.05f, 1.1f, 1.2f, 1.3f, 1.5f, 2.0f};
private static final String SPEED_BUTTON_TAG = "speed_overlay";
public static void setPlayer(Player playerInstance) {
player = playerInstance;
if (player != null) {
// Reset playback rate when switching between episodes to ensure correct display.
player.setPlaybackRate(1.0f);
}
}
public static void initializeSpeedOverlay(View userControlsView) {
try {
LinearLayout buttonContainer = Utils.getChildViewByResourceName(userControlsView, "ButtonContainerPlayerTop");
// If the speed overlay exists we should return early.
if (Utils.getChildView(buttonContainer, false, child ->
child instanceof ImageView && SPEED_BUTTON_TAG.equals(child.getTag())) != null) {
return;
}
ImageView speedButton = createSpeedButton(userControlsView.getContext());
speedButton.setOnClickListener(v -> changePlaybackSpeed(speedButton));
buttonContainer.addView(speedButton, 0);
} catch (IllegalArgumentException e) {
Logger.printException(() -> "initializeSpeedOverlay, no button container found", e);
} catch (Exception e) {
Logger.printException(() -> "initializeSpeedOverlay failure", e);
}
}
private static ImageView createSpeedButton(Context context) {
ImageView speedButton = new ImageView(context);
speedButton.setContentDescription("Playback Speed");
speedButton.setTag(SPEED_BUTTON_TAG);
speedButton.setClickable(true);
speedButton.setFocusable(true);
speedButton.setScaleType(ImageView.ScaleType.CENTER);
SpeedIconDrawable speedIcon = new SpeedIconDrawable();
speedButton.setImageDrawable(speedIcon);
int buttonSize = Utils.dipToPixels(48);
speedButton.setMinimumWidth(buttonSize);
speedButton.setMinimumHeight(buttonSize);
return speedButton;
}
private static String[] getSpeedOptions() {
String[] options = new String[SPEED_VALUES.length];
for (int i = 0; i < SPEED_VALUES.length; i++) {
options[i] = SPEED_VALUES[i] + "x";
}
return options;
}
private static void changePlaybackSpeed(ImageView imageView) {
if (player == null) {
Logger.printException(() -> "Player not available");
return;
}
try {
player.pause();
AlertDialog dialog = createSpeedPlaybackDialog(imageView);
dialog.setOnDismissListener(dialogInterface -> player.play());
dialog.show();
} catch (Exception e) {
Logger.printException(() -> "changePlaybackSpeed", e);
}
}
private static AlertDialog createSpeedPlaybackDialog(ImageView imageView) {
Context context = imageView.getContext();
int currentSelection = getCurrentSpeedSelection();
return new AlertDialog.Builder(context)
.setTitle("Select Playback Speed")
.setSingleChoiceItems(getSpeedOptions(), currentSelection,
PlaybackSpeedPatch::handleSpeedSelection)
.create();
}
private static int getCurrentSpeedSelection() {
try {
float currentRate = player.getPlaybackRate();
int index = Arrays.binarySearch(SPEED_VALUES, currentRate);
return Math.max(index, 0); // Use slowest speed if not found.
} catch (Exception e) {
Logger.printException(() -> "getCurrentSpeedSelection error getting current playback speed", e);
return 0;
}
}
private static void handleSpeedSelection(android.content.DialogInterface dialog, int selectedIndex) {
try {
float selectedSpeed = SPEED_VALUES[selectedIndex];
player.setPlaybackRate(selectedSpeed);
player.play();
} catch (Exception e) {
Logger.printException(() -> "handleSpeedSelection error setting playback speed", e);
} finally {
dialog.dismiss();
}
}
}
class SpeedIconDrawable extends Drawable {
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
@Override
public void draw(Canvas canvas) {
int w = getBounds().width();
int h = getBounds().height();
float centerX = w / 2f;
// Position gauge in lower portion.
float centerY = h * 0.7f;
float radius = Math.min(w, h) / 2f * 0.8f;
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(radius * 0.1f);
// Draw semicircle.
RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
canvas.drawArc(oval, 180, 180, false, paint);
// Draw three tick marks.
paint.setStrokeWidth(radius * 0.06f);
for (int i = 0; i < 3; i++) {
float angle = 180 + (i * 45); // 180°, 225°, 270°.
float angleRad = (float) Math.toRadians(angle);
float startX = centerX + (radius * 0.8f) * (float) Math.cos(angleRad);
float startY = centerY + (radius * 0.8f) * (float) Math.sin(angleRad);
float endX = centerX + radius * (float) Math.cos(angleRad);
float endY = centerY + radius * (float) Math.sin(angleRad);
canvas.drawLine(startX, startY, endX, endY, paint);
}
// Draw needle.
paint.setStrokeWidth(radius * 0.08f);
float needleAngle = 200; // Slightly right of center.
float needleAngleRad = (float) Math.toRadians(needleAngle);
float needleEndX = centerX + (radius * 0.6f) * (float) Math.cos(needleAngleRad);
float needleEndY = centerY + (radius * 0.6f) * (float) Math.sin(needleAngleRad);
canvas.drawLine(centerX, centerY, needleEndX, needleEndY, paint);
// Center dot.
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, radius * 0.06f, paint);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public int getIntrinsicWidth() {
return Utils.dipToPixels(32);
}
@Override
public int getIntrinsicHeight() {
return Utils.dipToPixels(32);
}
}

View File

@@ -4,4 +4,10 @@ public interface VideoPlayer {
long getCurrentPosition(); long getCurrentPosition();
void seekTo(long positionMs); void seekTo(long positionMs);
void pause();
void play();
boolean isPlaying();
} }

View File

@@ -0,0 +1,11 @@
package com.amazon.video.sdk.player;
public interface Player {
float getPlaybackRate();
void setPlaybackRate(float rate);
void play();
void pause();
}

View File

@@ -1438,6 +1438,38 @@ public class Utils {
); );
} }
/**
* Converts a percentage of the screen height to actual device pixels.
*
* @param percentage The percentage of the screen height (e.g., 30 for 30%).
* @return The device pixel value corresponding to the percentage of screen height.
*/
public static int percentageHeightToPixels(int percentage) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int) (metrics.heightPixels * (percentage / 100.0f));
}
/**
* Converts a percentage of the screen width to actual device pixels.
*
* @param percentage The percentage of the screen width (e.g., 30 for 30%).
* @return The device pixel value corresponding to the percentage of screen width.
*/
public static int percentageWidthToPixels(int percentage) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int) (metrics.widthPixels * (percentage / 100.0f));
}
/**
* Uses {@link #adjustColorBrightness(int, float)} depending if light or dark mode is active.
*/
@ColorInt
public static int adjustColorBrightness(@ColorInt int baseColor, float lightThemeFactor, float darkThemeFactor) {
return isDarkModeEnabled()
? adjustColorBrightness(baseColor, darkThemeFactor)
: adjustColorBrightness(baseColor, lightThemeFactor);
}
/** /**
* Adjusts the brightness of a color by lightening or darkening it based on the given factor. * Adjusts the brightness of a color by lightening or darkening it based on the given factor.
* <p> * <p>

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.shared.settings.preference; package app.revanced.extension.shared.settings.preference;
import static app.revanced.extension.shared.Utils.dipToPixels;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
@@ -26,7 +24,7 @@ public class CustomDialogListPreference extends ListPreference {
/** /**
* Custom ArrayAdapter to handle checkmark visibility. * Custom ArrayAdapter to handle checkmark visibility.
*/ */
private static class ListPreferenceArrayAdapter extends ArrayAdapter<CharSequence> { public static class ListPreferenceArrayAdapter extends ArrayAdapter<CharSequence> {
private static class SubViewDataContainer { private static class SubViewDataContainer {
ImageView checkIcon; ImageView checkIcon;
View placeholder; View placeholder;

View File

@@ -1,28 +1,15 @@
package app.revanced.extension.shared.settings.preference; package app.revanced.extension.shared.settings.preference;
import static app.revanced.extension.shared.StringRef.str; import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.Paint.Style;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Pair; import android.util.Pair;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;

View File

@@ -1,9 +1,12 @@
package app.revanced.extension.youtube.patches; package app.revanced.extension.youtube.patches;
import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.Objects; import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@@ -11,18 +14,21 @@ import app.revanced.extension.youtube.settings.Settings;
public class ChangeHeaderPatch { public class ChangeHeaderPatch {
public enum HeaderLogo { public enum HeaderLogo {
DEFAULT(null), DEFAULT(null, null),
REGULAR("ytWordmarkHeader"), REGULAR("ytWordmarkHeader", "yt_ringo2_wordmark_header"),
PREMIUM("ytPremiumWordmarkHeader"), PREMIUM("ytPremiumWordmarkHeader", "yt_ringo2_premium_wordmark_header"),
REVANCED("revanced_header_logo"), REVANCED("revanced_header_logo", "revanced_header_logo"),
REVANCED_MINIMAL("revanced_header_logo_minimal"), REVANCED_MINIMAL("revanced_header_logo_minimal", "revanced_header_logo_minimal"),
CUSTOM("custom_header"); CUSTOM("custom_header", "custom_header");
@Nullable @Nullable
private final String resourceName; private final String attributeName;
@Nullable
private final String drawableName;
HeaderLogo(@Nullable String resourceName) { HeaderLogo(@Nullable String attributeName, @Nullable String drawableName) {
this.resourceName = resourceName; this.attributeName = attributeName;
this.drawableName = drawableName;
} }
/** /**
@@ -30,24 +36,66 @@ public class ChangeHeaderPatch {
*/ */
@Nullable @Nullable
private Integer getAttributeId() { private Integer getAttributeId() {
if (resourceName == null) { if (attributeName == null) {
return null; return null;
} }
final int identifier = Utils.getResourceIdentifier(resourceName, "attr"); final int identifier = Utils.getResourceIdentifier(attributeName, "attr");
// Identifier is zero if custom header setting was included in imported settings if (identifier == 0) {
// and a custom image was not included during patching. // Identifier is zero if custom header setting was included in imported settings
return identifier == 0 ? null : identifier; // and a custom image was not included during patching.
Logger.printDebug(() -> "Could not find attribute: " + drawableName);
Settings.HEADER_LOGO.resetToDefault();
return null;
}
return identifier;
}
@Nullable
public Drawable getDrawable() {
if (drawableName == null) {
return null;
}
String drawableFullName = drawableName + (Utils.isDarkModeEnabled()
? "_dark"
: "_light");
final int identifier = Utils.getResourceIdentifier(drawableFullName, "drawable");
if (identifier == 0) {
Logger.printDebug(() -> "Could not find drawable: " + drawableFullName);
Settings.HEADER_LOGO.resetToDefault();
return null;
}
return Utils.getContext().getDrawable(identifier);
} }
} }
@Nullable
private static final Integer headerLogoResource = Settings.HEADER_LOGO.get().getAttributeId();
/** /**
* Injection point. * Injection point.
*/ */
public static int getHeaderAttributeId(int original) { public static int getHeaderAttributeId(int original) {
return Objects.requireNonNullElse(headerLogoResource, original); return Objects.requireNonNullElse(Settings.HEADER_LOGO.get().getAttributeId(), original);
}
public static Drawable getDrawable(Drawable original) {
Drawable logo = Settings.HEADER_LOGO.get().getDrawable();
if (logo != null) {
return logo;
}
// TODO: If 'Hide Doodles' is enabled, this will force the regular logo regardless
// what account the user has. This can be improved the next time a Doodle is
// active and the attribute id is passed to this method so the correct
// regular/premium logo is returned.
logo = HeaderLogo.REGULAR.getDrawable();
if (logo != null) {
return logo;
}
// Should never happen.
Logger.printException(() -> "Could not find regular header logo resource");
return original;
} }
} }

View File

@@ -3,7 +3,7 @@ package app.revanced.extension.youtube.patches;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class DisableChapterSkipDoubleTapPatch { public final class DisableDoubleTapActionsPatch {
/** /**
* Injection point. * Injection point.

View File

@@ -1,17 +1,15 @@
package app.revanced.extension.youtube.patches; package app.revanced.extension.youtube.patches;
import static app.revanced.extension.youtube.settings.preference.ExternalDownloaderPreference.showDialogIfAppIsNotInstalled;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Objects; import java.util.Objects;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.StringRef;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@@ -36,7 +34,7 @@ public final class DownloadsPatch {
* *
* Appears to always be called from the main thread. * Appears to always be called from the main thread.
*/ */
public static boolean inAppDownloadButtonOnClick(@NonNull String videoId) { public static boolean inAppDownloadButtonOnClick(String videoId) {
try { try {
if (!Settings.EXTERNAL_DOWNLOADER_ACTION_BUTTON.get()) { if (!Settings.EXTERNAL_DOWNLOADER_ACTION_BUTTON.get()) {
return false; return false;
@@ -48,6 +46,9 @@ public final class DownloadsPatch {
boolean isActivityContext = true; boolean isActivityContext = true;
if (context == null) { if (context == null) {
// Utils context is the application context, and not an activity context. // Utils context is the application context, and not an activity context.
//
// Edit: This check may no longer be needed since YT can now
// only be launched from the main Activity (embedded usage in other apps no longer works).
context = Utils.getContext(); context = Utils.getContext();
isActivityContext = false; isActivityContext = false;
} }
@@ -64,8 +65,7 @@ public final class DownloadsPatch {
* @param isActivityContext If the context parameter is for an Activity. If this is false, then * @param isActivityContext If the context parameter is for an Activity. If this is false, then
* the downloader is opened as a new task (which forces YT to minimize). * the downloader is opened as a new task (which forces YT to minimize).
*/ */
public static void launchExternalDownloader(@NonNull String videoId, public static void launchExternalDownloader(String videoId, Context context, boolean isActivityContext) {
@NonNull Context context, boolean isActivityContext) {
try { try {
Objects.requireNonNull(videoId); Objects.requireNonNull(videoId);
Logger.printDebug(() -> "Launching external downloader with context: " + context); Logger.printDebug(() -> "Launching external downloader with context: " + context);
@@ -73,16 +73,8 @@ public final class DownloadsPatch {
// Trim string to avoid any accidental whitespace. // Trim string to avoid any accidental whitespace.
var downloaderPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get().trim(); var downloaderPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get().trim();
boolean packageEnabled = false; // If the package is not installed, show a dialog.
try { if (showDialogIfAppIsNotInstalled(context, downloaderPackageName)) {
packageEnabled = context.getPackageManager().getApplicationInfo(downloaderPackageName, 0).enabled;
} catch (PackageManager.NameNotFoundException error) {
Logger.printDebug(() -> "External downloader could not be found: " + error);
}
// If the package is not installed, show the toast
if (!packageEnabled) {
Utils.showToastLong(StringRef.str("revanced_external_downloader_not_installed_warning", downloaderPackageName));
return; return;
} }

View File

@@ -24,6 +24,16 @@ public class ForceOriginalAudioPatch {
} }
} }
/**
* Injection point.
*/
public static boolean ignoreDefaultAudioStream(boolean original) {
if (Settings.FORCE_ORIGINAL_AUDIO.get()) {
return false;
}
return original;
}
/** /**
* Injection point. * Injection point.
*/ */
@@ -50,7 +60,6 @@ public class ForceOriginalAudioPatch {
return isOriginal; return isOriginal;
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "isDefaultAudioStream failure", ex); Logger.printException(() -> "isDefaultAudioStream failure", ex);
return isDefault; return isDefault;
} }
} }

View File

@@ -16,7 +16,7 @@ import java.util.Objects;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilterPatch; import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilter;
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
@@ -55,7 +55,7 @@ public class ReturnYouTubeDislikePatch {
private static volatile ReturnYouTubeDislike lastLithoShortsVideoData; private static volatile ReturnYouTubeDislike lastLithoShortsVideoData;
/** /**
* Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilterPatch} * Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilter}
* detects the video ids, but the current Short can arbitrarily reload the same span, * detects the video ids, but the current Short can arbitrarily reload the same span,
* then use the {@link #lastLithoShortsVideoData} if this value is greater than zero. * then use the {@link #lastLithoShortsVideoData} if this value is greater than zero.
*/ */

View File

@@ -6,8 +6,6 @@ import android.app.Instrumentation;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import androidx.annotation.Nullable;
import java.util.List; import java.util.List;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
@@ -155,10 +153,10 @@ public final class AdsFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == playerShoppingShelf) { if (matchedGroup == playerShoppingShelf) {
return contentIndex == 0 && playerShoppingShelfBuffer.check(protobufBufferArray).isFiltered(); return contentIndex == 0 && playerShoppingShelfBuffer.check(buffer).isFiltered();
} }
if (exceptions.matches(path)) { if (exceptions.matches(path)) {

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.youtube.patches.components; package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import app.revanced.extension.youtube.patches.playback.quality.AdvancedVideoQualityMenuPatch; import app.revanced.extension.youtube.patches.playback.quality.AdvancedVideoQualityMenuPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@@ -21,7 +19,7 @@ public final class AdvancedVideoQualityMenuFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
isVideoQualityMenuVisible = true; isVideoQualityMenuVisible = true;

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.youtube.patches.components; package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@@ -100,7 +98,7 @@ final class ButtonsFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == likeSubscribeGlow) { if (matchedGroup == likeSubscribeGlow) {
return (path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX)) return (path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX))
@@ -117,7 +115,7 @@ final class ButtonsFilter extends Filter {
// Make sure the current path is the right one // Make sure the current path is the right one
// to avoid false positives. // to avoid false positives.
return path.startsWith(VIDEO_ACTION_BAR_PATH) return path.startsWith(VIDEO_ACTION_BAR_PATH)
&& bufferButtonsGroupList.check(protobufBufferArray).isFiltered(); && bufferButtonsGroupList.check(buffer).isFiltered();
} }
return true; return true;

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.youtube.patches.components; package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
@@ -87,12 +85,12 @@ final class CommentsFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == chipBar) { if (matchedGroup == chipBar) {
// Playlist sort button uses same components and must only filter if the player is opened. // Playlist sort button uses same components and must only filter if the player is opened.
return PlayerType.getCurrent().isMaximizedOrFullscreen() return PlayerType.getCurrent().isMaximizedOrFullscreen()
&& aiCommentsSummary.check(protobufBufferArray).isFiltered(); && aiCommentsSummary.check(buffer).isFiltered();
} }
return true; return true;

View File

@@ -3,7 +3,6 @@ package app.revanced.extension.youtube.patches.components;
import static app.revanced.extension.shared.StringRef.str; import static app.revanced.extension.shared.StringRef.str;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@@ -146,7 +145,7 @@ final class CustomFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
// All callbacks are custom filter groups. // All callbacks are custom filter groups.
CustomFilterGroup custom = (CustomFilterGroup) matchedGroup; CustomFilterGroup custom = (CustomFilterGroup) matchedGroup;
@@ -158,6 +157,6 @@ final class CustomFilter extends Filter {
return true; // No buffer filter, only path filtering. return true; // No buffer filter, only path filtering.
} }
return custom.bufferSearch.matches(protobufBufferArray); return custom.bufferSearch.matches(buffer);
} }
} }

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.youtube.patches.components; package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import app.revanced.extension.youtube.StringTrieSearch; import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
@@ -105,7 +103,7 @@ final class DescriptionComponentsFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == aiGeneratedVideoSummarySection) { if (matchedGroup == aiGeneratedVideoSummarySection) {
@@ -116,11 +114,11 @@ final class DescriptionComponentsFilter extends Filter {
if (exceptions.matches(path)) return false; if (exceptions.matches(path)) return false;
if (matchedGroup == macroMarkersCarousel) { if (matchedGroup == macroMarkersCarousel) {
return contentIndex == 0 && macroMarkersCarouselGroupList.check(protobufBufferArray).isFiltered(); return contentIndex == 0 && macroMarkersCarouselGroupList.check(buffer).isFiltered();
} }
if (matchedGroup == horizontalShelf) { if (matchedGroup == horizontalShelf) {
return cellVideoAttribute.check(protobufBufferArray).isFiltered(); return cellVideoAttribute.check(buffer).isFiltered();
} }
return true; return true;

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.youtube.patches.components; package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -42,6 +40,7 @@ abstract class Filter {
/** /**
* Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)} * Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)}
* if any of the groups are found. * if any of the groups are found.
* <p>
*/ */
protected final void addIdentifierCallbacks(StringFilterGroup... groups) { protected final void addIdentifierCallbacks(StringFilterGroup... groups) {
identifierCallbacks.addAll(Arrays.asList(groups)); identifierCallbacks.addAll(Arrays.asList(groups));
@@ -68,7 +67,7 @@ abstract class Filter {
* @param contentIndex Matched index of the identifier or path. * @param contentIndex Matched index of the identifier or path.
* @return True if the litho component should be filtered out. * @return True if the litho component should be filtered out.
*/ */
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
return true; return true;
} }

View File

@@ -3,9 +3,9 @@ package app.revanced.extension.youtube.patches.components;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class HideInfoCardsFilterPatch extends Filter { public final class HideInfoCardsFilter extends Filter {
public HideInfoCardsFilterPatch() { public HideInfoCardsFilter() {
addIdentifierCallbacks( addIdentifierCallbacks(
new StringFilterGroup( new StringFilterGroup(
Settings.HIDE_INFO_CARDS, Settings.HIDE_INFO_CARDS,

View File

@@ -554,7 +554,7 @@ final class KeywordContentFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (contentIndex != 0 && matchedGroup == startsWithFilter) { if (contentIndex != 0 && matchedGroup == startsWithFilter) {
return false; return false;
@@ -574,7 +574,7 @@ final class KeywordContentFilter extends Filter {
} }
MutableReference<String> matchRef = new MutableReference<>(); MutableReference<String> matchRef = new MutableReference<>();
if (bufferSearch.matches(protobufBufferArray, matchRef)) { if (bufferSearch.matches(buffer, matchRef)) {
updateStats(true, matchRef.value); updateStats(true, matchRef.value);
return true; return true;
} }

View File

@@ -4,12 +4,14 @@ import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButt
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.StringTrieSearch; import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.youtube.patches.ChangeHeaderPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.NavigationBar; import app.revanced.extension.youtube.shared.NavigationBar;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
@@ -30,7 +32,7 @@ public final class LayoutComponentsFilter extends Filter {
); );
private final StringTrieSearch exceptions = new StringTrieSearch(); private final StringTrieSearch exceptions = new StringTrieSearch();
private final StringFilterGroup inFeedSurvey; private final StringFilterGroup surveys;
private final StringFilterGroup notifyMe; private final StringFilterGroup notifyMe;
private final StringFilterGroup singleItemInformationPanel; private final StringFilterGroup singleItemInformationPanel;
private final StringFilterGroup expandableMetadata; private final StringFilterGroup expandableMetadata;
@@ -108,8 +110,8 @@ public final class LayoutComponentsFilter extends Filter {
"chip_bar" "chip_bar"
); );
inFeedSurvey = new StringFilterGroup( surveys = new StringFilterGroup(
Settings.HIDE_FEED_SURVEY, Settings.HIDE_SURVEYS,
"in_feed_survey", "in_feed_survey",
"slimline_survey", "slimline_survey",
"feed_nudge" "feed_nudge"
@@ -264,7 +266,7 @@ public final class LayoutComponentsFilter extends Filter {
ticketShelf = new ByteArrayFilterGroup( ticketShelf = new ByteArrayFilterGroup(
Settings.HIDE_TICKET_SHELF, Settings.HIDE_TICKET_SHELF,
"ticket.eml" "ticket_item.eml"
); );
addPathCallbacks( addPathCallbacks(
@@ -284,7 +286,6 @@ public final class LayoutComponentsFilter extends Filter {
forYouShelf, forYouShelf,
horizontalShelves, horizontalShelves,
imageShelf, imageShelf,
inFeedSurvey,
infoPanel, infoPanel,
latestPosts, latestPosts,
medicalPanel, medicalPanel,
@@ -296,13 +297,14 @@ public final class LayoutComponentsFilter extends Filter {
singleItemInformationPanel, singleItemInformationPanel,
subscribersCommunityGuidelines, subscribersCommunityGuidelines,
subscriptionsChipBar, subscriptionsChipBar,
surveys,
timedReactions, timedReactions,
videoRecommendationLabels videoRecommendationLabels
); );
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
// This identifier is used not only in players but also in search results: // This identifier is used not only in players but also in search results:
// https://github.com/ReVanced/revanced-patches/issues/3245 // https://github.com/ReVanced/revanced-patches/issues/3245
@@ -315,12 +317,12 @@ public final class LayoutComponentsFilter extends Filter {
// The groups are excluded from the filter due to the exceptions list below. // The groups are excluded from the filter due to the exceptions list below.
// Filter them separately here. // Filter them separately here.
if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata) { if (matchedGroup == notifyMe || matchedGroup == surveys || matchedGroup == expandableMetadata) {
return true; return true;
} }
if (matchedGroup == channelProfile) { if (matchedGroup == channelProfile) {
return channelProfileBuffer.check(protobufBufferArray).isFiltered(); return channelProfileBuffer.check(buffer).isFiltered();
} }
if (exceptions.matches(path)) return false; // Exceptions are not filtered. if (exceptions.matches(path)) return false; // Exceptions are not filtered.
@@ -329,11 +331,11 @@ public final class LayoutComponentsFilter extends Filter {
return compactChannelBarInnerButton.check(path).isFiltered() return compactChannelBarInnerButton.check(path).isFiltered()
// The filter may be broad, but in the context of a compactChannelBarInnerButton, // The filter may be broad, but in the context of a compactChannelBarInnerButton,
// it's safe to assume that the button is the only thing that should be hidden. // it's safe to assume that the button is the only thing that should be hidden.
&& joinMembershipButton.check(protobufBufferArray).isFiltered(); && joinMembershipButton.check(buffer).isFiltered();
} }
if (matchedGroup == horizontalShelves) { if (matchedGroup == horizontalShelves) {
return contentIndex == 0 && (hideShelves() || ticketShelf.check(protobufBufferArray).isFiltered()); return contentIndex == 0 && (hideShelves() || ticketShelf.check(buffer).isFiltered());
} }
if (matchedGroup == chipBar) { if (matchedGroup == chipBar) {
@@ -437,13 +439,11 @@ public final class LayoutComponentsFilter extends Filter {
/** /**
* Injection point. * Injection point.
*/ */
@Nullable public static void setDoodleDrawable(ImageView imageView, Drawable original) {
public static Drawable hideYoodles(Drawable animatedYoodle) { Drawable replacement = HIDE_DOODLES_ENABLED
if (HIDE_DOODLES_ENABLED) { ? ChangeHeaderPatch.getDrawable(original)
return null; : original;
} imageView.setImageDrawable(replacement);
return animatedYoodle;
} }
private static final boolean HIDE_SHOW_MORE_BUTTON_ENABLED = Settings.HIDE_SHOW_MORE_BUTTON.get(); private static final boolean HIDE_SHOW_MORE_BUTTON_ENABLED = Settings.HIDE_SHOW_MORE_BUTTON.get();

View File

@@ -17,29 +17,28 @@ public final class LithoFilterPatch {
* Simple wrapper to pass the litho parameters through the prefix search. * Simple wrapper to pass the litho parameters through the prefix search.
*/ */
private static final class LithoFilterParameters { private static final class LithoFilterParameters {
@Nullable
final String identifier; final String identifier;
final String path; final String path;
final byte[] protoBuffer; final byte[] buffer;
LithoFilterParameters(@Nullable String lithoIdentifier, String lithoPath, byte[] protoBuffer) { LithoFilterParameters(String lithoIdentifier, String lithoPath, byte[] buffer) {
this.identifier = lithoIdentifier; this.identifier = lithoIdentifier;
this.path = lithoPath; this.path = lithoPath;
this.protoBuffer = protoBuffer; this.buffer = buffer;
} }
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {
// Estimate the percentage of the buffer that are Strings. // Estimate the percentage of the buffer that are Strings.
StringBuilder builder = new StringBuilder(Math.max(100, protoBuffer.length / 2)); StringBuilder builder = new StringBuilder(Math.max(100, buffer.length / 2));
builder.append( "ID: "); builder.append( "ID: ");
builder.append(identifier); builder.append(identifier);
builder.append(" Path: "); builder.append(" Path: ");
builder.append(path); builder.append(path);
if (Settings.DEBUG_PROTOBUFFER.get()) { if (Settings.DEBUG_PROTOBUFFER.get()) {
builder.append(" BufferStrings: "); builder.append(" BufferStrings: ");
findAsciiStrings(builder, protoBuffer); findAsciiStrings(builder, buffer);
} }
return builder.toString(); return builder.toString();
@@ -128,21 +127,21 @@ public final class LithoFilterPatch {
private static void filterUsingCallbacks(StringTrieSearch pathSearchTree, private static void filterUsingCallbacks(StringTrieSearch pathSearchTree,
Filter filter, List<StringFilterGroup> groups, Filter filter, List<StringFilterGroup> groups,
Filter.FilterContentType type) { Filter.FilterContentType type) {
String filterSimpleName = filter.getClass().getSimpleName();
for (StringFilterGroup group : groups) { for (StringFilterGroup group : groups) {
if (!group.includeInSearch()) { if (!group.includeInSearch()) {
continue; continue;
} }
for (String pattern : group.filters) { for (String pattern : group.filters) {
String filterSimpleName = filter.getClass().getSimpleName();
pathSearchTree.addPattern(pattern, (textSearched, matchedStartIndex, pathSearchTree.addPattern(pattern, (textSearched, matchedStartIndex,
matchedLength, callbackParameter) -> { matchedLength, callbackParameter) -> {
if (!group.isEnabled()) return false; if (!group.isEnabled()) return false;
LithoFilterParameters parameters = (LithoFilterParameters) callbackParameter; LithoFilterParameters parameters = (LithoFilterParameters) callbackParameter;
final boolean isFiltered = filter.isFiltered(parameters.identifier, final boolean isFiltered = filter.isFiltered(parameters.identifier,
parameters.path, parameters.protoBuffer, group, type, matchedStartIndex); parameters.path, parameters.buffer, group, type, matchedStartIndex);
if (isFiltered && BaseSettings.DEBUG.get()) { if (isFiltered && BaseSettings.DEBUG.get()) {
if (type == Filter.FilterContentType.IDENTIFIER) { if (type == Filter.FilterContentType.IDENTIFIER) {
@@ -163,6 +162,7 @@ public final class LithoFilterPatch {
/** /**
* Injection point. Called off the main thread. * Injection point. Called off the main thread.
* Targets 20.22+
*/ */
public static void setProtoBuffer(byte[] buffer) { public static void setProtoBuffer(byte[] buffer) {
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes. // Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
@@ -193,9 +193,9 @@ public final class LithoFilterPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static boolean shouldFilter(@Nullable String lithoIdentifier, StringBuilder pathBuilder) { public static boolean isFiltered(String lithoIdentifier, StringBuilder pathBuilder) {
try { try {
if (pathBuilder.length() == 0) { if (lithoIdentifier.isEmpty() && pathBuilder.length() == 0) {
return false; return false;
} }
@@ -210,7 +210,7 @@ public final class LithoFilterPatch {
lithoIdentifier, pathBuilder.toString(), buffer); lithoIdentifier, pathBuilder.toString(), buffer);
Logger.printDebug(() -> "Searching " + parameter); Logger.printDebug(() -> "Searching " + parameter);
if (parameter.identifier != null && identifierSearchTree.matches(parameter.identifier, parameter)) { if (identifierSearchTree.matches(parameter.identifier, parameter)) {
return true; return true;
} }
@@ -218,7 +218,7 @@ public final class LithoFilterPatch {
return true; return true;
} }
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Litho filter failure", ex); Logger.printException(() -> "isFiltered failure", ex);
} }
return false; return false;

View File

@@ -0,0 +1,49 @@
package app.revanced.extension.youtube.patches.components;
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
import app.revanced.extension.youtube.settings.Settings;
/**
* Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}.
*/
public final class PlaybackSpeedMenuFilter extends Filter {
/**
* Old litho based speed selection menu.
*/
public static volatile boolean isOldPlaybackSpeedMenuVisible;
/**
* 0.05x speed selection menu.
*/
public static volatile boolean isPlaybackRateSelectorMenuVisible;
private final StringFilterGroup oldPlaybackMenuGroup;
public PlaybackSpeedMenuFilter() {
// 0.05x litho speed menu.
var playbackRateSelectorGroup = new StringFilterGroup(
Settings.CUSTOM_SPEED_MENU,
"playback_rate_selector_menu_sheet.eml-js"
);
// Old litho based speed menu.
oldPlaybackMenuGroup = new StringFilterGroup(
Settings.CUSTOM_SPEED_MENU,
"playback_speed_sheet_content.eml-js");
addPathCallbacks(playbackRateSelectorGroup, oldPlaybackMenuGroup);
}
@Override
boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == oldPlaybackMenuGroup) {
isOldPlaybackSpeedMenuVisible = true;
} else {
isPlaybackRateSelectorMenuVisible = true;
}
return false;
}
}

View File

@@ -1,35 +0,0 @@
package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
import app.revanced.extension.youtube.settings.Settings;
/**
* Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}.
*/
public final class PlaybackSpeedMenuFilterPatch extends Filter {
/**
* 0.05x speed selection menu.
*/
public static volatile boolean isPlaybackRateSelectorMenuVisible;
public PlaybackSpeedMenuFilterPatch() {
// 0.05x litho speed menu.
var playbackRateSelectorGroup = new StringFilterGroup(
Settings.CUSTOM_SPEED_MENU,
"playback_rate_selector_menu_sheet.eml-js"
);
addPathCallbacks(playbackRateSelectorGroup);
}
@Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
isPlaybackRateSelectorMenuVisible = true;
return false;
}
}

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.youtube.patches.components; package app.revanced.extension.youtube.patches.components;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.settings.Setting; import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch; import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@@ -96,7 +94,7 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == videoQualityMenuFooter) { if (matchedGroup == videoQualityMenuFooter) {
return true; return true;
@@ -107,10 +105,10 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
} }
// Shorts also use this player flyout panel // Shorts also use this player flyout panel
if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(protobufBufferArray).isFiltered()) { if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(buffer).isFiltered()) {
return false; return false;
} }
return flyoutFilterGroupList.check(protobufBufferArray).isFiltered(); return flyoutFilterGroupList.check(buffer).isFiltered();
} }
} }

View File

@@ -26,7 +26,7 @@ import app.revanced.extension.youtube.TrieSearch;
* *
* Once a way to asynchronously update litho text is found, this strategy will no longer be needed. * Once a way to asynchronously update litho text is found, this strategy will no longer be needed.
*/ */
public final class ReturnYouTubeDislikeFilterPatch extends Filter { public final class ReturnYouTubeDislikeFilter extends Filter {
/** /**
* Last unique video id's loaded. Value is ignored and Map is treated as a Set. * Last unique video id's loaded. Value is ignored and Map is treated as a Set.
@@ -67,7 +67,7 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
private final ByteArrayFilterGroupList videoIdFilterGroup = new ByteArrayFilterGroupList(); private final ByteArrayFilterGroupList videoIdFilterGroup = new ByteArrayFilterGroupList();
public ReturnYouTubeDislikeFilterPatch() { public ReturnYouTubeDislikeFilter() {
// When a new Short is opened, the like buttons always seem to load before the dislike. // When a new Short is opened, the like buttons always seem to load before the dislike.
// But if swiping back to a previous video and liking/disliking, then only that single button reloads. // But if swiping back to a previous video and liking/disliking, then only that single button reloads.
// So must check for both buttons. // So must check for both buttons.
@@ -84,15 +84,15 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (!Settings.RYD_ENABLED.get() || !Settings.RYD_SHORTS.get()) { if (!Settings.RYD_ENABLED.get() || !Settings.RYD_SHORTS.get()) {
return false; return false;
} }
FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(protobufBufferArray); FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(buffer);
if (result.isFiltered()) { if (result.isFiltered()) {
String matchedVideoId = findVideoId(protobufBufferArray); String matchedVideoId = findVideoId(buffer);
// Matched video will be null if in incognito mode. // Matched video will be null if in incognito mode.
// Must pass a null id to correctly clear out the current video data. // Must pass a null id to correctly clear out the current video data.
// Otherwise if a Short is opened in non-incognito, then incognito is enabled and another Short is opened, // Otherwise if a Short is opened in non-incognito, then incognito is enabled and another Short is opened,

View File

@@ -4,8 +4,6 @@ import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButt
import android.view.View; import android.view.View;
import androidx.annotation.Nullable;
import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar; import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -13,7 +11,6 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.NavigationBar; import app.revanced.extension.youtube.shared.NavigationBar;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
@@ -321,7 +318,7 @@ public final class ShortsFilter extends Filter {
} }
@Override @Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (contentType == FilterContentType.PATH) { if (contentType == FilterContentType.PATH) {
if (matchedGroup == subscribeButton || matchedGroup == joinButton || matchedGroup == paidPromotionButton) { if (matchedGroup == subscribeButton || matchedGroup == joinButton || matchedGroup == paidPromotionButton) {
@@ -330,22 +327,22 @@ public final class ShortsFilter extends Filter {
} }
if (matchedGroup == useSoundButton) { if (matchedGroup == useSoundButton) {
return useSoundButtonBuffer.check(protobufBufferArray).isFiltered(); return useSoundButtonBuffer.check(buffer).isFiltered();
} }
if (matchedGroup == useTemplateButton) { if (matchedGroup == useTemplateButton) {
return useTemplateButtonBuffer.check(protobufBufferArray).isFiltered(); return useTemplateButtonBuffer.check(buffer).isFiltered();
} }
if (matchedGroup == shortsCompactFeedVideo) { if (matchedGroup == shortsCompactFeedVideo) {
return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered(); return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(buffer).isFiltered();
} }
// Video action buttons (comment, share, remix) have the same path. // Video action buttons (comment, share, remix) have the same path.
// Like and dislike are separate path filters and don't require buffer searching. // Like and dislike are separate path filters and don't require buffer searching.
if (matchedGroup == shortsActionBar) { if (matchedGroup == shortsActionBar) {
return videoActionButton.check(path).isFiltered() return videoActionButton.check(path).isFiltered()
&& videoActionButtonBuffer.check(protobufBufferArray).isFiltered(); && videoActionButtonBuffer.check(buffer).isFiltered();
} }
if (matchedGroup == suggestedAction) { if (matchedGroup == suggestedAction) {
@@ -356,7 +353,7 @@ public final class ShortsFilter extends Filter {
return true; return true;
} }
return suggestedActionsBuffer.check(protobufBufferArray).isFiltered(); return suggestedActionsBuffer.check(buffer).isFiltered();
} }
return true; return true;

View File

@@ -18,7 +18,7 @@ import app.revanced.extension.youtube.settings.Settings;
public final class AdvancedVideoQualityMenuPatch { public final class AdvancedVideoQualityMenuPatch {
/** /**
* Injection point. * Injection point. Regular videos.
*/ */
public static void onFlyoutMenuCreate(RecyclerView recyclerView) { public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return; if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return;
@@ -61,22 +61,12 @@ public final class AdvancedVideoQualityMenuPatch {
}); });
} }
/**
* Injection point.
*
* Used to force the creation of the advanced menu item for the Shorts quality flyout.
*/
public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) {
return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original;
}
/** /**
* Injection point. * Injection point.
* *
* Shorts video quality flyout. * Shorts video quality flyout.
*/ */
public static void showAdvancedVideoQualityMenu(ListView listView) { public static void addVideoQualityListMenuListener(ListView listView) {
if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return; if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return;
listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@@ -91,7 +81,6 @@ public final class AdvancedVideoQualityMenuPatch {
listView.setSoundEffectsEnabled(false); listView.setSoundEffectsEnabled(false);
final var qualityItemMenuPosition = 4; final var qualityItemMenuPosition = 4;
listView.performItemClick(null, qualityItemMenuPosition, 0); listView.performItemClick(null, qualityItemMenuPosition, 0);
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "showAdvancedVideoQualityMenu failure", ex); Logger.printException(() -> "showAdvancedVideoQualityMenu failure", ex);
} }
@@ -102,4 +91,13 @@ public final class AdvancedVideoQualityMenuPatch {
} }
}); });
} }
/**
* Injection point.
*
* Used to force the creation of the advanced menu item for the Shorts quality flyout.
*/
public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) {
return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original;
}
} }

View File

@@ -5,10 +5,9 @@ import static app.revanced.extension.shared.Utils.NetworkType;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.lang.reflect.Field; import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
@@ -17,10 +16,29 @@ import app.revanced.extension.shared.settings.IntegerSetting;
import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.ShortsPlayerState; import app.revanced.extension.youtube.shared.ShortsPlayerState;
import app.revanced.extension.youtube.videoplayer.VideoQualityDialogButton;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class RememberVideoQualityPatch { public class RememberVideoQualityPatch {
private static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
/**
* Interface to use obfuscated methods.
*/
public interface VideoQualityMenuInterface {
void patch_setQuality(VideoQuality quality);
}
/**
* Video resolution of the automatic quality option..
*/
public static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
/**
* All quality names are the same for all languages.
* VideoQuality also has a resolution enum that can be used if needed.
*/
public static final String VIDEO_QUALITY_1080P_PREMIUM_NAME = "1080p Premium";
private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI; private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI;
private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE; private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI; private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
@@ -29,46 +47,83 @@ public class RememberVideoQualityPatch {
private static boolean qualityNeedsUpdating; private static boolean qualityNeedsUpdating;
/** /**
* If the user selected a new quality from the flyout menu, * The available qualities of the current video.
* and {@link Settings#REMEMBER_VIDEO_QUALITY_LAST_SELECTED} is enabled.
*/
private static boolean userChangedDefaultQuality;
/**
* Index of the video quality chosen by the user from the flyout menu.
*/
private static int userSelectedQualityIndex;
/**
* The available qualities of the current video in human readable form: [1080, 720, 480]
*/ */
@Nullable @Nullable
private static List<Integer> videoQualities; private static VideoQuality[] currentQualities;
private static boolean shouldRememberVideoQuality() { /**
BooleanSetting preference = ShortsPlayerState.isOpen() ? * The current quality of the video playing.
Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED * This is always the actual quality even if Automatic quality is active.
*/
@Nullable
private static VideoQuality currentQuality;
/**
* The current VideoQualityMenuInterface, set during setVideoQuality.
*/
@Nullable
private static VideoQualityMenuInterface currentMenuInterface;
@Nullable
public static VideoQuality[] getCurrentQualities() {
return currentQualities;
}
@Nullable
public static VideoQuality getCurrentQuality() {
return currentQuality;
}
@Nullable
public static VideoQualityMenuInterface getCurrentMenuInterface() {
return currentMenuInterface;
}
public static boolean shouldRememberVideoQuality() {
BooleanSetting preference = ShortsPlayerState.isOpen()
? Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED
: Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED; : Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED;
return preference.get(); return preference.get();
} }
private static void changeDefaultQuality(int defaultQuality) { public static int getDefaultQualityResolution() {
final boolean isShorts = ShortsPlayerState.isOpen();
IntegerSetting preference = Utils.getNetworkType() == NetworkType.MOBILE
? (isShorts ? shortsQualityMobile : videoQualityMobile)
: (isShorts ? shortsQualityWifi : videoQualityWifi);
return preference.get();
}
public static void saveDefaultQuality(int qualityResolution) {
final boolean shortPlayerOpen = ShortsPlayerState.isOpen();
String networkTypeMessage; String networkTypeMessage;
boolean useShortsPreference = ShortsPlayerState.isOpen(); IntegerSetting qualitySetting;
if (Utils.getNetworkType() == NetworkType.MOBILE) { if (Utils.getNetworkType() == NetworkType.MOBILE) {
if (useShortsPreference) shortsQualityMobile.save(defaultQuality);
else videoQualityMobile.save(defaultQuality);
networkTypeMessage = str("revanced_remember_video_quality_mobile"); networkTypeMessage = str("revanced_remember_video_quality_mobile");
qualitySetting = shortPlayerOpen ? shortsQualityMobile : videoQualityMobile;
} else { } else {
if (useShortsPreference) shortsQualityWifi.save(defaultQuality);
else videoQualityWifi.save(defaultQuality);
networkTypeMessage = str("revanced_remember_video_quality_wifi"); networkTypeMessage = str("revanced_remember_video_quality_wifi");
qualitySetting = shortPlayerOpen ? shortsQualityWifi : videoQualityWifi;
} }
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get())
if (qualitySetting.get() == qualityResolution) {
// User clicked the same video quality as the current video,
// or changed between 1080p Premium and non-Premium.
return;
}
qualitySetting.save(qualityResolution);
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get()) {
String qualityLabel = qualityResolution + "p";
Utils.showToastShort(str( Utils.showToastShort(str(
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast", shortPlayerOpen
networkTypeMessage, (defaultQuality + "p") ? "revanced_remember_video_quality_toast_shorts"
)); : "revanced_remember_video_quality_toast",
networkTypeMessage,
qualityLabel)
);
}
} }
/** /**
@@ -77,109 +132,132 @@ public class RememberVideoQualityPatch {
* @param qualities Video qualities available, ordered from largest to smallest, with index 0 being the 'automatic' value of -2 * @param qualities Video qualities available, ordered from largest to smallest, with index 0 being the 'automatic' value of -2
* @param originalQualityIndex quality index to use, as chosen by YouTube * @param originalQualityIndex quality index to use, as chosen by YouTube
*/ */
public static int setVideoQuality(Object[] qualities, final int originalQualityIndex, Object qInterface, String qIndexMethod) { public static int setVideoQuality(VideoQuality[] qualities, VideoQualityMenuInterface menu, int originalQualityIndex) {
try { try {
boolean useShortsPreference = ShortsPlayerState.isOpen(); Utils.verifyOnMainThread();
final int preferredQuality = Utils.getNetworkType() == NetworkType.MOBILE currentMenuInterface = menu;
? (useShortsPreference ? shortsQualityMobile : videoQualityMobile).get()
: (useShortsPreference ? shortsQualityWifi : videoQualityWifi).get();
if (!userChangedDefaultQuality && preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) { final boolean availableQualitiesChanged = (currentQualities == null)
|| !Arrays.equals(currentQualities, qualities);
if (availableQualitiesChanged) {
currentQualities = qualities;
Logger.printDebug(() -> "VideoQualities: " + Arrays.toString(currentQualities));
}
VideoQuality updatedCurrentQuality = qualities[originalQualityIndex];
if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE
&& (currentQuality == null || currentQuality != updatedCurrentQuality)) {
currentQuality = updatedCurrentQuality;
Logger.printDebug(() -> "Current quality changed to: " + updatedCurrentQuality);
VideoQualityDialogButton.updateButtonIcon(updatedCurrentQuality);
}
final int preferredQuality = getDefaultQualityResolution();
if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) {
return originalQualityIndex; // Nothing to do. return originalQualityIndex; // Nothing to do.
} }
if (videoQualities == null || videoQualities.size() != qualities.length) { // After changing videos the qualities can initially be for the prior video.
videoQualities = new ArrayList<>(qualities.length); // If the qualities have changed and the default is not auto then an update is needed.
for (Object streamQuality : qualities) { if (!qualityNeedsUpdating && !availableQualitiesChanged) {
for (Field field : streamQuality.getClass().getFields()) {
if (field.getType().isAssignableFrom(Integer.TYPE)
&& field.getName().length() <= 2) {
videoQualities.add(field.getInt(streamQuality));
}
}
}
// After changing videos the qualities can initially be for the prior video.
// So if the qualities have changed an update is needed.
qualityNeedsUpdating = true;
Logger.printDebug(() -> "VideoQualities: " + videoQualities);
}
if (userChangedDefaultQuality) {
userChangedDefaultQuality = false;
final int quality = videoQualities.get(userSelectedQualityIndex);
Logger.printDebug(() -> "User changed default quality to: " + quality);
changeDefaultQuality(quality);
return userSelectedQualityIndex;
}
if (!qualityNeedsUpdating) {
return originalQualityIndex; return originalQualityIndex;
} }
qualityNeedsUpdating = false; qualityNeedsUpdating = false;
// Find the highest quality that is equal to or less than the preferred. // Find the highest quality that is equal to or less than the preferred.
int qualityToUse = videoQualities.get(0); // first element is automatic mode
int qualityIndexToUse = 0;
int i = 0; int i = 0;
for (Integer quality : videoQualities) { for (VideoQuality quality : qualities) {
if (quality <= preferredQuality && qualityToUse < quality) { final int qualityResolution = quality.patch_getResolution();
qualityToUse = quality; if ((qualityResolution != AUTOMATIC_VIDEO_QUALITY_VALUE && qualityResolution <= preferredQuality)
qualityIndexToUse = i; // Use the lowest video quality if the default is lower than all available.
|| i == qualities.length - 1) {
final boolean qualityNeedsChange = (i != originalQualityIndex);
Logger.printDebug(() -> qualityNeedsChange
? "Changing video quality from: " + updatedCurrentQuality + " to: " + quality
: "Video is already the preferred quality: " + quality
);
// On first load of a new regular video, if the video is already the
// desired quality then the quality flyout will show 'Auto' (ie: Auto (720p)).
//
// To prevent user confusion, set the video index even if the
// quality is already correct so the UI picker will not display "Auto".
//
// Only change Shorts quality if the quality actually needs to change,
// because the "auto" option is not shown in the flyout
// and setting the same quality again can cause the Short to restart.
if (qualityNeedsChange || !ShortsPlayerState.isOpen()) {
menu.patch_setQuality(qualities[i]);
return i;
}
return originalQualityIndex;
} }
i++; i++;
} }
// If the desired quality index is equal to the original index,
// then the video is already set to the desired default quality.
final int qualityToUseFinal = qualityToUse;
if (qualityIndexToUse == originalQualityIndex) {
// On first load of a new video, if the UI video quality flyout menu
// is not updated then it will still show 'Auto' (ie: Auto (480p)),
// even though it's already set to the desired resolution.
//
// To prevent confusion, set the video index anyways (even if it matches the existing index)
// as that will force the UI picker to not display "Auto".
Logger.printDebug(() -> "Video is already preferred quality: " + qualityToUseFinal);
} else {
Logger.printDebug(() -> "Changing video quality from: "
+ videoQualities.get(originalQualityIndex) + " to: " + qualityToUseFinal);
}
Method m = qInterface.getClass().getMethod(qIndexMethod, Integer.TYPE);
m.invoke(qInterface, qualityToUse);
return qualityIndexToUse;
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Failed to set quality", ex); Logger.printException(() -> "setVideoQuality failure", ex);
return originalQualityIndex; }
return originalQualityIndex;
}
/**
* Injection point.
* @param userSelectedQualityIndex Element index of {@link #currentQualities}.
*/
public static void userChangedShortsQuality(int userSelectedQualityIndex) {
try {
if (shouldRememberVideoQuality()) {
if (currentQualities == null) {
Logger.printDebug(() -> "Cannot save default quality, qualities is null");
return;
}
VideoQuality quality = currentQualities[userSelectedQualityIndex];
saveDefaultQuality(quality.patch_getResolution());
}
} catch (Exception ex) {
Logger.printException(() -> "userChangedShortsQuality failure", ex);
} }
} }
/** /**
* Injection point. Old quality menu. * Injection point. Regular videos.
* @param videoResolution Human readable resolution: 480, 720, 1080.
*/ */
public static void userChangedQuality(int selectedQualityIndex) { public static void userChangedQuality(int videoResolution) {
Utils.verifyOnMainThread();
if (shouldRememberVideoQuality()) { if (shouldRememberVideoQuality()) {
userSelectedQualityIndex = selectedQualityIndex; saveDefaultQuality(videoResolution);
userChangedDefaultQuality = true;
} }
} }
/**
* Injection point. New quality menu.
*/
public static void userChangedQualityInNewFlyout(int selectedQuality) {
if (!shouldRememberVideoQuality()) return;
changeDefaultQuality(selectedQuality); // Quality is human readable resolution (ie: 1080).
}
/** /**
* Injection point. * Injection point.
*/ */
public static void newVideoStarted(VideoInformation.PlaybackController ignoredPlayerController) { public static void newVideoStarted(VideoInformation.PlaybackController ignoredPlayerController) {
Utils.verifyOnMainThread();
Logger.printDebug(() -> "newVideoStarted"); Logger.printDebug(() -> "newVideoStarted");
currentQualities = null;
currentQuality = null;
currentMenuInterface = null;
qualityNeedsUpdating = true; qualityNeedsUpdating = true;
videoQualities = null;
// Hide the quality button until playback starts and the qualities are available.
VideoQualityDialogButton.updateButtonIcon(null);
}
/**
* Injection point. Fixes bad data used by YouTube.
*/
public static int fixVideoQualityResolution(String name, int quality) {
final int correctQuality = 480;
if (name.equals("480p") && quality != correctQuality) {
return correctQuality;
}
return quality;
} }
} }

View File

@@ -23,7 +23,6 @@ import android.view.Gravity;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.animation.Animation; import android.view.animation.Animation;
@@ -42,7 +41,7 @@ import java.util.function.Function;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilterPatch; import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilter;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
import kotlin.Unit; import kotlin.Unit;
@@ -80,6 +79,16 @@ public class CustomPlaybackSpeedPatch {
*/ */
public static final float[] customPlaybackSpeeds; public static final float[] customPlaybackSpeeds;
/**
* Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}.
*/
private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax;
/**
* The last time the old playback menu was forcefully called.
*/
private static volatile long lastTimeOldPlaybackMenuInvoked;
/** /**
* Formats speeds to UI strings. * Formats speeds to UI strings.
*/ */
@@ -90,11 +99,6 @@ public class CustomPlaybackSpeedPatch {
*/ */
private static WeakReference<Dialog> currentDialog = new WeakReference<>(null); private static WeakReference<Dialog> currentDialog = new WeakReference<>(null);
/**
* Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}.
*/
private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax;
static { static {
// Cap at 2 decimals (rounds automatically). // Cap at 2 decimals (rounds automatically).
speedFormatter.setMaximumFractionDigits(2); speedFormatter.setMaximumFractionDigits(2);
@@ -174,25 +178,33 @@ public class CustomPlaybackSpeedPatch {
public static void onFlyoutMenuCreate(RecyclerView recyclerView) { public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
recyclerView.getViewTreeObserver().addOnDrawListener(() -> { recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
try { try {
if (PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible) { if (PlaybackSpeedMenuFilter.isPlaybackRateSelectorMenuVisible) {
if (hideLithoMenuAndShowCustomSpeedMenu(recyclerView, 5)) { if (hideLithoMenuAndShowSpeedMenu(recyclerView, 5)) {
PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible = false; PlaybackSpeedMenuFilter.isPlaybackRateSelectorMenuVisible = false;
} }
} }
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "onFlyoutMenuCreate failure", ex); Logger.printException(() -> "isPlaybackRateSelectorMenuVisible failure", ex);
}
try {
if (PlaybackSpeedMenuFilter.isOldPlaybackSpeedMenuVisible) {
if (hideLithoMenuAndShowSpeedMenu(recyclerView, 8)) {
PlaybackSpeedMenuFilter.isOldPlaybackSpeedMenuVisible = false;
}
}
} catch (Exception ex) {
Logger.printException(() -> "isOldPlaybackSpeedMenuVisible failure", ex);
} }
}); });
} }
@SuppressWarnings("SameParameterValue") private static boolean hideLithoMenuAndShowSpeedMenu(RecyclerView recyclerView, int expectedChildCount) {
private static boolean hideLithoMenuAndShowCustomSpeedMenu(RecyclerView recyclerView, int expectedChildCount) {
if (recyclerView.getChildCount() == 0) { if (recyclerView.getChildCount() == 0) {
return false; return false;
} }
View firstChild = recyclerView.getChildAt(0); if (!(recyclerView.getChildAt(0) instanceof ViewGroup playbackSpeedParentView)) {
if (!(firstChild instanceof ViewGroup playbackSpeedParentView)) {
return false; return false;
} }
@@ -200,33 +212,49 @@ public class CustomPlaybackSpeedPatch {
return false; return false;
} }
ViewParent parentView3rd = Utils.getParentView(recyclerView, 3); if (!(Utils.getParentView(recyclerView, 3) instanceof ViewGroup parentView3rd)) {
if (!(parentView3rd instanceof ViewGroup)) { return false;
return true;
} }
ViewParent parentView4th = parentView3rd.getParent(); if (!(parentView3rd.getParent() instanceof ViewGroup parentView4th)) {
if (!(parentView4th instanceof ViewGroup)) { return false;
return true;
} }
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView. // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
// This only shows in phone layout. // This only shows in phone layout.
final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0); var touchInsidedView = parentView4th.getChildAt(0);
touchInsidedView.setSoundEffectsEnabled(false); touchInsidedView.setSoundEffectsEnabled(false);
touchInsidedView.performClick(); touchInsidedView.performClick();
// In tablet layout there is no Dismiss View, instead we just hide all two parent views. // In tablet layout there is no Dismiss View, instead we just hide all two parent views.
((ViewGroup) parentView3rd).setVisibility(View.GONE); parentView3rd.setVisibility(View.GONE);
((ViewGroup) parentView4th).setVisibility(View.GONE); parentView4th.setVisibility(View.GONE);
// Close the litho speed menu and show the modern custom speed dialog. // Close the litho speed menu and show the custom speeds.
showModernCustomPlaybackSpeedDialog(recyclerView.getContext()); if (Settings.RESTORE_OLD_SPEED_MENU.get()) {
Logger.printDebug(() -> "Modern playback speed dialog shown"); showOldPlaybackSpeedMenu();
Logger.printDebug(() -> "Old playback speed dialog shown");
} else {
showModernCustomPlaybackSpeedDialog(recyclerView.getContext());
Logger.printDebug(() -> "Modern playback speed dialog shown");
}
return true; return true;
} }
public static void showOldPlaybackSpeedMenu() {
// This method is sometimes used multiple times.
// To prevent this, ignore method reuse within 1 second.
final long now = System.currentTimeMillis();
if (now - lastTimeOldPlaybackMenuInvoked < 1000) {
Logger.printDebug(() -> "Ignoring call to showOldPlaybackSpeedMenu");
return;
}
lastTimeOldPlaybackMenuInvoked = now;
// Rest of the implementation added by patch.
}
/** /**
* Displays a modern custom dialog for adjusting video playback speed. * Displays a modern custom dialog for adjusting video playback speed.
* <p> * <p>
@@ -643,11 +671,9 @@ public class CustomPlaybackSpeedPatch {
*/ */
public static int getAdjustedBackgroundColor(boolean isHandleBar) { public static int getAdjustedBackgroundColor(boolean isHandleBar) {
final int baseColor = Utils.getDialogBackgroundColor(); final int baseColor = Utils.getDialogBackgroundColor();
float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme. final float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme.
float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme. final float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme.
return Utils.isDarkModeEnabled() return Utils.adjustColorBrightness(baseColor, lightThemeFactor, darkThemeFactor);
? Utils.adjustColorBrightness(baseColor, darkThemeFactor) // Lighten for dark theme.
: Utils.adjustColorBrightness(baseColor, lightThemeFactor); // Darken for light theme.
} }
} }

View File

@@ -5,7 +5,9 @@ import static app.revanced.extension.shared.Utils.getResourceIdentifier;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.util.TypedValue;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toolbar; import android.widget.Toolbar;
@@ -24,12 +26,15 @@ import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFrag
* This class is responsible for injecting our own fragment by replacing the LicenseActivity. * This class is responsible for injecting our own fragment by replacing the LicenseActivity.
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class LicenseActivityHook { public class LicenseActivityHook extends Activity {
private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value. private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.
private static ViewGroup.LayoutParams toolbarLayoutParams; private static ViewGroup.LayoutParams toolbarLayoutParams;
@SuppressLint("StaticFieldLeak")
public static SearchViewController searchViewController;
public static void setToolbarLayoutParams(Toolbar toolbar) { public static void setToolbarLayoutParams(Toolbar toolbar) {
if (toolbarLayoutParams != null) { if (toolbarLayoutParams != null) {
toolbar.setLayoutParams(toolbarLayoutParams); toolbar.setLayoutParams(toolbarLayoutParams);
@@ -126,12 +131,13 @@ public class LicenseActivityHook {
view -> view instanceof TextView); view -> view instanceof TextView);
if (toolbarTextView != null) { if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor()); toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
} }
setToolbarLayoutParams(toolbar); setToolbarLayoutParams(toolbar);
// Add Search Icon and EditText for ReVancedPreferenceFragment only. // Add Search bar only for ReVancedPreferenceFragment.
if (fragment instanceof ReVancedPreferenceFragment) { if (fragment instanceof ReVancedPreferenceFragment) {
SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment); searchViewController = SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
} }
toolBarParent.addView(toolbar, 0); toolBarParent.addView(toolbar, 0);
@@ -166,4 +172,10 @@ public class LicenseActivityHook {
Utils.setIsDarkModeEnabled(themeOrdinal == 1); Utils.setIsDarkModeEnabled(themeOrdinal == 1);
} }
} }
public static void handleConfigurationChanged(Activity activity, Configuration newConfig) {
if (searchViewController != null) {
searchViewController.handleOrientationChange(newConfig.orientation);
}
}
} }

View File

@@ -10,6 +10,7 @@ import android.graphics.drawable.GradientDrawable;
import android.util.Pair; import android.util.Pair;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
@@ -51,6 +52,7 @@ public class SearchViewController {
private final Deque<String> searchHistory; private final Deque<String> searchHistory;
private final AutoCompleteTextView autoCompleteTextView; private final AutoCompleteTextView autoCompleteTextView;
private final boolean showSettingsSearchHistory; private final boolean showSettingsSearchHistory;
private int currentOrientation;
/** /**
* Creates a background drawable for the SearchView with rounded corners. * Creates a background drawable for the SearchView with rounded corners.
@@ -83,8 +85,8 @@ public class SearchViewController {
/** /**
* Adds search view components to the activity. * Adds search view components to the activity.
*/ */
public static void addSearchViewComponents(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) { public static SearchViewController addSearchViewComponents(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
new SearchViewController(activity, toolbar, fragment); return new SearchViewController(activity, toolbar, fragment);
} }
private SearchViewController(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) { private SearchViewController(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
@@ -93,6 +95,7 @@ public class SearchViewController {
this.originalTitle = toolbar.getTitle(); this.originalTitle = toolbar.getTitle();
this.showSettingsSearchHistory = Settings.SETTINGS_SEARCH_HISTORY.get(); this.showSettingsSearchHistory = Settings.SETTINGS_SEARCH_HISTORY.get();
this.searchHistory = new LinkedList<>(); this.searchHistory = new LinkedList<>();
this.currentOrientation = activity.getResources().getConfiguration().orientation;
StringSetting searchEntries = Settings.SETTINGS_SEARCH_ENTRIES; StringSetting searchEntries = Settings.SETTINGS_SEARCH_ENTRIES;
if (showSettingsSearchHistory) { if (showSettingsSearchHistory) {
String entries = searchEntries.get(); String entries = searchEntries.get();
@@ -115,6 +118,9 @@ public class SearchViewController {
searchView.getContext().getResources().getIdentifier( searchView.getContext().getResources().getIdentifier(
"android:id/search_src_text", null, null)); "android:id/search_src_text", null, null));
// Disable fullscreen keyboard mode.
autoCompleteTextView.setImeOptions(autoCompleteTextView.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
// Set background and query hint. // Set background and query hint.
searchView.setBackground(createBackgroundDrawable(toolbar.getContext())); searchView.setBackground(createBackgroundDrawable(toolbar.getContext()));
searchView.setQueryHint(str("revanced_settings_search_hint")); searchView.setQueryHint(str("revanced_settings_search_hint"));
@@ -197,7 +203,7 @@ public class SearchViewController {
if (isSearchActive) { if (isSearchActive) {
closeSearch(); closeSearch();
} else { } else {
activity.onBackPressed(); activity.finish();
} }
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "navigation click failure", ex); Logger.printException(() -> "navigation click failure", ex);
@@ -285,6 +291,16 @@ public class SearchViewController {
} }
} }
public void handleOrientationChange(int newOrientation) {
if (newOrientation != currentOrientation) {
currentOrientation = newOrientation;
if (autoCompleteTextView != null) {
autoCompleteTextView.dismissDropDown();
Logger.printDebug(() -> "Orientation changed, search history dismissed");
}
}
}
/** /**
* Opens the search view and shows the keyboard. * Opens the search view and shows the keyboard.
*/ */
@@ -313,7 +329,7 @@ public class SearchViewController {
/** /**
* Closes the search view and hides the keyboard. * Closes the search view and hides the keyboard.
*/ */
private void closeSearch() { public void closeSearch() {
isSearchActive = false; isSearchActive = false;
toolbar.getMenu().findItem(getResourceIdentifier( toolbar.getMenu().findItem(getResourceIdentifier(
"action_search", "id")).setVisible(true); "action_search", "id")).setVisible(true);
@@ -326,6 +342,19 @@ public class SearchViewController {
imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0); imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0);
} }
public static boolean handleBackPress() {
if (LicenseActivityHook.searchViewController != null
&& LicenseActivityHook.searchViewController.isSearchActive()) {
LicenseActivityHook.searchViewController.closeSearch();
return true;
}
return false;
}
public boolean isSearchActive() {
return isSearchActive;
}
/** /**
* Custom ArrayAdapter for search history. * Custom ArrayAdapter for search history.
*/ */

View File

@@ -68,8 +68,9 @@ public class Settings extends BaseSettings {
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE); public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_last_selected_toast", TRUE, false, public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_last_selected_toast", TRUE, false,
parent(REMEMBER_PLAYBACK_SPEED_LAST_SELECTED)); parent(REMEMBER_PLAYBACK_SPEED_LAST_SELECTED));
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 FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f);
public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE);
public static final BooleanSetting RESTORE_OLD_SPEED_MENU = new BooleanSetting("revanced_restore_old_speed_menu", FALSE, parent(CUSTOM_SPEED_MENU));
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds", public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
"0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true); "0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true);
@@ -100,7 +101,6 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true); public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true);
public static final BooleanSetting HIDE_DOODLES = new BooleanSetting("revanced_hide_doodles", FALSE, true, "revanced_hide_doodles_user_dialog_message"); public static final BooleanSetting HIDE_DOODLES = new BooleanSetting("revanced_hide_doodles", FALSE, true, "revanced_hide_doodles_user_dialog_message");
public static final BooleanSetting HIDE_EXPANDABLE_CARD = new BooleanSetting("revanced_hide_expandable_card", TRUE); public static final BooleanSetting HIDE_EXPANDABLE_CARD = new BooleanSetting("revanced_hide_expandable_card", TRUE);
public static final BooleanSetting HIDE_FEED_SURVEY = new BooleanSetting("revanced_hide_feed_survey", TRUE);
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true); public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true);
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_HISTORY = new BooleanSetting("revanced_hide_filter_bar_feed_in_history", FALSE); public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_HISTORY = new BooleanSetting("revanced_hide_filter_bar_feed_in_history", FALSE);
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS = new BooleanSetting("revanced_hide_filter_bar_feed_in_related_videos", FALSE, true); public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS = new BooleanSetting("revanced_hide_filter_bar_feed_in_related_videos", FALSE, true);
@@ -113,6 +113,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_NOTIFY_ME_BUTTON = new BooleanSetting("revanced_hide_notify_me_button", TRUE); public static final BooleanSetting HIDE_NOTIFY_ME_BUTTON = new BooleanSetting("revanced_hide_notify_me_button", TRUE);
public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_playables", TRUE); public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_playables", TRUE);
public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true); public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true);
public static final BooleanSetting HIDE_SURVEYS = new BooleanSetting("revanced_hide_surveys", TRUE);
public static final BooleanSetting HIDE_TICKET_SHELF = new BooleanSetting("revanced_hide_ticket_shelf", FALSE); public static final BooleanSetting HIDE_TICKET_SHELF = new BooleanSetting("revanced_hide_ticket_shelf", FALSE);
public static final BooleanSetting HIDE_VIDEO_RECOMMENDATION_LABELS = new BooleanSetting("revanced_hide_video_recommendation_labels", TRUE); public static final BooleanSetting HIDE_VIDEO_RECOMMENDATION_LABELS = new BooleanSetting("revanced_hide_video_recommendation_labels", TRUE);
@@ -171,6 +172,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_VIDEO_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE); public static final BooleanSetting HIDE_VIDEO_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE);
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE); public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE); public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
public static final BooleanSetting VIDEO_QUALITY_DIALOG_BUTTON = new BooleanSetting("revanced_video_quality_dialog_button", FALSE);
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true); 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); public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
@@ -191,7 +193,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE); public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE);
public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action_button", FALSE); public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action_button", FALSE);
public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name", public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name",
"org.schabi.newpipe" /* NewPipe */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON)); "com.deniscerri.ytdl" /* YTDLnis */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON));
// Comments // Comments
public static final BooleanSetting HIDE_COMMENTS_AI_CHAT_SUMMARY = new BooleanSetting("revanced_hide_comments_ai_chat_summary", FALSE); public static final BooleanSetting HIDE_COMMENTS_AI_CHAT_SUMMARY = new BooleanSetting("revanced_hide_comments_ai_chat_summary", FALSE);

View File

@@ -16,10 +16,8 @@ import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings({"unused", "deprecation"}) @SuppressWarnings({"unused", "deprecation"})
public final class CustomVideoSpeedListPreference extends CustomDialogListPreference { public final class CustomVideoSpeedListPreference extends CustomDialogListPreference {
/** {
* Initialize a settings preference list with the available playback speeds. // Initialize a settings preference list with the available playback speeds.
*/
private void initializeEntryValues() {
float[] customPlaybackSpeeds = CustomPlaybackSpeedPatch.customPlaybackSpeeds; float[] customPlaybackSpeeds = CustomPlaybackSpeedPatch.customPlaybackSpeeds;
final int numberOfEntries = customPlaybackSpeeds.length + 1; final int numberOfEntries = customPlaybackSpeeds.length + 1;
String[] preferenceListEntries = new String[numberOfEntries]; String[] preferenceListEntries = new String[numberOfEntries];
@@ -41,10 +39,6 @@ public final class CustomVideoSpeedListPreference extends CustomDialogListPrefer
setEntryValues(preferenceListEntryValues); setEntryValues(preferenceListEntryValues);
} }
{
initializeEntryValues();
}
public CustomVideoSpeedListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public CustomVideoSpeedListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }

View File

@@ -0,0 +1,444 @@
package app.revanced.extension.youtube.settings.preference;
import static app.revanced.extension.shared.StringRef.sf;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.util.TypedValue;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
import app.revanced.extension.youtube.settings.Settings;
/**
* A custom ListPreference for selecting an external downloader package with checkmarks and EditText for custom package names.
*/
@SuppressWarnings({"unused", "deprecation"})
public class ExternalDownloaderPreference extends CustomDialogListPreference {
/**
* Enum representing supported external downloaders with their display names, package names, and download URLs.
*/
private enum Downloader {
YTDLNIS("YTDLnis",
"com.deniscerri.ytdl",
"https://ytdlnis.org",
true),
SEAL("Seal",
"com.junkfood.seal",
"https://github.com/JunkFood02/Seal/releases/latest",
true),
GRAYJAY("Grayjay",
"com.futo.platformplayer",
"https://grayjay.app"),
LIBRETUBE("LibreTube",
"com.github.libretube",
"https://libretube.dev"),
NEWPIPE("NewPipe",
"org.schabi.newpipe",
"https://newpipe.net"),
PIPEPIPE("PipePipe",
"InfinityLoop1309.NewPipeEnhanced",
"https://pipepipe.dev"),
TUBULAR("Tubular",
"org.polymorphicshade.tubular",
"https://github.com/polymorphicshade/Tubular/releases/latest"),
OTHER(sf("revanced_external_downloader_other_item").toString(),
null,
null,
true);
private static final Map<String, Downloader> PACKAGE_TO_ENUM = new HashMap<>();
static {
for (Downloader downloader : values()) {
String packageName = downloader.packageName;
if (packageName != null) {
PACKAGE_TO_ENUM.put(packageName, downloader);
}
}
}
/**
* Finds a Downloader by its package name. This method can never return {@link #OTHER}.
* @return The Downloader enum or null if not found.
*/
@Nullable
public static Downloader findByPackageName(String packageName) {
return PACKAGE_TO_ENUM.get(Objects.requireNonNull(packageName));
}
public final String name;
@Nullable
public final String packageName;
@Nullable
public final String downloadUrl;
/**
* If a downloader app should be shown in the preference settings
* if the app is not currently installed.
*/
public final boolean isPreferred;
Downloader(String name, String packageName, String downloadUrl) {
this(name, packageName, downloadUrl, false);
}
Downloader(String name, @Nullable String packageName, @Nullable String downloadUrl, boolean isPreferred) {
this.name = name;
this.packageName = packageName;
this.downloadUrl = downloadUrl;
this.isPreferred = isPreferred;
}
public boolean isInstalled() {
return packageName != null && isAppInstalledAndEnabled(packageName);
}
}
private static boolean isAppInstalledAndEnabled(String packageName) {
try {
if (Utils.getContext().getPackageManager().getApplicationInfo(packageName, 0).enabled) {
Logger.printDebug(() -> "App installed: " + packageName);
return true;
}
} catch (PackageManager.NameNotFoundException error) {
Logger.printDebug(() -> "App not installed: " + packageName);
}
return false;
}
private EditText editText;
private CustomDialogListPreference.ListPreferenceArrayAdapter adapter;
public ExternalDownloaderPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ExternalDownloaderPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ExternalDownloaderPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExternalDownloaderPreference(Context context) {
super(context);
}
private void updateEntries() {
List<CharSequence> entries = new ArrayList<>();
List<CharSequence> entryValues = new ArrayList<>();
for (Downloader downloader : Downloader.values()) {
if (downloader.isPreferred || downloader.isInstalled()) {
String packageName = downloader.packageName;
entries.add(downloader.name);
entryValues.add(packageName != null
? packageName
: Downloader.OTHER.name);
}
}
setEntries(entries.toArray(new CharSequence[0]));
setEntryValues(entryValues.toArray(new CharSequence[0]));
}
/**
* Sets the summary for this ListPreference.
*/
@Override
public void setSummary(CharSequence summary) {
// Ignore calls to set the summary.
// Summary is always the description of the category.
//
// This is required otherwise the ReVanced preference fragment
// sets all ListPreference summaries to show the current selection.
}
/**
* Shows a custom dialog with a ListView for predefined downloader packages and EditText for custom package input.
*/
@Override
protected void showDialog(@Nullable Bundle state) {
// Must set entries before showing the dialog, to handle if
// an app is installed while the settings are open in the background.
updateEntries();
Context context = getContext();
String packageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get();
// Create the main layout for the dialog content.
LinearLayout contentLayout = new LinearLayout(context);
contentLayout.setOrientation(LinearLayout.VERTICAL);
// Create ListView for predefined downloader apps.
ListView listView = new ListView(context);
listView.setId(android.R.id.list);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Create custom adapter for the ListView.
final boolean usingCustomDownloader = Downloader.findByPackageName(packageName) == null;
adapter = new CustomDialogListPreference.ListPreferenceArrayAdapter(
context,
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
getEntries(),
getEntryValues(),
usingCustomDownloader
? Downloader.OTHER.name
: packageName
);
listView.setAdapter(adapter);
Function<String, Void> updateListViewSelection = (updatedPackageName) -> {
String entryValueName = Downloader.findByPackageName(updatedPackageName) == null
? Downloader.OTHER.name
: updatedPackageName;
CharSequence[] entryValues = getEntryValues();
for (int i = 0, length = entryValues.length; i < length; i++) {
String entryString = entryValues[i].toString();
if (entryString.equals(entryValueName)) {
listView.setItemChecked(i, true);
listView.setSelection(i);
adapter.setSelectedValue(entryString);
adapter.notifyDataSetChanged();
break;
}
}
return null;
};
updateListViewSelection.apply(packageName);
// Handle item click to select value.
listView.setOnItemClickListener((parent, view, position, id) -> {
String selectedValue = getEntryValues()[position].toString();
Downloader selectedApp = Downloader.findByPackageName(selectedValue);
if (selectedApp != null) {
editText.setText(selectedApp.packageName);
editText.setEnabled(false); // Disable editing for predefined options.
} else {
String savedPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get();
editText.setText(Downloader.findByPackageName(savedPackageName) == null
? savedPackageName // If the user is clicking thru options then retain existing other app.
: ""
);
editText.setEnabled(true); // Enable editing for Custom.
editText.requestFocus();
}
editText.setSelection(editText.getText().length());
adapter.setSelectedValue(selectedValue);
adapter.notifyDataSetChanged();
});
// Add ListView to content layout with initial height.
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
0 // Initial height, will be updated.
);
listViewParams.bottomMargin = dipToPixels(16);
contentLayout.addView(listView, listViewParams);
// Add EditText for custom package name.
editText = new EditText(context);
editText.setText(packageName);
editText.setSelection(packageName.length());
editText.setHint(str("revanced_external_downloader_other_item_hint"));
editText.setSingleLine(true); // Restrict EditText to a single line.
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
// Set initial EditText state based on selected downloader.
editText.setEnabled(usingCustomDownloader);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable edit) {
String updatedPackageName = edit.toString().trim();
updateListViewSelection.apply(updatedPackageName);
}
});
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(10), null, null));
editTextBackground.getPaint().setColor(Utils.getEditTextBackground());
final int dip8 = dipToPixels(8);
editText.setPadding(dip8, dip8, dip8, dip8);
editText.setBackground(editTextBackground);
editText.setClipToOutline(true);
contentLayout.addView(editText);
// Create the custom dialog.
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
context,
getTitle() != null ? getTitle().toString() : "",
null,
null,
null,
() -> {
String newValue = editText.getText().toString().trim();
if (newValue.isEmpty()) {
// Show dialog if EditText is empty.
Utils.createCustomDialog(
context,
str("revanced_external_downloader_name_title"),
str("revanced_external_downloader_empty_warning"),
null,
null,
() -> {}, // OK button does nothing (dismiss only).
null,
null,
null,
false
).first.show();
return;
}
if (showDialogIfAppIsNotInstalled(getContext(), newValue)) {
return; // Invalid package. Do not save.
}
// Save custom package name.
if (callChangeListener(newValue)) {
setValue(newValue);
}
},
() -> {}, // Cancel button action (dismiss only).
str("revanced_settings_reset"),
() -> { // Reset action.
String defaultValue = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.defaultValue;
editText.setText(defaultValue);
editText.setSelection(defaultValue.length());
editText.setEnabled(false); // Disable editing on reset.
updateListViewSelection.apply(defaultValue);
},
false
);
// Add the content layout directly to the dialog's main layout.
LinearLayout dialogMainLayout = dialogPair.second;
dialogMainLayout.addView(contentLayout, dialogMainLayout.getChildCount() - 1);
// Update ListView height dynamically based on orientation.
//noinspection ExtractMethodRecommender
Runnable updateListViewHeight = () -> {
int totalHeight = 0;
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter != null) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int listAdapterCount = listAdapter.getCount();
for (int i = 0; i < listAdapterCount; i++) {
View item = listAdapter.getView(i, null, listView);
item.measure(
View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.AT_MOST),
View.MeasureSpec.UNSPECIFIED
);
totalHeight += item.getMeasuredHeight();
}
totalHeight += listView.getDividerHeight() * (listAdapterCount - 1);
}
final int orientation = context.getResources().getConfiguration().orientation;
if (orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT) {
// In portrait orientation, use WRAP_CONTENT for ListView height.
listViewParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
} else {
// In landscape orientation, limit ListView height to 30% of screen height.
final int maxHeight = Utils.percentageHeightToPixels(30);
listViewParams.height = Math.min(totalHeight, maxHeight);
}
listView.setLayoutParams(listViewParams);
};
// Initial height calculation.
updateListViewHeight.run();
// Listen for configuration changes (e.g., orientation).
View dialogView = dialogPair.second;
// Recalculate height when layout changes (e.g., orientation change).
dialogView.getViewTreeObserver().addOnGlobalLayoutListener(updateListViewHeight::run);
// Show the dialog.
dialogPair.first.show();
}
/**
* @return If the app is not installed and a dialog was shown.
*/
public static boolean showDialogIfAppIsNotInstalled(Context context, String packageName) {
if (isAppInstalledAndEnabled(packageName)) {
return false;
}
Downloader downloader = Downloader.findByPackageName(packageName);
String downloadUrl = downloader != null
? downloader.downloadUrl
: null;
String okButtonText = downloadUrl != null
? str("gms_core_dialog_open_website_text") // Open website.
: null; // Ok.
// Show a dialog if the recommended app is not installed or if the custom package cannot be found.
String message = downloader != null
? str("revanced_external_downloader_not_installed_warning", downloader.name)
: str("revanced_external_downloader_package_not_found_warning", packageName);
Utils.createCustomDialog(
context,
str("revanced_external_downloader_not_found_title"),
message,
null,
okButtonText,
() -> {
try {
// OK button action: open the downloader's URL if available.
if (downloadUrl != null) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(downloadUrl));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
} catch (Exception ex) {
Logger.printException(() -> "Failed to open downloader URL: " + downloader, ex);
}
},
() -> {}, // Cancel button action (dismiss only).
null,
null,
false
).first.show();
return true;
}
}

View File

@@ -17,6 +17,7 @@ import android.preference.SwitchPreference;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.BackgroundColorSpan; import android.text.style.BackgroundColorSpan;
import android.util.TypedValue;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowInsets; import android.view.WindowInsets;
@@ -248,7 +249,15 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
rootView.setOnApplyWindowInsetsListener((v, insets) -> { rootView.setOnApplyWindowInsetsListener((v, insets) -> {
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars()); Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars()); Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
v.setPadding(0, statusInsets.top, 0, navInsets.bottom); Insets cutoutInsets = insets.getInsets(WindowInsets.Type.displayCutout());
// Apply padding for display cutout in landscape.
int leftPadding = cutoutInsets.left;
int rightPadding = cutoutInsets.right;
int topPadding = statusInsets.top;
int bottomPadding = navInsets.bottom;
v.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
return insets; return insets;
}); });
} }
@@ -265,10 +274,16 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
true, TextView.class::isInstance); true, TextView.class::isInstance);
if (toolbarTextView != null) { if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor()); toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
} }
LicenseActivityHook.setToolbarLayoutParams(toolbar); LicenseActivityHook.setToolbarLayoutParams(toolbar);
if (LicenseActivityHook.searchViewController != null
&& LicenseActivityHook.searchViewController.isSearchActive()) {
toolbar.post(() -> LicenseActivityHook.searchViewController.closeSearch());
}
rootView.addView(toolbar, 0); rootView.addView(toolbar, 0);
return false; return false;
} }
@@ -318,10 +333,8 @@ class AbstractPreferenceSearchData<T extends Preference> {
return text; return text;
} }
final int baseColor = Utils.getAppBackgroundColor(); final int adjustedColor = Utils.adjustColorBrightness(Utils.getAppBackgroundColor(),
final int adjustedColor = Utils.isDarkModeEnabled() 0.95f, 1.20f);
? Utils.adjustColorBrightness(baseColor, 1.20f) // Lighten for dark theme.
: Utils.adjustColorBrightness(baseColor, 0.95f); // Darken for light theme.
BackgroundColorSpan highlightSpan = new BackgroundColorSpan(adjustedColor); BackgroundColorSpan highlightSpan = new BackgroundColorSpan(adjustedColor);
SpannableStringBuilder spannable = new SpannableStringBuilder(text); SpannableStringBuilder spannable = new SpannableStringBuilder(text);

View File

@@ -830,11 +830,10 @@ public class SegmentPlaybackController {
WindowManager.LayoutParams params = window.getAttributes(); WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.BOTTOM; params.gravity = Gravity.BOTTOM;
params.y = dipToPixels(72); params.y = dipToPixels(72);
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics(); int portraitWidth = Utils.percentageWidthToPixels(60); // 60% of the screen width.
int portraitWidth = (int) (displayMetrics.widthPixels * 0.6);
if (Resources.getSystem().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { if (Resources.getSystem().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
portraitWidth = (int) Math.min(portraitWidth, displayMetrics.heightPixels * 0.6); portraitWidth = Math.min(portraitWidth, Utils.percentageHeightToPixels(60)); // 60% of the screen height.
} }
params.width = portraitWidth; params.width = portraitWidth;
params.dimAmount = 0.0f; params.dimAmount = 0.0f;

View File

@@ -9,9 +9,6 @@ import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.showToastShort;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class PlaybackSpeedDialogButton { public class PlaybackSpeedDialogButton {
@Nullable @Nullable
@@ -29,7 +26,11 @@ public class PlaybackSpeedDialogButton {
Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get, Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get,
view -> { view -> {
try { try {
CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext()); if (Settings.RESTORE_OLD_SPEED_MENU.get()) {
CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu();
} else {
CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext());
}
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "speed button onClick failure", ex); Logger.printException(() -> "speed button onClick failure", ex);
} }

View File

@@ -187,4 +187,56 @@ public class PlayerControlButton {
if (view != null) view.setVisibility(View.GONE); if (view != null) view.setVisibility(View.GONE);
isVisible = false; isVisible = false;
} }
/**
* Sets the icon of the button.
* @param resourceId Drawable identifier, or zero to hide the icon.
*/
public void setIcon(int resourceId) {
try {
View button = buttonRef.get();
if (button instanceof ImageView imageButton) {
imageButton.setImageResource(resourceId);
}
} catch (Exception ex) {
Logger.printException(() -> "setIcon failure", ex);
}
}
/**
* Starts an animation on the button.
* @param animation The animation to apply.
*/
public void startAnimation(Animation animation) {
try {
View button = buttonRef.get();
if (button != null) {
button.startAnimation(animation);
}
} catch (Exception ex) {
Logger.printException(() -> "startAnimation failure", ex);
}
}
/**
* Clears any animation on the button.
*/
public void clearAnimation() {
try {
View button = buttonRef.get();
if (button != null) {
button.clearAnimation();
}
} catch (Exception ex) {
Logger.printException(() -> "clearAnimation failure", ex);
}
}
/**
* Returns the View associated with this button.
* @return The button View.
*/
public View getView() {
return buttonRef.get();
}
} }

View File

@@ -0,0 +1,482 @@
package app.revanced.extension.youtube.videoplayer;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.AUTOMATIC_VIDEO_QUALITY_VALUE;
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VIDEO_QUALITY_1080P_PREMIUM_NAME;
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VideoQualityMenuInterface;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
import java.util.ArrayList;
import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
public class VideoQualityDialogButton {
private static final int DRAWABLE_LD = getDrawableIdentifier("revanced_video_quality_dialog_button_ld");
private static final int DRAWABLE_SD = getDrawableIdentifier("revanced_video_quality_dialog_button_sd");
private static final int DRAWABLE_HD = getDrawableIdentifier("revanced_video_quality_dialog_button_hd");
private static final int DRAWABLE_FHD = getDrawableIdentifier("revanced_video_quality_dialog_button_fhd");
private static final int DRAWABLE_FHD_PLUS = getDrawableIdentifier("revanced_video_quality_dialog_button_fhd_plus");
private static final int DRAWABLE_QHD = getDrawableIdentifier("revanced_video_quality_dialog_button_qhd");
private static final int DRAWABLE_4K = getDrawableIdentifier("revanced_video_quality_dialog_button_4k");
private static final int DRAWABLE_UNKNOWN = getDrawableIdentifier("revanced_video_quality_dialog_button_unknown");
@Nullable
private static PlayerControlButton instance;
/**
* The current resource name of the button icon.
*/
private static int currentIconResource;
private static int getDrawableIdentifier(String resourceName) {
final int resourceId = Utils.getResourceIdentifier(resourceName, "drawable");
if (resourceId == 0) Logger.printException(() -> "Could not find resource: " + resourceName);
return resourceId;
}
/**
* Updates the button icon based on the current video quality.
*/
public static void updateButtonIcon(@Nullable VideoQuality quality) {
try {
Utils.verifyOnMainThread();
if (instance == null) return;
final int resolution = quality == null
? AUTOMATIC_VIDEO_QUALITY_VALUE // Video is still loading.
: quality.patch_getResolution();
final int iconResource = switch (resolution) {
case 144, 240, 360 -> DRAWABLE_LD;
case 480 -> DRAWABLE_SD;
case 720 -> DRAWABLE_HD;
case 1080 -> VIDEO_QUALITY_1080P_PREMIUM_NAME.equals(quality.patch_getQualityName())
? DRAWABLE_FHD_PLUS
: DRAWABLE_FHD;
case 1440 -> DRAWABLE_QHD;
case 2160 -> DRAWABLE_4K;
default -> DRAWABLE_UNKNOWN;
};
if (iconResource != currentIconResource) {
currentIconResource = iconResource;
Utils.runOnMainThreadDelayed(() -> {
if (iconResource != currentIconResource) {
Logger.printDebug(() -> "Ignoring stale button update to: " + quality);
return;
}
instance.setIcon(iconResource);
}, 100);
}
} catch (Exception ex) {
Logger.printException(() -> "updateButtonIcon failure", ex);
}
}
/**
* Injection point.
*/
public static void initializeButton(View controlsView) {
try {
instance = new PlayerControlButton(
controlsView,
"revanced_video_quality_dialog_button",
"revanced_video_quality_dialog_button_placeholder",
Settings.VIDEO_QUALITY_DIALOG_BUTTON::get,
view -> {
try {
showVideoQualityDialog(view.getContext());
} catch (Exception ex) {
Logger.printException(() -> "Video quality button onClick failure", ex);
}
},
view -> {
try {
VideoQuality[] qualities = RememberVideoQualityPatch.getCurrentQualities();
VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface();
if (qualities == null || menu == null) {
Logger.printDebug(() -> "Cannot reset quality, videoQualities is null");
return true;
}
// Reset to default quality.
final int defaultResolution = RememberVideoQualityPatch.getDefaultQualityResolution();
for (VideoQuality quality : qualities) {
final int resolution = quality.patch_getResolution();
if (resolution != AUTOMATIC_VIDEO_QUALITY_VALUE && resolution <= defaultResolution) {
Logger.printDebug(() -> "Resetting quality to: " + quality);
menu.patch_setQuality(quality);
return true;
}
}
// Existing hook cannot set default quality to auto.
// Instead show the quality dialog.
showVideoQualityDialog(view.getContext());
return true;
} catch (Exception ex) {
Logger.printException(() -> "Video quality button reset failure", ex);
}
return false;
}
);
// Set initial icon.
updateButtonIcon(RememberVideoQualityPatch.getCurrentQuality());
} catch (Exception ex) {
Logger.printException(() -> "initializeButton failure", ex);
}
}
/**
* Injection point.
*/
public static void setVisibilityImmediate(boolean visible) {
if (instance != null) {
instance.setVisibilityImmediate(visible);
}
}
/**
* Injection point.
*/
public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) {
instance.setVisibility(visible, animated);
}
}
/**
* Shows a dialog with available video qualities, excluding Auto, with a title showing the current quality.
*/
private static void showVideoQualityDialog(Context context) {
try {
VideoQuality[] currentQualities = RememberVideoQualityPatch.getCurrentQualities();
VideoQuality currentQuality = RememberVideoQualityPatch.getCurrentQuality();
if (currentQualities == null || currentQuality == null) {
Logger.printDebug(() -> "Cannot show qualities dialog, videoQualities is null");
return;
}
if (currentQualities.length < 2) {
// Should never happen.
Logger.printException(() -> "Cannot show qualities dialog, no qualities available");
return;
}
VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface();
if (menu == null) {
Logger.printDebug(() -> "Cannot show qualities dialog, menu is null");
return;
}
// -1 adjustment for automatic quality at first index.
int listViewSelectedIndex = -1;
for (VideoQuality quality : currentQualities) {
if (quality.patch_getQualityName().equals(currentQuality.patch_getQualityName())) {
break;
}
listViewSelectedIndex++;
}
List<String> qualityLabels = new ArrayList<>(currentQualities.length - 1);
for (VideoQuality availableQuality : currentQualities) {
if (availableQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE) {
qualityLabels.add(availableQuality.patch_getQualityName());
}
}
Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCanceledOnTouchOutside(true);
dialog.setCancelable(true);
final int dip4 = dipToPixels(4); // Height for handle bar.
final int dip5 = dipToPixels(5); // Padding for mainLayout.
final int dip6 = dipToPixels(6); // Bottom margin.
final int dip8 = dipToPixels(8); // Side padding.
final int dip16 = dipToPixels(16); // Left padding for ListView.
final int dip20 = dipToPixels(20); // Margin below handle.
final int dip40 = dipToPixels(40); // Width for handle bar.
LinearLayout mainLayout = new LinearLayout(context);
mainLayout.setOrientation(LinearLayout.VERTICAL);
mainLayout.setPadding(dip5, dip8, dip5, dip8);
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(12), null, null));
background.getPaint().setColor(Utils.getDialogBackgroundColor());
mainLayout.setBackground(background);
View handleBar = new View(context);
ShapeDrawable handleBackground = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(4), null, null));
final int baseColor = Utils.getDialogBackgroundColor();
final int adjustedHandleBarBackgroundColor = Utils.adjustColorBrightness(
baseColor, 0.9f, 1.25f);
handleBackground.getPaint().setColor(adjustedHandleBarBackgroundColor);
handleBar.setBackground(handleBackground);
LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(dip40, dip4);
handleParams.gravity = Gravity.CENTER_HORIZONTAL;
handleParams.setMargins(0, 0, 0, dip20);
handleBar.setLayoutParams(handleParams);
mainLayout.addView(handleBar);
// Create SpannableStringBuilder for formatted text.
SpannableStringBuilder spannableTitle = new SpannableStringBuilder();
String titlePart = str("video_quality_quick_menu_title");
String separatorPart = str("video_quality_title_seperator");
// Append title part with default foreground color.
spannableTitle.append(titlePart);
spannableTitle.setSpan(
new ForegroundColorSpan(Utils.getAppForegroundColor()),
0,
titlePart.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
spannableTitle.append(" "); // Space after title.
// Append separator part with adjusted title color.
int separatorStart = spannableTitle.length();
spannableTitle.append(separatorPart);
final int adjustedTitleForegroundColor = Utils.adjustColorBrightness(
Utils.getAppForegroundColor(), 1.6f, 0.6f);
spannableTitle.setSpan(
new ForegroundColorSpan(adjustedTitleForegroundColor),
separatorStart,
separatorStart + separatorPart.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
spannableTitle.append(" "); // Space after separator.
// Append quality label with adjusted title color.
final int qualityStart = spannableTitle.length();
spannableTitle.append(currentQuality.patch_getQualityName());
spannableTitle.setSpan(
new ForegroundColorSpan(adjustedTitleForegroundColor),
qualityStart,
qualityStart + currentQuality.patch_getQualityName().length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
// Add title with current quality.
TextView titleView = new TextView(context);
titleView.setText(spannableTitle);
titleView.setTextSize(16);
// Remove setTextColor since color is handled by SpannableStringBuilder.
LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
titleParams.setMargins(dip8, 0, 0, dip20);
titleView.setLayoutParams(titleParams);
mainLayout.addView(titleView);
ListView listView = new ListView(context);
CustomQualityAdapter adapter = new CustomQualityAdapter(context, qualityLabels);
adapter.setSelectedPosition(listViewSelectedIndex);
listView.setAdapter(adapter);
listView.setDivider(null);
listView.setPadding(dip16, 0, 0, 0);
listView.setOnItemClickListener((parent, view, which, id) -> {
try {
final int originalIndex = which + 1; // Adjust for automatic.
VideoQuality selectedQuality = currentQualities[originalIndex];
Logger.printDebug(() -> "User clicked on quality: " + selectedQuality);
if (RememberVideoQualityPatch.shouldRememberVideoQuality()) {
RememberVideoQualityPatch.saveDefaultQuality(selectedQuality.patch_getResolution());
}
// Don't update button icon now. Icon will update when the actual
// quality is changed by YT. This is needed to ensure the icon is correct
// if YT ignores changing from 1080p Premium to regular 1080p.
menu.patch_setQuality(selectedQuality);
dialog.dismiss();
} catch (Exception ex) {
Logger.printException(() -> "Video quality selection failure", ex);
}
});
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
listViewParams.setMargins(0, 0, 0, dip5);
listView.setLayoutParams(listViewParams);
mainLayout.addView(listView);
LinearLayout wrapperLayout = new LinearLayout(context);
wrapperLayout.setOrientation(LinearLayout.VERTICAL);
wrapperLayout.setPadding(dip8, 0, dip8, 0);
wrapperLayout.addView(mainLayout);
dialog.setContentView(wrapperLayout);
Window window = dialog.getWindow();
if (window != null) {
WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.BOTTOM;
params.y = dip6;
int portraitWidth = context.getResources().getDisplayMetrics().widthPixels;
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
portraitWidth = Math.min(
portraitWidth,
context.getResources().getDisplayMetrics().heightPixels);
}
params.width = portraitWidth;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(params);
window.setBackgroundDrawable(null);
}
final int fadeDurationFast = Utils.getResourceInteger("fade_duration_fast");
Animation slideInABottomAnimation = Utils.getResourceAnimation("slide_in_bottom");
slideInABottomAnimation.setDuration(fadeDurationFast);
mainLayout.startAnimation(slideInABottomAnimation);
// noinspection ClickableViewAccessibility
mainLayout.setOnTouchListener(new View.OnTouchListener() {
final float dismissThreshold = dipToPixels(100);
float touchY;
float translationY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchY = event.getRawY();
translationY = mainLayout.getTranslationY();
return true;
case MotionEvent.ACTION_MOVE:
final float deltaY = event.getRawY() - touchY;
if (deltaY >= 0) {
mainLayout.setTranslationY(translationY + deltaY);
}
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mainLayout.getTranslationY() > dismissThreshold) {
//noinspection ExtractMethodRecommender
final float remainingDistance = context.getResources().getDisplayMetrics().heightPixels
- mainLayout.getTop();
TranslateAnimation slideOut = new TranslateAnimation(
0, 0, mainLayout.getTranslationY(), remainingDistance);
slideOut.setDuration(fadeDurationFast);
slideOut.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
dialog.dismiss();
}
@Override
public void onAnimationRepeat(Animation animation) {}
});
mainLayout.startAnimation(slideOut);
} else {
TranslateAnimation slideBack = new TranslateAnimation(
0, 0, mainLayout.getTranslationY(), 0);
slideBack.setDuration(fadeDurationFast);
mainLayout.startAnimation(slideBack);
mainLayout.setTranslationY(0);
}
return true;
default:
return false;
}
}
});
dialog.show();
} catch (Exception ex) {
Logger.printException(() -> "showVideoQualityDialog failure", ex);
}
}
private static class CustomQualityAdapter extends ArrayAdapter<String> {
private int selectedPosition = -1;
public CustomQualityAdapter(@NonNull Context context, @NonNull List<String> objects) {
super(context, 0, objects);
}
private void setSelectedPosition(int position) {
this.selectedPosition = position;
notifyDataSetChanged();
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
parent,
false
);
viewHolder = new ViewHolder();
viewHolder.checkIcon = convertView.findViewById(
Utils.getResourceIdentifier("revanced_check_icon", "id")
);
viewHolder.placeholder = convertView.findViewById(
Utils.getResourceIdentifier("revanced_check_icon_placeholder", "id")
);
viewHolder.textView = convertView.findViewById(
Utils.getResourceIdentifier("revanced_item_text", "id")
);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(getItem(position));
final boolean isSelected = position == selectedPosition;
viewHolder.checkIcon.setVisibility(isSelected ? View.VISIBLE : View.GONE);
viewHolder.placeholder.setVisibility(isSelected ? View.GONE : View.INVISIBLE);
return convertView;
}
private static class ViewHolder {
ImageView checkIcon;
View placeholder;
TextView textView;
}
}
}

View File

@@ -0,0 +1,8 @@
package com.google.android.libraries.youtube.innertube.model.media;
public abstract class VideoQuality implements Comparable<VideoQuality> {
public abstract String patch_getQualityName();
public abstract int patch_getResolution();
}

View File

@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true org.gradle.parallel = true
android.useAndroidX = true android.useAndroidX = true
kotlin.code.style = official kotlin.code.style = official
version = 5.31.2-dev.1 version = 5.33.0-dev.12

9
package-lock.json generated
View File

@@ -9,7 +9,7 @@
"@semantic-release/changelog": "^6.0.3", "@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1", "@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.10.1", "gradle-semantic-release-plugin": "^1.10.1",
"semantic-release": "^24.2.6" "semantic-release": "^24.2.7"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@@ -6889,10 +6889,11 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/semantic-release": { "node_modules/semantic-release": {
"version": "24.2.6", "version": "24.2.7",
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.6.tgz", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.7.tgz",
"integrity": "sha512-D0cwjlO5RZzHHxAcsoF1HxiRLfC3ehw+ay+zntzFs6PNX6aV0JzKNG15mpxPipBYa/l4fHly88dHvgDyqwb1Ww==", "integrity": "sha512-g7RssbTAbir1k/S7uSwSVZFfFXwpomUB9Oas0+xi9KStSCmeDXcA7rNhiskjLqvUe/Evhx8fVCT16OSa34eM5g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@semantic-release/commit-analyzer": "^13.0.0-beta.1", "@semantic-release/commit-analyzer": "^13.0.0-beta.1",
"@semantic-release/error": "^4.0.0", "@semantic-release/error": "^4.0.0",

View File

@@ -4,6 +4,6 @@
"@semantic-release/changelog": "^6.0.3", "@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1", "@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.10.1", "gradle-semantic-release-plugin": "^1.10.1",
"semantic-release": "^24.2.6" "semantic-release": "^24.2.7"
} }
} }

View File

@@ -424,6 +424,10 @@ public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatc
public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatchKt {
public static final fun getRemoveRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/pandora/ads/DisableAudioAdsPatchKt { public final class app/revanced/patches/pandora/ads/DisableAudioAdsPatchKt {
public static final fun getDisableAudioAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getDisableAudioAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
@@ -476,6 +480,10 @@ public final class app/revanced/patches/primevideo/misc/permissions/RenamePermis
public static final fun getRenamePermissionsPatch ()Lapp/revanced/patcher/patch/ResourcePatch; public static final fun getRenamePermissionsPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
} }
public final class app/revanced/patches/primevideo/video/speed/PlaybackSpeedPatchKt {
public static final fun getPlaybackSpeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatchKt { public final class app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatchKt {
public static final fun getRemoveFreeAccountsLimitPatch ()Lapp/revanced/patcher/patch/ResourcePatch; public static final fun getRemoveFreeAccountsLimitPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
} }
@@ -1238,6 +1246,7 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD
public final class app/revanced/patches/youtube/interaction/doubletap/DisableChapterSkipDoubleTapPatchKt { public final class app/revanced/patches/youtube/interaction/doubletap/DisableChapterSkipDoubleTapPatchKt {
public static final fun getDisableChapterSkipDoubleTapPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getDisableChapterSkipDoubleTapPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getDisableDoubleTapActionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/youtube/interaction/downloads/DownloadsPatchKt { public final class app/revanced/patches/youtube/interaction/downloads/DownloadsPatchKt {
@@ -1655,6 +1664,10 @@ public final class app/revanced/patches/youtube/video/quality/VideoQualityPatchK
public static final fun getVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatchKt {
public static final fun getVideoQualityButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatchKt { public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatchKt {
public static final fun getPlaybackSpeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getPlaybackSpeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }

View File

@@ -23,7 +23,6 @@ internal val createInboxSubTabsFingerprint = fingerprint {
} }
internal val loadInboxAdsFingerprint = fingerprint { internal val loadInboxAdsFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("V") returns("V")
strings( strings(
"ads_load_begin", "ads_load_begin",

View File

@@ -8,12 +8,7 @@ val hideVideoAdsPatch = bytecodePatch(
name = "Hide music video ads", name = "Hide music video ads",
description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.", description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
navigate(showVideoAdsParentFingerprint.originalMethod) navigate(showVideoAdsParentFingerprint.originalMethod)

View File

@@ -8,12 +8,7 @@ val enableExclusiveAudioPlaybackPatch = bytecodePatch(
name = "Enable exclusive audio playback", name = "Enable exclusive audio playback",
description = "Enables the option to play audio without video.", description = "Enables the option to play audio without video.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
allowExclusiveAudioPlaybackFingerprint.method.returnEarly(true) allowExclusiveAudioPlaybackFingerprint.method.returnEarly(true)

View File

@@ -11,12 +11,7 @@ val permanentRepeatPatch = bytecodePatch(
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.", description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
use = false, use = false,
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex

View File

@@ -7,18 +7,9 @@ import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused") @Suppress("unused")
val permanentShufflePatch = bytecodePatch( val permanentShufflePatch = bytecodePatch(
description = "Permanently remember your shuffle preference " + description = "Permanently remember your shuffle preference " +
"even if the playlist ends or another track is played.", "even if the playlist ends or another track is played."
use = false,
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
),
)
execute { execute {
disableShuffleFingerprint.method.addInstruction(0, "return-void") disableShuffleFingerprint.method.addInstruction(0, "return-void")

View File

@@ -11,12 +11,7 @@ val hideCategoryBar = bytecodePatch(
description = "Hides the category bar at the top of the homepage.", description = "Hides the category bar at the top of the homepage.",
use = false, use = false,
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
constructCategoryBarFingerprint.method.apply { constructCategoryBarFingerprint.method.apply {

View File

@@ -11,12 +11,7 @@ val hideGetPremiumPatch = bytecodePatch(
name = "Hide 'Get Music Premium' label", name = "Hide 'Get Music Premium' label",
description = "Hides the \"Get Music Premium\" label from the account menu and settings.", description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
hideGetPremiumFingerprint.method.apply { hideGetPremiumFingerprint.method.apply {

View File

@@ -18,12 +18,7 @@ val removeUpgradeButtonPatch = bytecodePatch(
name = "Remove upgrade button", name = "Remove upgrade button",
description = "Removes the upgrade tab from the pivot bar.", description = "Removes the upgrade tab from the pivot bar.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
pivotBarConstructorFingerprint.method.apply { pivotBarConstructorFingerprint.method.apply {

View File

@@ -8,12 +8,7 @@ val bypassCertificateChecksPatch = bytecodePatch(
name = "Bypass certificate checks", name = "Bypass certificate checks",
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.", description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
checkCertificateFingerprint.method.returnEarly(true) checkCertificateFingerprint.method.returnEarly(true)

View File

@@ -8,12 +8,7 @@ val backgroundPlaybackPatch = bytecodePatch(
name = "Remove background playback restrictions", name = "Remove background playback restrictions",
description = "Removes restrictions on background playback, including playing kids videos in the background.", description = "Removes restrictions on background playback, including playing kids videos in the background.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
execute { execute {
kidsBackgroundPlaybackPolicyControllerFingerprint.method.addInstruction( kidsBackgroundPlaybackPolicyControllerFingerprint.method.addInstruction(

View File

@@ -25,12 +25,7 @@ val spoofClientPatch = bytecodePatch(
name = "Spoof client", name = "Spoof client",
description = "Spoofs the client to fix playback.", description = "Spoofs the client to fix playback.",
) { ) {
compatibleWith( compatibleWith("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music"(
"7.16.53",
"8.05.51"
)
)
dependsOn( dependsOn(
sharedExtensionPatch, sharedExtensionPatch,

View File

@@ -3,6 +3,7 @@ package app.revanced.patches.nfctoolsse.misc.pro
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
@Deprecated("This patch no longer works and will soon be deleted.")
internal val isLicenseRegisteredFingerprint = fingerprint { internal val isLicenseRegisteredFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC) accessFlags(AccessFlags.PUBLIC)
returns("Z") returns("Z")

View File

@@ -4,9 +4,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused") @Suppress("unused")
val unlockProPatch = bytecodePatch( @Deprecated("This patch no longer works and will soon be deleted.")
name = "Unlock pro", val unlockProPatch = bytecodePatch{
) {
compatibleWith("com.wakdev.apps.nfctools.se") compatibleWith("com.wakdev.apps.nfctools.se")
execute { execute {

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.orfon.detection.root
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal val isDeviceRootedFingeprint = fingerprint {
accessFlags(AccessFlags.PUBLIC)
returns("Z")
custom { method, classDef ->
method.name == "isDeviceRooted" &&
classDef.endsWith("/RootChecker;")
}
}

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.orfon.detection.root
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.returnEarly
@Suppress("unused")
val removeRootDetectionPatch = bytecodePatch(
name = "Remove root detection",
description = "Removes the check for root permissions.",
) {
compatibleWith("com.nousguide.android.orftvthek")
execute {
isDeviceRootedFingeprint.method.returnEarly(false)
}
}

View File

@@ -12,7 +12,7 @@ val skipAdsPatch = bytecodePatch(
name = "Skip ads", name = "Skip ads",
description = "Automatically skips video stream ads.", description = "Automatically skips video stream ads.",
) { ) {
compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.403.257")) compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.412.2947"))
dependsOn(sharedExtensionPatch) dependsOn(sharedExtensionPatch)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.primevideo.video.speed
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal val playbackUserControlsInitializeFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC)
parameters("Lcom/amazon/avod/playbackclient/PlaybackInitializationContext;")
returns("V")
custom { method, classDef ->
method.name == "initialize" && classDef.type == "Lcom/amazon/avod/playbackclient/activity/feature/PlaybackUserControlsFeature;"
}
}
internal val playbackUserControlsPrepareForPlaybackFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC)
parameters("Lcom/amazon/avod/playbackclient/PlaybackContext;")
returns("V")
custom { method, classDef ->
method.name == "prepareForPlayback" &&
classDef.type == "Lcom/amazon/avod/playbackclient/activity/feature/PlaybackUserControlsFeature;"
}
}

View File

@@ -0,0 +1,56 @@
package app.revanced.patches.primevideo.video.speed
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.primevideo.misc.extension.sharedExtensionPatch
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.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/primevideo/videoplayer/PlaybackSpeedPatch;"
val playbackSpeedPatch = bytecodePatch(
name = "Playback speed",
description = "Adds playback speed controls to the video player.",
) {
dependsOn(
sharedExtensionPatch,
)
compatibleWith(
"com.amazon.avod.thirdpartyclient"("3.0.412.2947")
)
execute {
playbackUserControlsInitializeFingerprint.method.apply {
val getIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.IPUT_OBJECT &&
getReference<FieldReference>()?.name == "mUserControls"
}
val getRegister = getInstruction<OneRegisterInstruction>(getIndex).registerA
addInstructions(
getIndex + 1,
"""
invoke-static { v$getRegister }, $EXTENSION_CLASS_DESCRIPTOR->initializeSpeedOverlay(Landroid/view/View;)V
"""
)
}
playbackUserControlsPrepareForPlaybackFingerprint.method.apply {
addInstructions(
0,
"""
invoke-virtual { p1 }, Lcom/amazon/avod/playbackclient/PlaybackContext;->getPlayer()Lcom/amazon/video/sdk/player/Player;
move-result-object v0
invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->setPlayer(Lcom/amazon/video/sdk/player/Player;)V
"""
)
}
}
}

View File

@@ -148,7 +148,7 @@ fun gmsCoreSupportPatch(
fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string -> fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string ->
when (string) { when (string) {
"$fromPackageName.SuggestionsProvider", "$fromPackageName.SuggestionProvider",
"$fromPackageName.fileprovider", "$fromPackageName.fileprovider",
-> string.replace(fromPackageName, toPackageName) -> string.replace(fromPackageName, toPackageName)

View File

@@ -11,6 +11,22 @@ internal val loadOrbitLibraryFingerprint = fingerprint {
strings("/liborbit-jni-spotify.so") strings("/liborbit-jni-spotify.so")
} }
internal val setClientIdFingerprint = fingerprint {
parameters("Ljava/lang/String;")
custom { method, classDef ->
classDef.type == "Lcom/spotify/connectivity/ApplicationScopeConfiguration;"
&& method.name == "setClientId"
}
}
internal val setUserAgentFingerprint = fingerprint {
parameters("Ljava/lang/String;")
custom { method, classDef ->
classDef.type == "Lcom/spotify/connectivity/ApplicationScopeConfiguration;"
&& method.name == "setDefaultHTTPUserAgent"
}
}
internal val extensionFixConstantsFingerprint = fingerprint { internal val extensionFixConstantsFingerprint = fingerprint {
custom { _, classDef -> classDef.type == "Lapp/revanced/extension/spotify/misc/fix/Constants;" } custom { _, classDef -> classDef.type == "Lapp/revanced/extension/spotify/misc/fix/Constants;" }
} }

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.spotify.misc.fix package app.revanced.patches.spotify.misc.fix
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.intOption import app.revanced.patcher.patch.intOption
@@ -72,7 +73,29 @@ val spoofClientPatch = bytecodePatch(
compatibleWith("com.spotify.music") compatibleWith("com.spotify.music")
execute { execute {
// region Spoof client. val clientVersion = clientVersion!!
val hardwareMachine = hardwareMachine!!
val systemVersion = systemVersion!!
// region Spoof login request.
val version = clientVersion
.substringAfter('-')
.substringBeforeLast('.')
.substringBeforeLast('.')
setUserAgentFingerprint.method.addInstruction(
0,
"const-string p1, \"Spotify/$version iOS/$systemVersion ($hardwareMachine)\""
)
setClientIdFingerprint.method.addInstruction(
0, "const-string p1, \"58bd3c95768941ea9eb4350aaa033eb3\""
)
// endregion
// region Spoof client-token request.
loadOrbitLibraryFingerprint.method.addInstructions( loadOrbitLibraryFingerprint.method.addInstructions(
0, 0,
@@ -83,9 +106,9 @@ val spoofClientPatch = bytecodePatch(
) )
mapOf( mapOf(
"getClientVersion" to clientVersion!!, "getClientVersion" to clientVersion,
"getSystemVersion" to systemVersion!!, "getSystemVersion" to systemVersion,
"getHardwareMachine" to hardwareMachine!! "getHardwareMachine" to hardwareMachine
).forEach { (methodName, value) -> ).forEach { (methodName, value) ->
extensionFixConstantsFingerprint.classDef.methods.single { it.name == methodName }.returnEarly(value) extensionFixConstantsFingerprint.classDef.methods.single { it.name == methodName }.returnEarly(value)
} }

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.interaction.doubletap package app.revanced.patches.youtube.interaction.doubletap
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
@@ -8,12 +9,14 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
private const val EXTENSION_CLASS_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/DisableChapterSkipDoubleTapPatch;" "Lapp/revanced/extension/youtube/patches/DisableDoubleTapActionsPatch;"
@Suppress("unused") @Suppress("unused")
val disableChapterSkipDoubleTapPatch = bytecodePatch( val disableDoubleTapActionsPatch = bytecodePatch(
name = "Disable double tap actions", name = "Disable double tap actions",
description = "Adds an option to disable player double tap gestures.", description = "Adds an option to disable player double tap gestures.",
) { ) {
@@ -25,9 +28,6 @@ val disableChapterSkipDoubleTapPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.34.42",
"19.43.41",
"19.47.53",
"20.07.39", "20.07.39",
"20.12.46", "20.12.46",
"20.13.41", "20.13.41",
@@ -35,12 +35,28 @@ val disableChapterSkipDoubleTapPatch = bytecodePatch(
) )
execute { execute {
addResources("youtube", "interaction.doubletap.disableChapterSkipDoubleTapPatch") addResources("youtube", "interaction.doubletap.disableDoubleTapActionsPatch")
PreferenceScreen.PLAYER.addPreferences( PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_disable_chapter_skip_double_tap"), SwitchPreference("revanced_disable_chapter_skip_double_tap"),
) )
val doubleTapInfoGetSeekSourceFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("Z")
returns(seekTypeEnumFingerprint.originalClassDef.type)
opcodes(
Opcode.IF_EQZ,
Opcode.SGET_OBJECT,
Opcode.RETURN_OBJECT,
Opcode.SGET_OBJECT,
Opcode.RETURN_OBJECT,
)
custom { _, classDef ->
classDef.fields.count() == 4
}
}
// Force isChapterSeek flag to false. // Force isChapterSeek flag to false.
doubleTapInfoGetSeekSourceFingerprint.method.addInstructions( doubleTapInfoGetSeekSourceFingerprint.method.addInstructions(
0, 0,
@@ -61,3 +77,8 @@ val disableChapterSkipDoubleTapPatch = bytecodePatch(
) )
} }
} }
@Deprecated("Patch was renamed", ReplaceWith("disableDoubleTapActionsPatch"))
val disableChapterSkipDoubleTapPatch = bytecodePatch {
dependsOn(disableDoubleTapActionsPatch)
}

View File

@@ -2,22 +2,13 @@ package app.revanced.patches.youtube.interaction.doubletap
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val doubleTapInfoGetSeekSourceFingerprint = fingerprint { internal val seekTypeEnumFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
parameters("Z") strings(
returns("L") // Enum SeekSource, but name obfuscated. "SEEK_SOURCE_SEEK_TO_NEXT_CHAPTER",
opcodes( "SEEK_SOURCE_SEEK_TO_PREVIOUS_CHAPTER"
Opcode.IF_EQZ,
Opcode.SGET_OBJECT,
Opcode.RETURN_OBJECT,
Opcode.SGET_OBJECT,
Opcode.RETURN_OBJECT,
) )
custom { _, classDef ->
classDef.fields.count() == 4
}
} }
internal val doubleTapInfoCtorFingerprint = fingerprint { internal val doubleTapInfoCtorFingerprint = fingerprint {

View File

@@ -6,7 +6,6 @@ import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.InputType
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
@@ -40,7 +39,10 @@ private val downloadsResourcePatch = resourcePatch {
preferences = setOf( preferences = setOf(
SwitchPreference("revanced_external_downloader"), SwitchPreference("revanced_external_downloader"),
SwitchPreference("revanced_external_downloader_action_button"), SwitchPreference("revanced_external_downloader_action_button"),
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT), TextPreference(
"revanced_external_downloader_name",
tag = "app.revanced.extension.youtube.settings.preference.ExternalDownloaderPreference",
),
), ),
), ),
) )

View File

@@ -22,6 +22,8 @@ import app.revanced.util.forEachLiteralValueInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import java.io.File import java.io.File
private val variants = arrayOf("light", "dark")
private const val EXTENSION_CLASS_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/ChangeHeaderPatch;" "Lapp/revanced/extension/youtube/patches/ChangeHeaderPatch;"
@@ -29,6 +31,17 @@ private val changeHeaderBytecodePatch = bytecodePatch {
dependsOn(resourceMappingPatch) dependsOn(resourceMappingPatch)
execute { execute {
// Resources are not used during patching, but extension code uses these
// images so verify they exist.
arrayOf(
"yt_ringo2_wordmark_header",
"yt_ringo2_premium_wordmark_header"
).forEach { resource ->
variants.forEach { theme ->
resourceMappings["drawable", resource + "_" + theme]
}
}
arrayOf( arrayOf(
"ytWordmarkHeader", "ytWordmarkHeader",
"ytPremiumWordmarkHeader" "ytPremiumWordmarkHeader"
@@ -57,7 +70,6 @@ private val targetResourceDirectoryNames = mapOf(
"mdpi" to "129px x 48px" "mdpi" to "129px x 48px"
).mapKeys { (dpi, _) -> "drawable-$dpi" } ).mapKeys { (dpi, _) -> "drawable-$dpi" }
private val variants = arrayOf("light", "dark")
/** /**
* Header logos built into this patch. * Header logos built into this patch.

View File

@@ -8,6 +8,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.instructions import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
@@ -200,9 +201,9 @@ val hideLayoutComponentsPatch = bytecodePatch(
key = "revanced_hide_filter_bar_screen", key = "revanced_hide_filter_bar_screen",
preferences = setOf( preferences = setOf(
SwitchPreference("revanced_hide_filter_bar_feed_in_feed"), SwitchPreference("revanced_hide_filter_bar_feed_in_feed"),
SwitchPreference("revanced_hide_filter_bar_feed_in_history"),
SwitchPreference("revanced_hide_filter_bar_feed_in_search"),
SwitchPreference("revanced_hide_filter_bar_feed_in_related_videos"), SwitchPreference("revanced_hide_filter_bar_feed_in_related_videos"),
SwitchPreference("revanced_hide_filter_bar_feed_in_search"),
SwitchPreference("revanced_hide_filter_bar_feed_in_history"),
), ),
), ),
PreferenceScreenPreference( PreferenceScreenPreference(
@@ -222,7 +223,6 @@ val hideLayoutComponentsPatch = bytecodePatch(
SwitchPreference("revanced_hide_crowdfunding_box"), SwitchPreference("revanced_hide_crowdfunding_box"),
SwitchPreference("revanced_hide_chips_shelf"), SwitchPreference("revanced_hide_chips_shelf"),
SwitchPreference("revanced_hide_expandable_card"), SwitchPreference("revanced_hide_expandable_card"),
SwitchPreference("revanced_hide_feed_survey"),
SwitchPreference("revanced_hide_floating_microphone_button"), SwitchPreference("revanced_hide_floating_microphone_button"),
SwitchPreference("revanced_hide_horizontal_shelves"), SwitchPreference("revanced_hide_horizontal_shelves"),
SwitchPreference("revanced_hide_image_shelf"), SwitchPreference("revanced_hide_image_shelf"),
@@ -232,6 +232,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
SwitchPreference("revanced_hide_notify_me_button"), SwitchPreference("revanced_hide_notify_me_button"),
SwitchPreference("revanced_hide_playables"), SwitchPreference("revanced_hide_playables"),
SwitchPreference("revanced_hide_show_more_button"), SwitchPreference("revanced_hide_show_more_button"),
SwitchPreference("revanced_hide_surveys"),
SwitchPreference("revanced_hide_ticket_shelf"), SwitchPreference("revanced_hide_ticket_shelf"),
SwitchPreference("revanced_hide_video_recommendation_labels"), SwitchPreference("revanced_hide_video_recommendation_labels"),
SwitchPreference("revanced_hide_doodles"), SwitchPreference("revanced_hide_doodles"),
@@ -379,16 +380,13 @@ val hideLayoutComponentsPatch = bytecodePatch(
findInstructionIndicesReversedOrThrow { findInstructionIndicesReversedOrThrow {
getReference<MethodReference>()?.name == "setImageDrawable" getReference<MethodReference>()?.name == "setImageDrawable"
}.forEach { insertIndex -> }.forEach { insertIndex ->
val register = getInstruction<FiveRegisterInstruction>(insertIndex).registerD val drawableRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
val imageViewRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
addInstructionsWithLabels( replaceInstruction(
insertIndex, insertIndex,
""" "invoke-static { v$imageViewRegister, v$drawableRegister }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->" +
invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideYoodles(Landroid/graphics/drawable/Drawable;)Landroid/graphics/drawable/Drawable; "setDoodleDrawable(Landroid/widget/ImageView;Landroid/graphics/drawable/Drawable;)V"
move-result-object v$register
if-eqz v$register, :hide
""",
ExternalLabel("hide", getInstruction(insertIndex + 1)),
) )
} }
} }

View File

@@ -99,7 +99,7 @@ val hideInfoCardsPatch = bytecodePatch(
) )
// Info cards can also appear as Litho components. // Info cards can also appear as Litho components.
val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch;" val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilter;"
addLithoFilter(filterClassDescriptor) addLithoFilter(filterClassDescriptor)
} }
} }

View File

@@ -66,8 +66,8 @@ private val hideShortsComponentsResourcePatch = resourcePatch {
PreferenceScreen.SHORTS.addPreferences( PreferenceScreen.SHORTS.addPreferences(
SwitchPreference("revanced_hide_shorts_home"), SwitchPreference("revanced_hide_shorts_home"),
SwitchPreference("revanced_hide_shorts_subscriptions"),
SwitchPreference("revanced_hide_shorts_search"), SwitchPreference("revanced_hide_shorts_search"),
SwitchPreference("revanced_hide_shorts_subscriptions"),
SwitchPreference("revanced_hide_shorts_history"), SwitchPreference("revanced_hide_shorts_history"),
PreferenceScreenPreference( PreferenceScreenPreference(

View File

@@ -43,7 +43,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch;" "Lapp/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch;"
private const val FILTER_CLASS_DESCRIPTOR = private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;" "Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter;"
val returnYouTubeDislikePatch = bytecodePatch( val returnYouTubeDislikePatch = bytecodePatch(
name = "Return YouTube Dislike", name = "Return YouTube Dislike",

View File

@@ -156,7 +156,7 @@ val lithoFilterPatch = bytecodePatch(
move-object/from16 v$freeRegister, p2 move-object/from16 v$freeRegister, p2
iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField
iget-object v$pathRegister, v$freeRegister, $conversionContextPathBuilderField iget-object v$pathRegister, v$freeRegister, $conversionContextPathBuilderField
invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->shouldFilter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->isFiltered(Ljava/lang/String;Ljava/lang/StringBuilder;)Z
move-result v$freeRegister move-result v$freeRegister
if-eqz v$freeRegister, :unfiltered if-eqz v$freeRegister, :unfiltered

View File

@@ -11,7 +11,6 @@ val recyclerViewTreeHookPatch = bytecodePatch {
dependsOn(sharedExtensionPatch) dependsOn(sharedExtensionPatch)
execute { execute {
recyclerViewTreeObserverFingerprint.method.apply { recyclerViewTreeObserverFingerprint.method.apply {
val insertIndex = recyclerViewTreeObserverFingerprint.patternMatch!!.startIndex + 1 val insertIndex = recyclerViewTreeObserverFingerprint.patternMatch!!.startIndex + 1
val recyclerViewParameter = 2 val recyclerViewParameter = 2

View File

@@ -12,31 +12,15 @@ import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.patches.shared.misc.settings.overrideThemeColors import app.revanced.patches.shared.misc.settings.overrideThemeColors
import app.revanced.patches.shared.misc.settings.preference.BasePreference import app.revanced.patches.shared.misc.settings.preference.*
import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.InputType
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.misc.settings.preference.ListPreference
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.shared.misc.settings.preference.TextPreference
import app.revanced.patches.shared.misc.settings.settingsPatch import app.revanced.patches.shared.misc.settings.settingsPatch
import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
import app.revanced.patches.youtube.misc.playservice.is_19_34_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.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.util.ResourceGroup import app.revanced.util.*
import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.copyResources
import app.revanced.util.copyXmlNode
import app.revanced.util.findElementByAttributeValueOrThrow
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.inputStreamFromBundledResource
import app.revanced.util.insertLiteralOverride
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
@@ -152,15 +136,24 @@ private val settingsResourcePatch = resourcePatch {
} }
} }
// Modify the manifest and add a data intent filter to the LicenseActivity. // Modify the manifest to enhance LicenseActivity behavior:
// Some devices freak out if undeclared data is passed to an intent, // 1. Add a data intent filter with MIME type "text/plain".
// and this change appears to fix the issue. // Some devices crash if undeclared data is passed to an intent,
// and this change appears to fix the issue.
// 2. Add android:configChanges="orientation|screenSize|keyboardHidden".
// This prevents the activity from being recreated on configuration changes
// (e.g., screen rotation), preserving its current state and fragment.
document("AndroidManifest.xml").use { document -> document("AndroidManifest.xml").use { document ->
val licenseElement = document.childNodes.findElementByAttributeValueOrThrow( val licenseElement = document.childNodes.findElementByAttributeValueOrThrow(
"android:name", "android:name",
"com.google.android.libraries.social.licenses.LicenseActivity", "com.google.android.libraries.social.licenses.LicenseActivity",
) )
licenseElement.setAttribute(
"android:configChanges",
"orientation|screenSize|keyboardHidden"
)
val mimeType = document.createElement("data") val mimeType = document.createElement("data")
mimeType.setAttribute("android:mimeType", "text/plain") mimeType.setAttribute("android:mimeType", "text/plain")
@@ -242,9 +235,9 @@ val settingsPatch = bytecodePatch(
methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) } methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
} }
// Add context override to force a specific settings language.
licenseActivityOnCreateFingerprint.classDef.apply { licenseActivityOnCreateFingerprint.classDef.apply {
val attachBaseContext = ImmutableMethod( // Add attachBaseContext method to override the context for setting a specific language.
ImmutableMethod(
type, type,
"attachBaseContext", "attachBaseContext",
listOf(ImmutableMethodParameter("Landroid/content/Context;", null, null)), listOf(ImmutableMethodParameter("Landroid/content/Context;", null, null)),
@@ -262,9 +255,50 @@ val settingsPatch = bytecodePatch(
return-void return-void
""" """
) )
} }.let(methods::add)
methods.add(attachBaseContext) // Add onBackPressed method to handle back button presses, delegating to SearchViewController.
ImmutableMethod(
type,
"onBackPressed",
emptyList(),
"V",
AccessFlags.PUBLIC.value,
null,
null,
MutableMethodImplementation(3),
).toMutable().apply {
addInstructions(
"""
invoke-static {}, Lapp/revanced/extension/youtube/settings/SearchViewController;->handleBackPress()Z
move-result v0
if-nez v0, :search_handled
invoke-virtual { p0 }, Landroid/app/Activity;->finish()V
:search_handled
return-void
"""
)
}.let(methods::add)
// Add onConfigurationChanged method to handle configuration changes (e.g., screen orientation).
ImmutableMethod(
type,
"onConfigurationChanged",
listOf(ImmutableMethodParameter("Landroid/content/res/Configuration;", null, null)),
"V",
AccessFlags.PUBLIC.value,
null,
null,
MutableMethodImplementation(3)
).toMutable().apply {
addInstructions(
"""
invoke-super { p0, p1 }, Landroid/app/Activity;->onConfigurationChanged(Landroid/content/res/Configuration;)V
invoke-static { p0, p1 }, $EXTENSION_CLASS_DESCRIPTOR->handleConfigurationChanged(Landroid/app/Activity;Landroid/content/res/Configuration;)V
return-void
"""
)
}.let(methods::add)
} }
// Update shared dark mode status based on YT theme. // Update shared dark mode status based on YT theme.
@@ -338,20 +372,18 @@ object PreferenceScreen : BasePreferenceScreen() {
icon = "@drawable/revanced_settings_screen_05_player", icon = "@drawable/revanced_settings_screen_05_player",
layout = "@layout/preference_with_icon", layout = "@layout/preference_with_icon",
) )
val SHORTS = Screen( val SHORTS = Screen(
key = "revanced_settings_screen_06_shorts", key = "revanced_settings_screen_06_shorts",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_06_shorts", icon = "@drawable/revanced_settings_screen_06_shorts",
layout = "@layout/preference_with_icon", layout = "@layout/preference_with_icon",
) )
val SEEKBAR = Screen( val SEEKBAR = Screen(
key = "revanced_settings_screen_07_seekbar", key = "revanced_settings_screen_07_seekbar",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_07_seekbar", icon = "@drawable/revanced_settings_screen_07_seekbar",
layout = "@layout/preference_with_icon", layout = "@layout/preference_with_icon",
) )
val SWIPE_CONTROLS = Screen( val SWIPE_CONTROLS = Screen(
key = "revanced_settings_screen_08_swipe_controls", key = "revanced_settings_screen_08_swipe_controls",
summaryKey = null, summaryKey = null,

View File

@@ -121,7 +121,7 @@ internal val subtitleButtonControllerFingerprint = fingerprint {
) )
} }
internal val newVideoQualityChangedFingerprint = fingerprint { internal val videoQualityChangedFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L") returns("L")
parameters("L") parameters("L")

View File

@@ -1,23 +1,27 @@
package app.revanced.patches.youtube.video.audio package app.revanced.patches.youtube.video.audio
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.util.containsLiteralInstruction
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal val streamingModelBuilderFingerprint = fingerprint { internal val formatStreamModelToStringFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L") returns("Ljava/lang/String;")
strings("vprng") custom { method, classDef ->
method.name == "toString" && classDef.type ==
"Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;"
}
} }
internal val menuItemAudioTrackFingerprint = fingerprint { internal const val AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG = 45666189L
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("L") internal val selectAudioStreamFingerprint = fingerprint {
returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
strings("menu_item_audio_track") returns("L")
custom { method, _ ->
method.parameters.size > 2 // Method has a large number of parameters and may change.
&& method.parameters[1].type == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;"
&& method.containsLiteralInstruction(AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG)
}
} }
internal val audioStreamingTypeSelector = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
returns("L")
strings("raw") // String is not unique
}

View File

@@ -5,22 +5,22 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_20_07_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.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference import app.revanced.util.findMethodFromToString
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertLiteralOverride
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
@@ -37,6 +37,7 @@ val forceOriginalAudioPatch = bytecodePatch(
sharedExtensionPatch, sharedExtensionPatch,
settingsPatch, settingsPatch,
addResourcesPatch, addResourcesPatch,
versionCheckPatch
) )
compatibleWith( compatibleWith(
@@ -60,29 +61,25 @@ val forceOriginalAudioPatch = bytecodePatch(
) )
) )
fun Method.firstFormatStreamingModelCall( // Disable feature flag that ignores the default track flag
returnType: String = "Ljava/lang/String;" // and instead overrides to the user region language.
): MutableMethod { if (is_20_07_or_greater) {
val audioTrackIdIndex = indexOfFirstInstructionOrThrow { selectAudioStreamFingerprint.method.insertLiteralOverride(
val reference = getReference<MethodReference>() AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG,
reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" "$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z"
&& reference.returnType == returnType )
}
return navigate(this).to(audioTrackIdIndex).stop()
} }
// Accessor methods of FormatStreamModel have no string constants and val isDefaultAudioTrackMethod = formatStreamModelToStringFingerprint.originalMethod
// opcodes are identical to other methods in the same class, .findMethodFromToString("isDefaultAudioTrack=")
// so must walk from another class that use the methods. val audioTrackDisplayNameMethod = formatStreamModelToStringFingerprint.originalMethod
val isDefaultMethod = streamingModelBuilderFingerprint.originalMethod.firstFormatStreamingModelCall("Z") .findMethodFromToString("audioTrackDisplayName=")
val audioTrackIdMethod = menuItemAudioTrackFingerprint.originalMethod.firstFormatStreamingModelCall() val audioTrackIdMethod = formatStreamModelToStringFingerprint.originalMethod
val audioTrackDisplayNameMethod = audioStreamingTypeSelector.originalMethod.firstFormatStreamingModelCall() .findMethodFromToString("audioTrackId=")
val formatStreamModelClass = proxy(classes.first {
it.type == audioTrackIdMethod.definingClass
}).mutableClass
formatStreamModelClass.apply { proxy(classes.first {
it.type == audioTrackIdMethod.definingClass
}).mutableClass.apply {
// Add a new field to store the override. // Add a new field to store the override.
val helperFieldName = "isDefaultAudioTrackOverride" val helperFieldName = "isDefaultAudioTrackOverride"
fields.add( fields.add(
@@ -103,7 +100,7 @@ val forceOriginalAudioPatch = bytecodePatch(
// Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed. // Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed.
val helperMethodClass = type val helperMethodClass = type
val helperMethodName = "extension_isDefaultAudioTrack" val helperMethodName = "patch_isDefaultAudioTrack"
val helperMethod = ImmutableMethod( val helperMethod = ImmutableMethod(
helperMethodClass, helperMethodClass,
helperMethodName, helperMethodName,
@@ -143,7 +140,7 @@ val forceOriginalAudioPatch = bytecodePatch(
methods.add(helperMethod) methods.add(helperMethod)
// Modify isDefaultAudioTrack() to call extension helper method. // Modify isDefaultAudioTrack() to call extension helper method.
isDefaultMethod.apply { isDefaultAudioTrackMethod.apply {
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN) val index = indexOfFirstInstructionOrThrow(Opcode.RETURN)
val register = getInstruction<OneRegisterInstruction>(index).registerA val register = getInstruction<OneRegisterInstruction>(index).registerA

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.video.information package app.revanced.patches.youtube.video.information
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
import app.revanced.util.getReference import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@@ -110,7 +110,7 @@ internal val seekRelativeFingerprint = fingerprint {
} }
/** /**
* Resolves with the class found in [newVideoQualityChangedFingerprint]. * Resolves with the class found in [videoQualityChangedFingerprint].
*/ */
internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint { internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)

View File

@@ -9,7 +9,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.toInstructions import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
import app.revanced.patches.youtube.video.playerresponse.Hook import app.revanced.patches.youtube.video.playerresponse.Hook
import app.revanced.patches.youtube.video.playerresponse.addPlayerResponseMethodHook import app.revanced.patches.youtube.video.playerresponse.addPlayerResponseMethodHook
import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHookPatch import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHookPatch
@@ -263,7 +263,7 @@ val videoInformationPatch = bytecodePatch(
// Handle new playback speed menu. // Handle new playback speed menu.
playbackSpeedMenuSpeedChangedFingerprint.match( playbackSpeedMenuSpeedChangedFingerprint.match(
newVideoQualityChangedFingerprint.originalClassDef, videoQualityChangedFingerprint.originalClassDef,
).method.apply { ).method.apply {
val index = indexOfFirstInstructionOrThrow(Opcode.IGET) val index = indexOfFirstInstructionOrThrow(Opcode.IGET)

View File

@@ -68,7 +68,6 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
// region Patch for the old type of the video quality menu. // region Patch for the old type of the video quality menu.
// Used for regular videos when spoofing to old app version, // Used for regular videos when spoofing to old app version,
// and for the Shorts quality flyout on newer app versions. // and for the Shorts quality flyout on newer app versions.
videoQualityMenuViewInflateFingerprint.let { videoQualityMenuViewInflateFingerprint.let {
it.method.apply { it.method.apply {
val checkCastIndex = it.patternMatch!!.endIndex val checkCastIndex = it.patternMatch!!.endIndex
@@ -77,7 +76,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
addInstruction( addInstruction(
checkCastIndex + 1, checkCastIndex + 1,
"invoke-static { v$listViewRegister }, $EXTENSION_CLASS_DESCRIPTOR->" + "invoke-static { v$listViewRegister }, $EXTENSION_CLASS_DESCRIPTOR->" +
"showAdvancedVideoQualityMenu(Landroid/widget/ListView;)V", "addVideoQualityListMenuListener(Landroid/widget/ListView;)V",
) )
} }
} }

View File

@@ -5,10 +5,25 @@ import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
internal val videoQualityFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters(
"I", // Resolution.
"Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc
"Z",
"L"
)
custom { _, classDef ->
classDef.type == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
}
}
/** /**
* Matches with the class found in [videoQualitySetterFingerprint]. * Matches with the class found in [videoQualitySetterFingerprint].
*/ */
internal val setQualityByIndexMethodClassFieldReferenceFingerprint = fingerprint { internal val setVideoQualityFingerprint = fingerprint {
returns("V") returns("V")
parameters("L") parameters("L")
opcodes( opcodes(
@@ -23,6 +38,22 @@ internal val videoQualityItemOnClickParentFingerprint = fingerprint {
strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT") strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT")
} }
/**
* Resolves to class found in [videoQualityItemOnClickFingerprint].
*/
internal val videoQualityItemOnClickFingerprint = fingerprint {
returns("V")
parameters(
"Landroid/widget/AdapterView;",
"Landroid/view/View;",
"I",
"J"
)
custom { method, _ ->
method.name == "onItemClick"
}
}
internal val videoQualitySetterFingerprint = fingerprint { internal val videoQualitySetterFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V") returns("V")
@@ -37,7 +68,6 @@ internal val videoQualitySetterFingerprint = fingerprint {
strings("menu_item_video_quality") strings("menu_item_video_quality")
} }
internal val videoQualityMenuOptionsFingerprint = fingerprint { internal val videoQualityMenuOptionsFingerprint = fingerprint {
accessFlags(AccessFlags.STATIC) accessFlags(AccessFlags.STATIC)
returns("[L") returns("[L")

View File

@@ -3,8 +3,8 @@ package app.revanced.patches.youtube.video.quality
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.ListPreference import app.revanced.patches.shared.misc.settings.preference.ListPreference
@@ -12,15 +12,21 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
import app.revanced.patches.youtube.video.information.onCreateHook import app.revanced.patches.youtube.video.information.onCreateHook
import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.patches.youtube.video.information.videoInformationPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
private const val EXTENSION_CLASS_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch;" "Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch;"
private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE =
"Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch\$VideoQualityMenuInterface;"
val rememberVideoQualityPatch = bytecodePatch { val rememberVideoQualityPatch = bytecodePatch {
dependsOn( dependsOn(
@@ -61,81 +67,152 @@ val rememberVideoQualityPatch = bytecodePatch {
SwitchPreference("revanced_remember_video_quality_last_selected_toast") SwitchPreference("revanced_remember_video_quality_last_selected_toast")
)) ))
/*
* The following code works by hooking the method which is called when the user selects a video quality
* to remember the last selected video quality.
*
* It also hooks the method which is called when the video quality to set is determined.
* Conveniently, at this point the video quality is overridden to the remembered playback speed.
*/
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted") onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
videoQualityFingerprint.let {
// Fix bad data used by YouTube.
it.method.addInstructions(
0,
"""
invoke-static { p2, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I
move-result p1
"""
)
// Add methods to access obfuscated quality fields.
it.classDef.apply {
methods.add(
ImmutableMethod(
type,
"patch_getQualityName",
listOf(),
"Ljava/lang/String;",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
// Only one string field.
val qualityNameField = fields.single { field ->
field.type == "Ljava/lang/String;"
}
addInstructions(
0,
"""
iget-object v0, p0, $qualityNameField
return-object v0
"""
)
}
)
methods.add(
ImmutableMethod(
type,
"patch_getResolution",
listOf(),
"I",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
val resolutionField = fields.single { field ->
field.type == "I"
}
addInstructions(
0,
"""
iget v0, p0, $resolutionField
return v0
"""
)
}
)
}
}
// Inject a call to set the remembered quality once a video loads. // Inject a call to set the remembered quality once a video loads.
setQualityByIndexMethodClassFieldReferenceFingerprint.match( setVideoQualityFingerprint.match(
videoQualitySetterFingerprint.originalClassDef, videoQualitySetterFingerprint.originalClassDef
).let { match -> ).let { match ->
// This instruction refers to the field with the type that contains the setQualityByIndex method. // This instruction refers to the field with the type that contains the setQuality method.
val instructions = match.method.implementation!!.instructions val instructions = match.method.implementation!!.instructions
val onItemClickListenerClassReference =
val getOnItemClickListenerClassReference =
(instructions.elementAt(0) as ReferenceInstruction).reference (instructions.elementAt(0) as ReferenceInstruction).reference
val getSetQualityByIndexMethodClassFieldReference = val setQualityFieldReference =
(instructions.elementAt(1) as ReferenceInstruction).reference ((instructions.elementAt(1) as ReferenceInstruction).reference) as FieldReference
val setQualityByIndexMethodClassFieldReference = proxy(
getSetQualityByIndexMethodClassFieldReference as FieldReference classes.find { classDef ->
classDef.type == setQualityFieldReference.type
}!!
).mutableClass.apply {
// Add interface and helper methods to allow extension code to call obfuscated methods.
interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE)
val setQualityByIndexMethodClass = classes methods.add(
.find { classDef -> classDef.type == setQualityByIndexMethodClassFieldReference.type }!! ImmutableMethod(
type,
"patch_setQuality",
listOf(
ImmutableMethodParameter(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE, null, null)
),
"V",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
val setQualityMenuIndexMethod = methods.single { method ->
method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
}
// Get the name of the setQualityByIndex method. addInstructions(
val setQualityByIndexMethod = setQualityByIndexMethodClass.methods 0,
.find { method -> method.parameterTypes.first() == "I" } """
?: throw PatchException("Could not find setQualityByIndex method") invoke-virtual { p0, p1 }, $setQualityMenuIndexMethod
return-void
"""
)
}
)
}
videoQualitySetterFingerprint.method.addInstructions( videoQualitySetterFingerprint.method.addInstructions(
0, 0,
""" """
# Get the object instance to invoke the setQualityByIndex method on. # Get object instance to invoke setQuality method.
iget-object v0, p0, $getOnItemClickListenerClassReference iget-object v0, p0, $onItemClickListenerClassReference
iget-object v0, v0, $getSetQualityByIndexMethodClassFieldReference iget-object v0, v0, $setQualityFieldReference
# Get the method name. invoke-static { p1, v0, p2 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([$YOUTUBE_VIDEO_QUALITY_CLASS_TYPE${EXTENSION_VIDEO_QUALITY_MENU_INTERFACE}I)I
const-string v1, "${setQualityByIndexMethod.name}"
# Set the quality.
# The first parameter is the array list of video qualities.
# The second parameter is the index of the selected quality.
# The register v0 stores the object instance to invoke the setQualityByIndex method on.
# The register v1 stores the name of the setQualityByIndex method.
invoke-static { p1, p2, v0, v1 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
move-result p2 move-result p2
""", """
) )
} }
// Inject a call to remember the selected quality. // Inject a call to remember the selected quality for Shorts.
videoQualityItemOnClickParentFingerprint.classDef.methods.find { it.name == "onItemClick" } videoQualityItemOnClickFingerprint.match(
?.apply { videoQualityItemOnClickParentFingerprint.classDef
val listItemIndexParameter = 3 ).method.addInstruction(
0,
"invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V"
)
// Inject a call to remember the user selected quality for regular videos.
videoQualityChangedFingerprint.let {
it.method.apply {
val index = it.patternMatch!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(index).registerA
addInstruction( addInstruction(
0, index + 1,
"invoke-static { p$listItemIndexParameter }, " + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
"$EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
) )
} ?: throw PatchException("Failed to find onItemClick method") }
// Remember video quality if not using old layout menu.
newVideoQualityChangedFingerprint.method.apply {
val index = newVideoQualityChangedFingerprint.patternMatch!!.startIndex
val qualityRegister = getInstruction<TwoRegisterInstruction>(index).registerA
addInstruction(
index + 1,
"invoke-static { v$qualityRegister }, " +
"$EXTENSION_CLASS_DESCRIPTOR->userChangedQualityInNewFlyout(I)V",
)
} }
} }
} }

View File

@@ -5,6 +5,7 @@ import app.revanced.patches.shared.misc.settings.preference.BasePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.video.quality.button.videoQualityButtonPatch
/** /**
* Video quality settings. Used to organize all speed related settings together. * Video quality settings. Used to organize all speed related settings together.
@@ -19,6 +20,7 @@ val videoQualityPatch = bytecodePatch(
dependsOn( dependsOn(
rememberVideoQualityPatch, rememberVideoQualityPatch,
advancedVideoQualityMenuPatch, advancedVideoQualityMenuPatch,
videoQualityButtonPatch,
) )
compatibleWith( compatibleWith(

View File

@@ -0,0 +1,64 @@
package app.revanced.patches.youtube.video.quality.button
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
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.playercontrols.*
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.video.quality.rememberVideoQualityPatch
import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
private val videoQualityButtonResourcePatch = resourcePatch {
dependsOn(playerControlsResourcePatch)
execute {
copyResources(
"qualitybutton",
ResourceGroup(
"drawable",
"revanced_video_quality_dialog_button_ld.xml",
"revanced_video_quality_dialog_button_sd.xml",
"revanced_video_quality_dialog_button_hd.xml",
"revanced_video_quality_dialog_button_fhd.xml",
"revanced_video_quality_dialog_button_fhd_plus.xml",
"revanced_video_quality_dialog_button_qhd.xml",
"revanced_video_quality_dialog_button_4k.xml",
"revanced_video_quality_dialog_button_unknown.xml",
),
)
addBottomControl("qualitybutton")
}
}
private const val QUALITY_BUTTON_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/videoplayer/VideoQualityDialogButton;"
val videoQualityButtonPatch = bytecodePatch(
description = "Adds the option to display video quality dialog button in the video player.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
rememberVideoQualityPatch,
videoQualityButtonResourcePatch,
playerControlsPatch,
)
execute {
addResources("youtube", "video.quality.button.videoQualityButtonPatch")
PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_video_quality_dialog_button"),
)
initializeBottomControl(QUALITY_BUTTON_CLASS_DESCRIPTOR)
injectVisibilityCheckCall(QUALITY_BUTTON_CLASS_DESCRIPTOR)
}
}

View File

@@ -1,11 +1,19 @@
package app.revanced.patches.youtube.video.speed.custom package app.revanced.patches.youtube.video.speed.custom
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.patches.shared.misc.settings.preference.InputType 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.SwitchPreference
import app.revanced.patches.shared.misc.settings.preference.TextPreference import app.revanced.patches.shared.misc.settings.preference.TextPreference
@@ -18,18 +26,34 @@ import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTr
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstLiteralInstruction import app.revanced.util.indexOfFirstLiteralInstruction
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction 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.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
private const val FILTER_CLASS_DESCRIPTOR = private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch;" "Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter;"
private const val EXTENSION_CLASS_DESCRIPTOR = internal const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch;" "Lapp/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch;"
internal var speedUnavailableId = -1L
private set
private val customPlaybackSpeedResourcePatch = resourcePatch {
dependsOn(resourceMappingPatch)
execute {
speedUnavailableId = resourceMappings["string", "varispeed_unavailable_message"]
}
}
internal val customPlaybackSpeedPatch = bytecodePatch( internal val customPlaybackSpeedPatch = bytecodePatch(
description = "Adds custom playback speed options.", description = "Adds custom playback speed options.",
) { ) {
@@ -39,7 +63,8 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
lithoFilterPatch, lithoFilterPatch,
versionCheckPatch, versionCheckPatch,
recyclerViewTreeHookPatch recyclerViewTreeHookPatch,
customPlaybackSpeedResourcePatch
) )
execute { execute {
@@ -48,6 +73,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
settingsMenuVideoSpeedGroup.addAll( settingsMenuVideoSpeedGroup.addAll(
listOf( listOf(
SwitchPreference("revanced_custom_speed_menu"), SwitchPreference("revanced_custom_speed_menu"),
SwitchPreference("revanced_restore_old_speed_menu"),
TextPreference( TextPreference(
"revanced_custom_playback_speeds", "revanced_custom_playback_speeds",
inputType = InputType.TEXT_MULTI_LINE inputType = InputType.TEXT_MULTI_LINE
@@ -77,15 +103,88 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
replaceInstruction(limitMaxIndex, "const/high16 v$limitMaxRegister, 8.0f") replaceInstruction(limitMaxIndex, "const/high16 v$limitMaxRegister, 8.0f")
} }
// Replace the speeds float array with custom speeds.
// These speeds are used if the speed menu is immediately opened after a video is opened.
speedArrayGeneratorFingerprint.method.apply {
val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference<MethodReference>()?.name == "size" }
val sizeCallResultRegister = getInstruction<OneRegisterInstruction>(sizeCallIndex + 1).registerA
replaceInstruction(sizeCallIndex + 1, "const/4 v$sizeCallResultRegister, 0x0")
val arrayLengthConstIndex = indexOfFirstLiteralInstructionOrThrow(7)
val arrayLengthConstDestination = getInstruction<OneRegisterInstruction>(arrayLengthConstIndex).registerA
val playbackSpeedsArrayType = "$EXTENSION_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F"
addInstructions(
arrayLengthConstIndex + 1,
"""
sget-object v$arrayLengthConstDestination, $playbackSpeedsArrayType
array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination
""",
)
val originalArrayFetchIndex = indexOfFirstInstructionOrThrow {
val reference = getReference<FieldReference>()
reference?.type == "[F" && reference.definingClass.endsWith("/PlayerConfigModel;")
}
val originalArrayFetchDestination =
getInstruction<OneRegisterInstruction>(originalArrayFetchIndex).registerA
replaceInstruction(
originalArrayFetchIndex,
"sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType",
)
}
// region Force old video quality menu.
// Add a static INSTANCE field to the class.
// This is later used to call "showOldPlaybackSpeedMenu" on the instance.
val instanceField = ImmutableField(
getOldPlaybackSpeedsFingerprint.originalClassDef.type,
"INSTANCE",
getOldPlaybackSpeedsFingerprint.originalClassDef.type,
AccessFlags.PUBLIC.value or AccessFlags.STATIC.value,
null,
null,
null,
).toMutable()
getOldPlaybackSpeedsFingerprint.classDef.staticFields.add(instanceField)
// Set the INSTANCE field to the instance of the class.
// In order to prevent a conflict with another patch, add the instruction at index 1.
getOldPlaybackSpeedsFingerprint.method.addInstruction(1, "sput-object p0, $instanceField")
// Get the "showOldPlaybackSpeedMenu" method.
// This is later called on the field INSTANCE.
val showOldPlaybackSpeedMenuMethod = showOldPlaybackSpeedMenuFingerprint.match(
getOldPlaybackSpeedsFingerprint.classDef,
).method
// Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE.
showOldPlaybackSpeedMenuExtensionFingerprint.method.apply {
addInstructionsWithLabels(
instructions.lastIndex,
"""
sget-object v0, $instanceField
if-nez v0, :not_null
return-void
:not_null
invoke-virtual { v0 }, $showOldPlaybackSpeedMenuMethod
"""
)
}
// endregion
// Close the unpatched playback dialog and show the modern custom dialog. // Close the unpatched playback dialog and show the modern custom dialog.
addRecyclerViewTreeHook(EXTENSION_CLASS_DESCRIPTOR) addRecyclerViewTreeHook(EXTENSION_CLASS_DESCRIPTOR)
// Required to check if the playback speed menu is currently shown. // Required to check if the playback speed menu is currently shown.
addLithoFilter(FILTER_CLASS_DESCRIPTOR) addLithoFilter(FILTER_CLASS_DESCRIPTOR)
// endregion
// region Custom tap and hold 2x speed. // region Custom tap and hold 2x speed.
if (is_19_25_or_greater) { if (is_19_25_or_greater) {

View File

@@ -3,10 +3,33 @@ package app.revanced.patches.youtube.video.speed.custom
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.iface.reference.StringReference
internal val getOldPlaybackSpeedsFingerprint = fingerprint {
parameters("[L", "I")
strings("menu_item_playback_speed")
}
internal val showOldPlaybackSpeedMenuFingerprint = fingerprint {
literal { speedUnavailableId }
}
internal val showOldPlaybackSpeedMenuExtensionFingerprint = fingerprint {
custom { method, classDef ->
method.name == "showOldPlaybackSpeedMenu" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
}
}
internal val speedArrayGeneratorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("[L")
parameters("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;")
strings("0.0#")
}
internal val speedLimiterFingerprint = fingerprint { internal val speedLimiterFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V") returns("V")

View File

@@ -32,7 +32,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstructio
import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.Reference import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.EnumSet import java.util.EnumSet
@@ -171,6 +174,79 @@ internal val Instruction.isBranchInstruction: Boolean
internal val Instruction.isReturnInstruction: Boolean internal val Instruction.isReturnInstruction: Boolean
get() = this.opcode in returnOpcodes get() = this.opcode in returnOpcodes
/**
* Find the instruction index used for a toString() StringBuilder write of a given String name.
*
* @param fieldName The name of the field to find. Partial matches are allowed.
*/
private fun Method.findInstructionIndexFromToString(fieldName: String) : Int {
val stringIndex = indexOfFirstInstruction {
val reference = getReference<StringReference>()
reference?.string?.contains(fieldName) == true
}
if (stringIndex < 0) {
throw IllegalArgumentException("Could not find usage of string: '$fieldName'")
}
val stringRegister = getInstruction<OneRegisterInstruction>(stringIndex).registerA
// Find use of the string with a StringBuilder.
val stringUsageIndex = indexOfFirstInstruction(stringIndex) {
val reference = getReference<MethodReference>()
reference?.definingClass == "Ljava/lang/StringBuilder;" &&
(this as? FiveRegisterInstruction)?.registerD == stringRegister
}
if (stringUsageIndex < 0) {
throw IllegalArgumentException("Could not find StringBuilder usage in: $this")
}
// Find the next usage of StringBuilder, which should be the desired field.
val fieldUsageIndex = indexOfFirstInstruction(stringUsageIndex + 1) {
val reference = getReference<MethodReference>()
reference?.definingClass == "Ljava/lang/StringBuilder;" && reference.name == "append"
}
if (fieldUsageIndex < 0) {
// Should never happen.
throw IllegalArgumentException("Could not find StringBuilder append usage in: $this")
}
val fieldUsageRegister = getInstruction<FiveRegisterInstruction>(fieldUsageIndex).registerD
// Look backwards up the method to find the instruction that sets the register.
var fieldSetIndex = indexOfFirstInstructionReversedOrThrow(fieldUsageIndex - 1) {
fieldUsageRegister == writeRegister
}
// If the field is a method call, then adjust from MOVE_RESULT to the method call.
val fieldSetOpcode = getInstruction(fieldSetIndex).opcode
if (fieldSetOpcode == MOVE_RESULT ||
fieldSetOpcode == MOVE_RESULT_WIDE ||
fieldSetOpcode == MOVE_RESULT_OBJECT) {
fieldSetIndex--
}
return fieldSetIndex
}
/**
* Find the method used for a toString() StringBuilder write of a given String name.
*
* @param fieldName The name of the field to find. Partial matches are allowed.
*/
context(BytecodePatchContext)
internal fun Method.findMethodFromToString(fieldName: String) : MutableMethod {
val methodUsageIndex = findInstructionIndexFromToString(fieldName)
return navigate(this).to(methodUsageIndex).stop()
}
/**
* Find the field used for a toString() StringBuilder write of a given String name.
*
* @param fieldName The name of the field to find. Partial matches are allowed.
*/
internal fun Method.findFieldFromToString(fieldName: String) : FieldReference {
val methodUsageIndex = findInstructionIndexFromToString(fieldName)
return getInstruction<ReferenceInstruction>(methodUsageIndex).getReference<FieldReference>()!!
}
/** /**
* Adds public [AccessFlags] and removes private and protected flags (if present). * Adds public [AccessFlags] and removes private and protected flags (if present).
*/ */
@@ -594,7 +670,7 @@ fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfF
/** /**
* Get the index of matching instruction, * Get the index of matching instruction,
* starting from and [startIndex] and searching down. * starting from [startIndex] and searching down.
* *
* @param startIndex Optional starting index to search down from. Searching includes the start index. * @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return The index of the instruction. * @return The index of the instruction.
@@ -617,7 +693,7 @@ fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int = i
/** /**
* Get the index of matching instruction, * Get the index of matching instruction,
* starting from and [startIndex] and searching down. * starting from [startIndex] and searching down.
* *
* @param startIndex Optional starting index to search down from. Searching includes the start index. * @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return The index of the instruction. * @return The index of the instruction.

View File

@@ -40,7 +40,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch"> <patch id="layout.hide.general.hideLayoutComponentsPatch">
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
<!-- 'Show more' should be translated with the same localized wording that YouTube displays. <!-- 'Show more' should be translated with the same localized wording that YouTube displays.
This button usually appears when searching for a YT creator. --> This button usually appears when searching for a YT creator. -->
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. --> <!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="ad.general.hideAdsResourcePatch"> <patch id="ad.general.hideAdsResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
</patch> </patch>
<patch id="ad.getpremium.hideGetPremiumPatch"> <patch id="ad.getpremium.hideGetPremiumPatch">
</patch> </patch>
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch"> <patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch> </patch>
<patch id="interaction.downloads.downloadsResourcePatch"> <patch id="interaction.downloads.downloadsResourcePatch">
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. --> <!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch"> <patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. --> <!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
<patch id="layout.formfactor.changeFormFactorPatch"> <patch id="layout.formfactor.changeFormFactorPatch">
</patch> </patch>
<patch id="layout.spoofappversion.spoofAppVersionPatch"> <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. -->
</patch> </patch>
<patch id="layout.startpage.changeStartPagePatch"> <patch id="layout.startpage.changeStartPagePatch">
</patch> </patch>
@@ -224,6 +222,8 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>
<patch id="video.speed.remember.rememberPlaybackSpeedPatch"> <patch id="video.speed.remember.rememberPlaybackSpeedPatch">

View File

@@ -40,7 +40,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch"> <patch id="layout.hide.general.hideLayoutComponentsPatch">
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
<!-- 'Show more' should be translated with the same localized wording that YouTube displays. <!-- 'Show more' should be translated with the same localized wording that YouTube displays.
This button usually appears when searching for a YT creator. --> This button usually appears when searching for a YT creator. -->
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. --> <!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="ad.general.hideAdsResourcePatch"> <patch id="ad.general.hideAdsResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
</patch> </patch>
<patch id="ad.getpremium.hideGetPremiumPatch"> <patch id="ad.getpremium.hideGetPremiumPatch">
</patch> </patch>
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch"> <patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch> </patch>
<patch id="interaction.downloads.downloadsResourcePatch"> <patch id="interaction.downloads.downloadsResourcePatch">
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. --> <!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch"> <patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. --> <!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
<patch id="layout.formfactor.changeFormFactorPatch"> <patch id="layout.formfactor.changeFormFactorPatch">
</patch> </patch>
<patch id="layout.spoofappversion.spoofAppVersionPatch"> <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. -->
</patch> </patch>
<patch id="layout.startpage.changeStartPagePatch"> <patch id="layout.startpage.changeStartPagePatch">
</patch> </patch>
@@ -224,6 +222,8 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>
<patch id="video.speed.remember.rememberPlaybackSpeedPatch"> <patch id="video.speed.remember.rememberPlaybackSpeedPatch">

View File

@@ -137,7 +137,7 @@ Second \"item\" text"</string>
<string name="revanced_debug_logs_disabled">ØĒŲ… ØĒØšØˇŲŠŲ„ ØĒØŗØŦŲŠŲ„Ø§ØĒ ØĒØĩØ­ŲŠØ­ Ø§Ų„ØŖØŽØˇØ§ØĄ</string> <string name="revanced_debug_logs_disabled">ØĒŲ… ØĒØšØˇŲŠŲ„ ØĒØŗØŦŲŠŲ„Ø§ØĒ ØĒØĩØ­ŲŠØ­ Ø§Ų„ØŖØŽØˇØ§ØĄ</string>
<string name="revanced_debug_logs_none_found">Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ ØŗØŦŲ„Ø§ØĒ</string> <string name="revanced_debug_logs_none_found">Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ ØŗØŦŲ„Ø§ØĒ</string>
<string name="revanced_debug_logs_copied_to_clipboard">ØĒŲ… Ų†ØŗØŽ Ø§Ų„ØŗØŦŲ„Ø§ØĒ</string> <string name="revanced_debug_logs_copied_to_clipboard">ØĒŲ… Ų†ØŗØŽ Ø§Ų„ØŗØŦŲ„Ø§ØĒ</string>
<string name="revanced_debug_logs_failed_to_export">ŲØ´Ų„ ØĒØĩØ¯ŲŠØą Ø§Ų„ØŗØŦŲ„Ø§ØĒ: $s</string> <string name="revanced_debug_logs_failed_to_export">ŲØ´Ų„ ØĒØĩØ¯ŲŠØą Ø§Ų„ØŗØŦŲ„Ø§ØĒ: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Ų…ØŗØ­ ØŗØŦŲ„Ø§ØĒ ØĒØĩØ­ŲŠØ­ Ø§Ų„ØŖØŽØˇØ§ØĄ</string> <string name="revanced_debug_logs_clear_buffer_title">Ų…ØŗØ­ ØŗØŦŲ„Ø§ØĒ ØĒØĩØ­ŲŠØ­ Ø§Ų„ØŖØŽØˇØ§ØĄ</string>
<string name="revanced_debug_logs_clear_buffer_summary">ŲŠŲ…ØŗØ­ ØŦŲ…ŲŠØš ØŗØŦŲ„Ø§ØĒ ØĒØĩØ­ŲŠØ­ ØŖØŽØˇØ§ØĄ ReVanced Ø§Ų„Ų…ØŽØ˛Ų†ØŠ</string> <string name="revanced_debug_logs_clear_buffer_summary">ŲŠŲ…ØŗØ­ ØŦŲ…ŲŠØš ØŗØŦŲ„Ø§ØĒ ØĒØĩØ­ŲŠØ­ ØŖØŽØˇØ§ØĄ ReVanced Ø§Ų„Ų…ØŽØ˛Ų†ØŠ</string>
<string name="revanced_debug_logs_clear_toast">ØĒŲ… Ų…ØŗØ­ Ø§Ų„ØŗØŦŲ„Ø§ØĒ</string> <string name="revanced_debug_logs_clear_toast">ØĒŲ… Ų…ØŗØ­ Ø§Ų„ØŗØŦŲ„Ø§ØĒ</string>
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_expandable_card_title">ØĨØŽŲØ§ØĄ Ø§Ų„Ø¨ØˇØ§Ų‚ØŠ Ø§Ų„Ų‚Ø§Ø¨Ų„ØŠ Ų„Ų„ØĒŲˆØŗŲŠØš</string> <string name="revanced_hide_expandable_card_title">ØĨØŽŲØ§ØĄ Ø§Ų„Ø¨ØˇØ§Ų‚ØŠ Ø§Ų„Ų‚Ø§Ø¨Ų„ØŠ Ų„Ų„ØĒŲˆØŗŲŠØš</string>
<string name="revanced_hide_expandable_card_summary_on">Ø§Ų„Ø¨ØˇØ§Ų‚ØŠ Ø§Ų„Ų‚Ø§Ø¨Ų„ØŠ Ų„Ų„ØĒŲˆØŗŲŠØš ØŖØŗŲŲ„ Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠØŠ</string> <string name="revanced_hide_expandable_card_summary_on">Ø§Ų„Ø¨ØˇØ§Ų‚ØŠ Ø§Ų„Ų‚Ø§Ø¨Ų„ØŠ Ų„Ų„ØĒŲˆØŗŲŠØš ØŖØŗŲŲ„ Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠØŠ</string>
<string name="revanced_hide_expandable_card_summary_off">Ø§Ų„Ø¨ØˇØ§Ų‚ØŠ Ø§Ų„Ų‚Ø§Ø¨Ų„ØŠ Ų„Ų„ØĒŲˆØŗŲŠØš ØŖØŗŲŲ„ Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØšØąŲˆØļØŠ</string> <string name="revanced_hide_expandable_card_summary_off">Ø§Ų„Ø¨ØˇØ§Ų‚ØŠ Ø§Ų„Ų‚Ø§Ø¨Ų„ØŠ Ų„Ų„ØĒŲˆØŗŲŠØš ØŖØŗŲŲ„ Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØšØąŲˆØļØŠ</string>
<string name="revanced_hide_feed_survey_title">ØĨØŽŲØ§ØĄ Ø§Ų„Ø§ØŗØĒØ¨ŲŠØ§Ų†Ø§ØĒ</string>
<string name="revanced_hide_feed_survey_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø§Ų„Ø§ØŗØĒØ¨ŲŠØ§Ų†Ø§ØĒ</string>
<string name="revanced_hide_feed_survey_summary_off">؊ØĒŲ… ØšØąØļ Ø§Ų„Ø§ØŗØĒØ¨ŲŠØ§Ų†Ø§ØĒ</string>
<string name="revanced_hide_floating_microphone_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą Ø§Ų„Ų…ŲŠŲƒØąŲˆŲŲˆŲ† Ø§Ų„ØšØ§ØĻŲ…</string> <string name="revanced_hide_floating_microphone_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą Ø§Ų„Ų…ŲŠŲƒØąŲˆŲŲˆŲ† Ø§Ų„ØšØ§ØĻŲ…</string>
<string name="revanced_hide_floating_microphone_button_summary_on">Ø˛Øą Ø§Ų„Ų…ŲŠŲƒØąŲˆŲŲˆŲ† Ø§Ų„ØšØ§ØĻŲ… ؁؊ Ø§Ų„Ø¨Ø­ØĢ Ų…ØŽŲŲŠ</string> <string name="revanced_hide_floating_microphone_button_summary_on">Ø˛Øą Ø§Ų„Ų…ŲŠŲƒØąŲˆŲŲˆŲ† Ø§Ų„ØšØ§ØĻŲ… ؁؊ Ø§Ų„Ø¨Ø­ØĢ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_floating_microphone_button_summary_off">ŲŠØ¸Ų‡Øą Ø˛Øą Ø§Ų„Ų…ŲŠŲƒØąŲˆŲŲˆŲ† Ø§Ų„ØšØ§ØĻŲ… ؁؊ Ø§Ų„Ø¨Ø­ØĢ</string> <string name="revanced_hide_floating_microphone_button_summary_off">ŲŠØ¸Ų‡Øą Ø˛Øą Ø§Ų„Ų…ŲŠŲƒØąŲˆŲŲˆŲ† Ø§Ų„ØšØ§ØĻŲ… ؁؊ Ø§Ų„Ø¨Ø­ØĢ</string>
@@ -192,7 +189,7 @@ Second \"item\" text"</string>
<string name="revanced_hide_movies_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø§Ų„ØŖŲŲ„Ø§Ų…</string> <string name="revanced_hide_movies_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø§Ų„ØŖŲŲ„Ø§Ų…</string>
<string name="revanced_hide_movies_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ø§Ų„ØŖŲŲ„Ø§Ų…</string> <string name="revanced_hide_movies_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ø§Ų„ØŖŲŲ„Ø§Ų…</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions 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_on">Ø˛Øą ØĨØ´ØšØ§ØąŲŠ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_notify_me_button_summary_off">Ø˛Øą ØĨØ´ØšØ§ØąŲŠ Ų…ØšØąŲˆØļ</string> <string name="revanced_hide_notify_me_button_summary_off">Ø˛Øą ØĨØ´ØšØ§ØąŲŠ Ų…ØšØąŲˆØļ</string>
@@ -204,6 +201,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_show_more_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą \'ØšØąØļ Ø§Ų„Ų…Ø˛ŲŠØ¯\'</string> <string name="revanced_hide_show_more_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą \'ØšØąØļ Ø§Ų„Ų…Ø˛ŲŠØ¯\'</string>
<string name="revanced_hide_show_more_button_summary_on">Ø˛Øą ØĨØ¸Ų‡Ø§Øą Ø§Ų„Ų…Ø˛ŲŠØ¯ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ Ų…ØŽŲŲŠ</string> <string name="revanced_hide_show_more_button_summary_on">Ø˛Øą ØĨØ¸Ų‡Ø§Øą Ø§Ų„Ų…Ø˛ŲŠØ¯ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_show_more_button_summary_off">Ø˛Øą ØĨØ¸Ų‡Ø§Øą Ø§Ų„Ų…Ø˛ŲŠØ¯ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ Ų…ØšØąŲˆØļ</string> <string name="revanced_hide_show_more_button_summary_off">Ø˛Øą ØĨØ¸Ų‡Ø§Øą Ø§Ų„Ų…Ø˛ŲŠØ¯ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ Ų…ØšØąŲˆØļ</string>
<string name="revanced_hide_surveys_title">ØĨØŽŲØ§ØĄ Ø§Ų„Ø§ØŗØĒØ¨ŲŠØ§Ų†Ø§ØĒ</string>
<string name="revanced_hide_surveys_summary_on">Ø§Ų„Ø§ØŗØĒØˇŲ„Ø§ØšØ§ØĒ Ų…ØŽŲŲŠØŠ</string>
<string name="revanced_hide_surveys_summary_off">Ø§Ų„Ø§ØŗØĒØˇŲ„Ø§ØšØ§ØĒ Ų…ØšØąŲˆØļØŠ</string>
<string name="revanced_hide_ticket_shelf_title">ØĨØŽŲØ§ØĄ ØąŲ Ø§Ų„ØĒØ°Ø§ŲƒØą</string> <string name="revanced_hide_ticket_shelf_title">ØĨØŽŲØ§ØĄ ØąŲ Ø§Ų„ØĒØ°Ø§ŲƒØą</string>
<string name="revanced_hide_ticket_shelf_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ ØąŲ Ø§Ų„ØĒØ°Ø§ŲƒØą</string> <string name="revanced_hide_ticket_shelf_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ ØąŲ Ø§Ų„ØĒØ°Ø§ŲƒØą</string>
<string name="revanced_hide_ticket_shelf_summary_off">؊ØĒŲ… ØšØąØļ ØąŲ Ø§Ų„ØĒØ°Ø§ŲƒØą</string> <string name="revanced_hide_ticket_shelf_summary_off">؊ØĒŲ… ØšØąØļ ØąŲ Ø§Ų„ØĒØ°Ø§ŲƒØą</string>
@@ -251,8 +251,8 @@ Second \"item\" text"</string>
<string name="revanced_hide_timed_reactions_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ ØąØ¯ŲˆØ¯ Ø§Ų„ŲØšŲ„ Ø§Ų„Ų…Ø¤Ų‚ØĒØŠ</string> <string name="revanced_hide_timed_reactions_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ ØąØ¯ŲˆØ¯ Ø§Ų„ŲØšŲ„ Ø§Ų„Ų…Ø¤Ų‚ØĒØŠ</string>
<string name="revanced_hide_timed_reactions_summary_off">؊ØĒŲ… ØšØąØļ ØąØ¯ŲˆØ¯ Ø§Ų„ŲØšŲ„ Ø§Ų„Ų…Ø¤Ų‚ØĒØŠ</string> <string name="revanced_hide_timed_reactions_summary_off">؊ØĒŲ… ØšØąØļ ØąØ¯ŲˆØ¯ Ø§Ų„ŲØšŲ„ Ø§Ų„Ų…Ø¤Ų‚ØĒØŠ</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">ØĨØŽŲØ§ØĄ \'Ų…Ų„ØŽØĩ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„Ø°ŲŠ ØĒŲ… ØĨŲ†Ø´Ø§Ø¤Ų‡ Ø¨ŲˆØ§ØŗØˇØŠ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ\'</string> <string name="revanced_hide_ai_generated_video_summary_section_title">ØĨØŽŲØ§ØĄ \'Ų…Ų„ØŽØĩ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„Ø°ŲŠ ØĒŲ… ØĨŲ†Ø´Ø§Ø¤Ų‡ Ø¨ŲˆØ§ØŗØˇØŠ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ\'</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ų…Ų„ØŽØĩ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_on">Ų‚ØŗŲ… Ų…Ų„ØŽØĩ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„Ø°ŲŠ ØĒŲ… ØĨŲ†Ø´Ø§Ø¤Ų‡ Ø¨ŲˆØ§ØŗØˇØŠ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ų…Ų„ØŽØĩ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_off">Ų‚ØŗŲ… Ų…Ų„ØŽØĩ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„Ø°ŲŠ ØĒŲ… ØĨŲ†Ø´Ø§Ø¤Ų‡ Ø¨ŲˆØ§ØŗØˇØŠ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ Ų…ØšØąŲˆØļ</string>
<string name="revanced_hide_ask_section_title">ØĨØŽŲØ§ØĄ \"Ask\"</string> <string name="revanced_hide_ask_section_title">ØĨØŽŲØ§ØĄ \"Ask\"</string>
<string name="revanced_hide_ask_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… \"Ask\"</string> <string name="revanced_hide_ask_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… \"Ask\"</string>
<string name="revanced_hide_ask_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… \"Ask\"</string> <string name="revanced_hide_ask_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… \"Ask\"</string>
@@ -280,19 +280,19 @@ Second \"item\" text"</string>
<string name="revanced_hide_description_components_screen_title">؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_description_components_screen_title">؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_hide_description_components_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲˆ ØšØąØļ Ų…ŲƒŲˆŲ†Ø§ØĒ ؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</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_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_title">ØĨØŽŲØ§ØĄ ؁؊ Ø§Ų„Ų…ŲˆØŦØ˛</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Ų…ØŽŲŲŠ ؁؊ Ø§Ų„Ų…ŲˆØŦØ˛</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> <string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Ų…ØšØąŲˆØļ ؁؊ Ø§Ų„Ų…ŲˆØŦØ˛</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">ØĨØŽŲØ§ØĄ ؁؊ Ø§Ų„ØŗØŦŲ„</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Ų…ØŽŲŲŠ ؁؊ Ø§Ų„ØŗØŦŲ„</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Ų…ØšØąŲˆØļ ؁؊ Ø§Ų„ØŗØŦŲ„</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">ØĨØŽŲØ§ØĄ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Ų…ØŽŲŲŠ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">ŲŠŲØšØąØļ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">ØĨØŽŲØ§ØĄ ؁؊ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_title">ØĨØŽŲØ§ØĄ ؁؊ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Ų…ØŽŲŲŠ ؁؊ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Ų…ØŽŲŲŠ ؁؊ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">ŲŠŲØšØąØļ ؁؊ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">ŲŠŲØšØąØļ ؁؊ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">ØĨØŽŲØ§ØĄ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Ų…ØŽŲŲŠ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">ŲŠŲØšØąØļ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">ØĨØŽŲØ§ØĄ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Ų…ØŽŲŲŠ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Ų…ØšØąŲˆØļ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string>
<string name="revanced_channel_screen_title">ØĩŲØ­ØŠ Ø§Ų„Ų‚Ų†Ø§ØŠ</string> <string name="revanced_channel_screen_title">ØĩŲØ­ØŠ Ø§Ų„Ų‚Ų†Ø§ØŠ</string>
<string name="revanced_channel_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲˆ ØĨØ¸Ų‡Ø§Øą Ų…ŲƒŲˆŲ†Ø§ØĒ ØĩŲØ­ØŠ Ø§Ų„Ų‚Ų†Ø§ØŠ</string> <string name="revanced_channel_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲˆ ØĨØ¸Ų‡Ø§Øą Ų…ŲƒŲˆŲ†Ø§ØĒ ØĩŲØ­ØŠ Ø§Ų„Ų‚Ų†Ø§ØŠ</string>
<!-- 'For You' should be translated using the same localized wording YouTube displays. --> <!-- 'For You' should be translated using the same localized wording YouTube displays. -->
@@ -315,12 +315,12 @@ Second \"item\" text"</string>
<string name="revanced_hide_visit_store_button_summary_off">Ø˛Øą Ø˛ŲŠØ§ØąØŠ Ø§Ų„Ų…ØĒØŦØą Ų…ØšØąŲˆØļ</string> <string name="revanced_hide_visit_store_button_summary_off">Ø˛Øą Ø˛ŲŠØ§ØąØŠ Ø§Ų„Ų…ØĒØŦØą Ų…ØšØąŲˆØļ</string>
<string name="revanced_comments_screen_title">Ø§Ų„ØĒØšŲ„ŲŠŲ‚Ø§ØĒ</string> <string name="revanced_comments_screen_title">Ø§Ų„ØĒØšŲ„ŲŠŲ‚Ø§ØĒ</string>
<string name="revanced_comments_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲˆ ØšØąØļ Ų…ŲƒŲˆŲ†Ø§ØĒ Ų‚ØŗŲ… Ø§Ų„ØĒØšŲ„ŲŠŲ‚Ø§ØĒ</string> <string name="revanced_comments_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲˆ ØšØąØļ Ų…ŲƒŲˆŲ†Ø§ØĒ Ų‚ØŗŲ… Ø§Ų„ØĒØšŲ„ŲŠŲ‚Ø§ØĒ</string>
<string name="revanced_hide_comments_ai_chat_summary_title">ØĨØŽŲØ§ØĄ Ų…Ų„ØŽØĩ Ų…Ø­Ø§Ø¯ØĢاØĒ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ</string> <string name="revanced_hide_comments_ai_chat_summary_title">ØĨØŽŲØ§ØĄ Ų…Ų„ØŽØĩ Ø§Ų„Ø¯ØąØ¯Ø´ØŠ Ø¨Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų…Ų„ØŽØĩ Ø§Ų„Ų…Ø­Ø§Ø¯ØĢاØĒ</string> <string name="revanced_hide_comments_ai_chat_summary_summary_on">Ų…Ų„ØŽØĩ Ø§Ų„Ø¯ØąØ¯Ø´ØŠ Ø¨Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">؊ØĒŲ… ØšØąØļ Ų…Ų„ØŽØĩ Ø§Ų„Ų…Ø­Ø§Ø¯ØĢاØĒ</string> <string name="revanced_hide_comments_ai_chat_summary_summary_off">Ų…Ų„ØŽØĩ Ø§Ų„Ø¯ØąØ¯Ø´ØŠ Ø¨Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ Ų…ØšØąŲˆØļ</string>
<string name="revanced_hide_comments_ai_summary_title">ØĨØŽŲØ§ØĄ Ų…Ų„ØŽØĩ ØĒØšŲ„ŲŠŲ‚Ø§ØĒ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ</string> <string name="revanced_hide_comments_ai_summary_title">ØĨØŽŲØ§ØĄ Ų…Ų„ØŽØĩ ØĒØšŲ„ŲŠŲ‚Ø§ØĒ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ</string>
<string name="revanced_hide_comments_ai_summary_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų…Ų„ØŽØĩ Ø§Ų„ØĒØšŲ„ŲŠŲ‚Ø§ØĒ</string> <string name="revanced_hide_comments_ai_summary_summary_on">Ų…Ų„ØŽØĩ ØĒØšŲ„ŲŠŲ‚Ø§ØĒ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_comments_ai_summary_summary_off">؊ØĒŲ… ØšØąØļ Ų…Ų„ØŽØĩ Ø§Ų„ØĒØšŲ„ŲŠŲ‚Ø§ØĒ</string> <string name="revanced_hide_comments_ai_summary_summary_off">Ų…Ų„ØŽØĩ ØĒØšŲ„ŲŠŲ‚Ø§ØĒ Ø§Ų„Ø°ŲƒØ§ØĄ Ø§Ų„Ø§ØĩØˇŲ†Ø§ØšŲŠ Ų…ØšØąŲˆØļ</string>
<string name="revanced_hide_comments_channel_guidelines_title">ØĨØŽŲØ§ØĄ ØĨØąØ´Ø§Ø¯Ø§ØĒ Ø§Ų„Ų‚Ų†Ø§ØŠ</string> <string name="revanced_hide_comments_channel_guidelines_title">ØĨØŽŲØ§ØĄ ØĨØąØ´Ø§Ø¯Ø§ØĒ Ø§Ų„Ų‚Ų†Ø§ØŠ</string>
<string name="revanced_hide_comments_channel_guidelines_summary_on">ØĨØąØ´Ø§Ø¯Ø§ØĒ Ø§Ų„Ų‚Ų†Ø§ØŠ Ų…ØŽŲŲŠØŠ</string> <string name="revanced_hide_comments_channel_guidelines_summary_on">ØĨØąØ´Ø§Ø¯Ø§ØĒ Ø§Ų„Ų‚Ų†Ø§ØŠ Ų…ØŽŲŲŠØŠ</string>
<string name="revanced_hide_comments_channel_guidelines_summary_off">ØĨØąØ´Ø§Ø¯Ø§ØĒ Ø§Ų„Ų‚Ų†Ø§ØŠ Ų…ØšØąŲˆØļØŠ</string> <string name="revanced_hide_comments_channel_guidelines_summary_off">ØĨØąØ´Ø§Ø¯Ø§ØĒ Ø§Ų„Ų‚Ų†Ø§ØŠ Ų…ØšØąŲˆØļØŠ</string>
@@ -419,7 +419,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_shopping_links_title">ØĨØŽŲØ§ØĄ ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØĒØŗŲˆŲ‚</string> <string name="revanced_hide_shopping_links_title">ØĨØŽŲØ§ØĄ ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØĒØŗŲˆŲ‚</string>
<string name="revanced_hide_shopping_links_summary_on">ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØĒØŗŲˆŲ‚ ؁؊ ؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠØŠ</string> <string name="revanced_hide_shopping_links_summary_on">ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØĒØŗŲˆŲ‚ ؁؊ ؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠØŠ</string>
<string name="revanced_hide_shopping_links_summary_off">؊ØĒŲ… ØšØąØļ ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØĒØŗŲˆŲ‚ ؁؊ ؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_shopping_links_summary_off">؊ØĒŲ… ØšØąØļ ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØĒØŗŲˆŲ‚ ؁؊ ؈Øĩ؁ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_view_products_banner_title">ØĨØŽŲØ§ØĄ Ų„Ø§ŲØĒØŠ \'ØšØąØļ Ø§Ų„Ų…Ų†ØĒØŦاØĒ\'</string> <string name="revanced_hide_view_products_banner_title">ØĨØŽŲØ§ØĄ Ų„Ø§ŲØĒØŠ \'ØšØąØļ Ø§Ų„Ų…Ų†ØĒØŦاØĒ\'</string>
<string name="revanced_hide_view_products_banner_summary_on">Ų„Ø§ŲØĒØŠ ØšØąØļ Ø§Ų„Ų…Ų†ØĒØŦاØĒ ؁؊ ØĒØąØ§ŲƒØ¨ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠØŠ</string> <string name="revanced_hide_view_products_banner_summary_on">Ų„Ø§ŲØĒØŠ ØšØąØļ Ø§Ų„Ų…Ų†ØĒØŦاØĒ ؁؊ ØĒØąØ§ŲƒØ¨ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠØŠ</string>
<string name="revanced_hide_view_products_banner_summary_off">Ų„Ø§ŲØĒØŠ ØšØąØļ Ø§Ų„Ų…Ų†ØĒØŦاØĒ ؁؊ ØĒØąØ§ŲƒØ¨ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØšØąŲˆØļØŠ</string> <string name="revanced_hide_view_products_banner_summary_off">Ų„Ø§ŲØĒØŠ ØšØąØļ Ø§Ų„Ų…Ų†ØĒØŦاØĒ ؁؊ ØĒØąØ§ŲƒØ¨ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØšØąŲˆØļØŠ</string>
@@ -453,7 +452,7 @@ Second \"item\" text"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">ØŗŲŠØĒŲ… ØšØąØļ Ų…ØąØ¨Øš Ø§Ų„Ø­ŲˆØ§Øą</string> <string name="revanced_remove_viewer_discretion_dialog_summary_off">ØŗŲŠØĒŲ… ØšØąØļ Ų…ØąØ¨Øš Ø§Ų„Ø­ŲˆØ§Øą</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">ŲˆŲ‡Ø°Ø§ Ų„Ø§ ؊ØĒØŦØ§ŲˆØ˛ Ų‚ŲŠŲˆØ¯ Ø§Ų„ØŗŲ†. Ø¨Ų„ ŲŠŲ‚Ø¨Ų„Ų‡Ø§ ØĒŲ„Ų‚Ø§ØĻŲŠŲ‹Ø§.</string> <string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">ŲˆŲ‡Ø°Ø§ Ų„Ø§ ؊ØĒØŦØ§ŲˆØ˛ Ų‚ŲŠŲˆØ¯ Ø§Ų„ØŗŲ†. Ø¨Ų„ ŲŠŲ‚Ø¨Ų„Ų‡Ø§ ØĒŲ„Ų‚Ø§ØĻŲŠŲ‹Ø§.</string>
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">ØĒØšØˇŲŠŲ„ ØĒØŽØˇŲŠ Ø§Ų„ŲØĩŲ„ Ø¨Ø§Ų„Ų†Ų‚Øą Ø§Ų„Ų…Ø˛Ø¯ŲˆØŦ</string> <string name="revanced_disable_chapter_skip_double_tap_title">ØĒØšØˇŲŠŲ„ ØĒØŽØˇŲŠ Ø§Ų„ŲØĩŲ„ Ø¨Ø§Ų„Ų†Ų‚Øą Ø§Ų„Ų…Ø˛Ø¯ŲˆØŦ</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Ų„Ø§ ŲŠŲ…ŲƒŲ† Ų„Ų„Ų†Ų‚Øą Ø§Ų„Ų…Ø˛Ø¯ŲˆØŦ Ų…ØˇŲ„Ų‚Ų‹Ø§ ØŖŲ† ŲŠØ¤Ø¯ŲŠ ØĨŲ„Ų‰ ØĒØŽØˇŲŠ Ø§Ų„ŲØĩŲ„ Ø§Ų„ØĒØ§Ų„ŲŠ/Ø§Ų„ØŗØ§Ø¨Ų‚</string> <string name="revanced_disable_chapter_skip_double_tap_summary_on">Ų„Ø§ ŲŠŲ…ŲƒŲ† Ų„Ų„Ų†Ų‚Øą Ø§Ų„Ų…Ø˛Ø¯ŲˆØŦ Ų…ØˇŲ„Ų‚Ų‹Ø§ ØŖŲ† ŲŠØ¤Ø¯ŲŠ ØĨŲ„Ų‰ ØĒØŽØˇŲŠ Ø§Ų„ŲØĩŲ„ Ø§Ų„ØĒØ§Ų„ŲŠ/Ø§Ų„ØŗØ§Ø¨Ų‚</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_off">ŲŠŲ…ŲƒŲ† Ų„Ų„Ų†Ų‚Øą Ø§Ų„Ų…Ø˛Ø¯ŲˆØŦ ØŖŲ† ŲŠØ¤Ø¯ŲŠ ØŖØ­ŲŠØ§Ų†Ų‹Ø§ ØĨŲ„Ų‰ ØĒØŽØˇŲŠ Ø§Ų„ŲØĩŲ„ Ø§Ų„ØĒØ§Ų„ŲŠ/Ø§Ų„ØŗØ§Ø¨Ų‚</string> <string name="revanced_disable_chapter_skip_double_tap_summary_off">ŲŠŲ…ŲƒŲ† Ų„Ų„Ų†Ų‚Øą Ø§Ų„Ų…Ø˛Ø¯ŲˆØŦ ØŖŲ† ŲŠØ¤Ø¯ŲŠ ØŖØ­ŲŠØ§Ų†Ų‹Ø§ ØĨŲ„Ų‰ ØĒØŽØˇŲŠ Ø§Ų„ŲØĩŲ„ Ø§Ų„ØĒØ§Ų„ŲŠ/Ø§Ų„ØŗØ§Ø¨Ų‚</string>
@@ -469,8 +468,15 @@ Second \"item\" text"</string>
<string name="revanced_external_downloader_action_button_summary_on">؊؁ØĒØ­ Ø˛Øą Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ ØŖØ¯Ø§ØŠ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ Ø§Ų„ØŽØ§ØąØŦŲŠØŠ</string> <string name="revanced_external_downloader_action_button_summary_on">؊؁ØĒØ­ Ø˛Øą Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ ØŖØ¯Ø§ØŠ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ Ø§Ų„ØŽØ§ØąØŦŲŠØŠ</string>
<string name="revanced_external_downloader_action_button_summary_off">؊؁ØĒØ­ Ø˛Øą Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ ØŖØ¯Ø§ØŠ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ Ø§Ų„ØŖØĩŲ„ŲŠØŠ Ø¯Ø§ØŽŲ„ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚</string> <string name="revanced_external_downloader_action_button_summary_off">؊؁ØĒØ­ Ø˛Øą Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ ØŖØ¯Ø§ØŠ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ Ø§Ų„ØŖØĩŲ„ŲŠØŠ Ø¯Ø§ØŽŲ„ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚</string>
<string name="revanced_external_downloader_name_title">Ø§ØŗŲ… Ø­Ø˛Ų…ØŠ ØŖØ¯Ø§ØŠ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„</string> <string name="revanced_external_downloader_name_title">Ø§ØŗŲ… Ø­Ø˛Ų…ØŠ ØŖØ¯Ø§ØŠ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„</string>
<string name="revanced_external_downloader_name_summary">Ø§ØŗŲ… Ø§Ų„Ø­Ø˛Ų…ØŠ Ų„ØĒØˇØ¨ŲŠŲ‚ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ Ø§Ų„ØŽØ§ØąØŦ؊ Ø§Ų„Ų…ØĢبØĒ Ų„Ø¯ŲŠŲƒØŒ Ų…ØĢŲ„ NewPipe ØŖŲˆ Seal</string> <string name="revanced_external_downloader_name_summary">Ø§ØŗŲ… Ø­Ø˛Ų…ØŠ ØĒØˇØ¨ŲŠŲ‚ Ø§Ų„ØĒŲ†Ø˛ŲŠŲ„ Ø§Ų„ØŽØ§ØąØŦ؊ Ø§Ų„Ų…ØĢبØĒ Ų„Ø¯ŲŠŲƒ</string>
<string name="revanced_external_downloader_other_item_hint">ØŖØ¯ØŽŲ„ Ø§ØŗŲ… Ø§Ų„Ø­Ø˛Ų…ØŠ</string>
<string name="revanced_external_downloader_other_item">ØŖØŽØąŲ‰</string>
<string name="revanced_external_downloader_not_found_title">Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ ØēŲŠØą Ų…ØĢبØĒ</string>
<string name="revanced_external_downloader_not_installed_warning">Ų„Ų… ؊ØĒŲ… ØĒØĢØ¨ŲŠØĒ %s . Ø§Ų„ØąØŦØ§ØĄ ØĒØĢØ¨ŲŠØĒŲ‡.</string> <string name="revanced_external_downloader_not_installed_warning">Ų„Ų… ؊ØĒŲ… ØĒØĢØ¨ŲŠØĒ %s . Ø§Ų„ØąØŦØ§ØĄ ØĒØĢØ¨ŲŠØĒŲ‡.</string>
<string name="revanced_external_downloader_package_not_found_warning">"ØĒØšØ°Øą Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ø§Ų„Ų…ØĢبØĒ Ø¨Ø§ØŗŲ… Ø§Ų„Ø­Ø˛Ų…ØŠ: %s
ØĒØŖŲƒØ¯ Ų…Ų† ØŖŲ† Ø§ØŗŲ… Ø§Ų„Ø­Ø˛Ų…ØŠ ØĩØ­ŲŠØ­ ŲˆØŖŲ† Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ų…ØĢبØĒ"</string>
<string name="revanced_external_downloader_empty_warning">Ų„Ø§ ŲŠŲ…ŲƒŲ† ØŖŲ† ŲŠŲƒŲˆŲ† Ø§ØŗŲ… Ø§Ų„Ø­Ø˛Ų…ØŠ ŲØ§ØąØēŲ‹Ø§</string>
</patch> </patch>
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch"> <patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">ØĒØšØˇŲŠŲ„ ØĨŲŠŲ…Ø§ØĄØŠ Ø§Ų„ØĒŲ…ØąŲŠØą Ø§Ų„Ø¯Ų‚ŲŠŲ‚ØŠ</string> <string name="revanced_disable_precise_seeking_gesture_title">ØĒØšØˇŲŠŲ„ ØĨŲŠŲ…Ø§ØĄØŠ Ø§Ų„ØĒŲ…ØąŲŠØą Ø§Ų„Ø¯Ų‚ŲŠŲ‚ØŠ</string>
@@ -730,27 +736,28 @@ Second \"item\" text"</string>
<string name="revanced_disable_rolling_number_animations_summary_off">ؚدد Ų…ØąØ§ØĒ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ ŲˆØ§Ų„ØĨØšØŦاباØĒ Ų…ØĒØ­ØąŲƒØŠ</string> <string name="revanced_disable_rolling_number_animations_summary_off">ؚدد Ų…ØąØ§ØĒ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ ŲˆØ§Ų„ØĨØšØŦاباØĒ Ų…ØĒØ­ØąŲƒØŠ</string>
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<string name="revanced_hide_seekbar_title">ØĨØŽŲØ§ØĄ Ø´ØąŲŠØˇ Ø§Ų„ØĒŲ‚Ø¯Ų… ؁؊ Ų…Ø´ØēŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_seekbar_title">ØĨØŽŲØ§ØĄ Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… Ų…Ø´ØēŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_hide_seekbar_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_seekbar_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_hide_seekbar_summary_off">؊ØĒŲ… ØšØąØļ Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_hide_seekbar_summary_off">؊ØĒŲ… ØšØąØļ Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_hide_seekbar_thumbnail_title">ØĨØŽŲØ§ØĄ Ø´ØąŲŠØˇ Ø§Ų„ØĒŲ‚Ø¯Ų… ؁؊ Ų…ŲØĩŲ‘ŲŽØēŲŽØąØ§ØĒ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
<string name="revanced_hide_seekbar_thumbnail_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų…ØĩØēØąØŠ Ø´ØąŲŠØˇ Ø§Ų„ØĒŲ‚Ø¯Ų…</string> <string name="revanced_hide_seekbar_thumbnail_title">ØĨØŽŲØ§ØĄ Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… ØĩŲˆØą Ų…ØĩØēØąØŠ Ų„Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">؊ØĒŲ… ØšØąØļ Ų…ØĩØēØąØŠ Ø´ØąŲŠØˇ Ø§Ų„ØĒŲ‚Ø¯Ų…</string> <string name="revanced_hide_seekbar_thumbnail_summary_on">Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… ØĩŲˆØą Ų…ØĩØēØąØŠ Ų„Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØŽŲŲŠ</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">Ø´ØąŲŠØˇ ØĒŲ‚Ø¯Ų… ØĩŲˆØą Ų…ØĩØēØąØŠ Ų„Ų„ŲŲŠØ¯ŲŠŲˆ Ų…ØšØąŲˆØļ</string>
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<string name="revanced_shorts_player_screen_title">Ų…Ø´ØēŲ„ Shorts</string> <string name="revanced_shorts_player_screen_title">Ų…Ø´ØēŲ„ Shorts</string>
<string name="revanced_shorts_player_screen_summary">ØĨØŽŲØ§ØĄ ØŖŲˆ ØšØąØļ Ø§Ų„Ų…ŲƒŲˆŲ†Ø§ØĒ ؁؊ Ų…Ø´ØēŲ„ Shorts</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. --> <!-- '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_title">ØĨØŽŲØ§ØĄ Shorts ؁؊ Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ</string>
<string name="revanced_hide_shorts_home_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string> <string name="revanced_hide_shorts_home_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string>
<string name="revanced_hide_shorts_home_summary_off">Ų…ØšØąŲˆØļØŠ ؁؊ Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string> <string name="revanced_hide_shorts_home_summary_off">Ų…ØšØąŲˆØļØŠ ؁؊ Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ ذاØĒ Ø§Ų„ØĩŲ„ØŠ</string>
<string name="revanced_hide_shorts_search_title">ØĨØŽŲØ§ØĄ Shorts ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_shorts_search_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_shorts_search_summary_off">ØĒŲØšØąØļ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</string>
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. --> <!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
<string name="revanced_hide_shorts_subscriptions_title">ØĨØŽŲØ§ØĄ Shorts ؁؊ ØŽŲ„Ø§ØĩØŠ Ø§Ų„Ø§Ø´ØĒØąØ§ŲƒØ§ØĒ</string> <string name="revanced_hide_shorts_subscriptions_title">ØĨØŽŲØ§ØĄ Shorts ؁؊ ØŽŲ„Ø§ØĩØŠ Ø§Ų„Ø§Ø´ØĒØąØ§ŲƒØ§ØĒ</string>
<string name="revanced_hide_shorts_subscriptions_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ ØŽŲ„Ø§ØĩØŠ Ø§Ų„Ø§Ø´ØĒØąØ§ŲƒØ§ØĒ</string> <string name="revanced_hide_shorts_subscriptions_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ ØŽŲ„Ø§ØĩØŠ Ø§Ų„Ø§Ø´ØĒØąØ§ŲƒØ§ØĒ</string>
<string name="revanced_hide_shorts_subscriptions_summary_off">Ų…ØšØąŲˆØļØŠ ؁؊ ØŽŲ„Ø§ØĩØŠ Ø§Ų„Ø§Ø´ØĒØąØ§ŲƒØ§ØĒ</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">Ų…ØŽŲŲŠØŠ ؁؊ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ</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_title">ØĨØŽŲØ§ØĄ Shorts ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string>
<string name="revanced_hide_shorts_history_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string> <string name="revanced_hide_shorts_history_summary_on">Ų…ØŽŲŲŠØŠ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string>
<string name="revanced_hide_shorts_history_summary_off">ØĒŲØšØąØļ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string> <string name="revanced_hide_shorts_history_summary_off">ØĒŲØšØąØļ ؁؊ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ</string>
@@ -1190,8 +1197,6 @@ Second \"item\" text"</string>
ØŗŲŠØ¤Ø¯ŲŠ Ų‡Ø°Ø§ ØĨŲ„Ų‰ ØĒØēŲŠŲŠØą Ų…Ø¸Ų‡Øą ŲˆŲ…Ų…ŲŠØ˛Ø§ØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ØŒ ŲˆŲ„ŲƒŲ† Ų‚Ø¯ ØĒحدØĢ ØĒØŖØĢŲŠØąØ§ØĒ ØŦØ§Ų†Ø¨ŲŠØŠ ØēŲŠØą Ų…ØšØąŲˆŲØŠ. ØŗŲŠØ¤Ø¯ŲŠ Ų‡Ø°Ø§ ØĨŲ„Ų‰ ØĒØēŲŠŲŠØą Ų…Ø¸Ų‡Øą ŲˆŲ…Ų…ŲŠØ˛Ø§ØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ØŒ ŲˆŲ„ŲƒŲ† Ų‚Ø¯ ØĒحدØĢ ØĒØŖØĢŲŠØąØ§ØĒ ØŦØ§Ų†Ø¨ŲŠØŠ ØēŲŠØą Ų…ØšØąŲˆŲØŠ.
ØĨذا ØĒŲ… ØĨŲŠŲ‚Ø§Ų ØĒØ´ØēŲŠŲ„Ų‡ Ų„Ø§Ø­Ų‚Ų‹Ø§ØŒ Ų…Ų† Ø§Ų„Ų…ØŗØĒØ­ØŗŲ† Ų…ØŗØ­ Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ų„Ų…Ų†Øš Ø­Ø¯ŲˆØĢ ØŖØŽØˇØ§ØĄ ؁؊ ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų…."</string> ØĨذا ØĒŲ… ØĨŲŠŲ‚Ø§Ų ØĒØ´ØēŲŠŲ„Ų‡ Ų„Ø§Ø­Ų‚Ų‹Ø§ØŒ Ų…Ų† Ø§Ų„Ų…ØŗØĒØ­ØŗŲ† Ų…ØŗØ­ Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ų„Ų…Ų†Øš Ø­Ø¯ŲˆØĢ ØŖØŽØˇØ§ØĄ ؁؊ ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų…."</string>
<!-- 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. -->
<string name="revanced_spoof_app_version_target_title">Ø§Ų„Ų‡Ø¯Ų Ų…Ų† ØĒØēŲŠŲŠØą ØĨØĩØ¯Ø§Øą Ø§Ų„ØĒØˇØ¨ŲŠŲ‚</string> <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_1">19.35.36 - Ø§ØŗØĒؚاد؊ ØŖŲŠŲ‚ŲˆŲ†Ø§ØĒ Ų…Ø´ØēŲ„ Shorts Ø§Ų„Ų‚Ø¯ŲŠŲ…ØŠ</string>
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Ø§ØŗØĒؚاد؊ ØŖŲŠŲ‚ŲˆŲ†Ø§ØĒ Ø§Ų„ØĒŲ†Ų‚Ų„ Ø§Ų„Ų‚Ø¯ŲŠŲ…ØŠ</string> <string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Ø§ØŗØĒؚاد؊ ØŖŲŠŲ‚ŲˆŲ†Ø§ØĒ Ø§Ų„ØĒŲ†Ų‚Ų„ Ø§Ų„Ų‚Ø¯ŲŠŲ…ØŠ</string>
@@ -1460,10 +1465,18 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Ø§Ų„Ø˛Øą Ų…ØšØąŲˆØļ. Ø§Ų†Ų‚Øą Ų…Øš Ø§Ų„Ø§ØŗØĒŲ…ØąØ§Øą Ų„ØĨؚاد؊ ØļØ¨Øˇ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ ØĨŲ„Ų‰ Ø§Ų„ŲˆØļØš Ø§Ų„Ø§ŲØĒØąØ§Øļ؊</string> <string name="revanced_playback_speed_dialog_button_summary_on">Ø§Ų„Ø˛Øą Ų…ØšØąŲˆØļ. Ø§Ų†Ų‚Øą Ų…Øš Ø§Ų„Ø§ØŗØĒŲ…ØąØ§Øą Ų„ØĨؚاد؊ ØļØ¨Øˇ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ ØĨŲ„Ų‰ Ø§Ų„ŲˆØļØš Ø§Ų„Ø§ŲØĒØąØ§Øļ؊</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Ų„Ø§ ؊ØĒŲ… ØšØąØļ Ø§Ų„Ø˛Øą</string> <string name="revanced_playback_speed_dialog_button_summary_off">Ų„Ø§ ؊ØĒŲ… ØšØąØļ Ø§Ų„Ø˛Øą</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
<string name="revanced_video_quality_dialog_button_title">ØšØąØļ Ø˛Øą ØŦŲˆØ¯ØŠ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_video_quality_dialog_button_summary_on">Ø§Ų„Ø˛Øą Ų…ØšØąŲˆØļ. Ø§Ų†Ų‚Øą Ų…Øš Ø§Ų„Ø§ØŗØĒŲ…ØąØ§Øą Ų„ØĨؚاد؊ ØĒØšŲŠŲŠŲ† Ø§Ų„ØŦŲˆØ¯ØŠ ØĨŲ„Ų‰ Ø§Ų„Ø§ŲØĒØąØ§Øļ؊</string>
<string name="revanced_video_quality_dialog_button_summary_off">Ø§Ų„Ø˛Øą ØēŲŠØą Ų…ØšØąŲˆØļ</string>
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string> <string name="revanced_custom_speed_menu_title">Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string>
<string name="revanced_custom_speed_menu_summary_on">؊ØĒŲ… ØšØąØļ Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string> <string name="revanced_custom_speed_menu_summary_on">؊ØĒŲ… ØšØąØļ Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string>
<string name="revanced_custom_speed_menu_summary_off">Ų„Ø§ ؊ØĒŲ… ØšØąØļ Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string> <string name="revanced_custom_speed_menu_summary_off">Ų„Ø§ ؊ØĒŲ… ØšØąØļ Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string>
<string name="revanced_restore_old_speed_menu_title">Ø§ØŗØĒؚاد؊ Ų‚Ø§ØĻŲ…ØŠ ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų‚Ø¯ŲŠŲ…ØŠ</string>
<string name="revanced_restore_old_speed_menu_summary_on">Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØŗØąØšØŠ Ø§Ų„Ų‚Ø¯ŲŠŲ…ØŠ Ų…ØšØąŲˆØļØŠ</string>
<string name="revanced_restore_old_speed_menu_summary_off">Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØŗØąØšØŠ Ø§Ų„Ø­Ø¯ŲŠØĢØŠ Ų…ØšØąŲˆØļØŠ</string>
<string name="revanced_custom_playback_speeds_title">ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string> <string name="revanced_custom_playback_speeds_title">ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string>
<string name="revanced_custom_playback_speeds_summary">ØĨØļØ§ŲØŠ ØŖŲˆ ØĒØēŲŠŲŠØą ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string> <string name="revanced_custom_playback_speeds_summary">ØĨØļØ§ŲØŠ ØŖŲˆ ØĒØēŲŠŲŠØą ØŗØąØšØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ</string>
<string name="revanced_custom_playback_speeds_invalid">؊ØŦب ØŖŲ† ØĒŲƒŲˆŲ† ØŗØąØšØ§ØĒ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ ØŖŲ‚Ų„ Ų…Ų† %s</string> <string name="revanced_custom_playback_speeds_invalid">؊ØŦب ØŖŲ† ØĒŲƒŲˆŲ† ØŗØąØšØ§ØĒ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų…ØŽØĩØĩØŠ ØŖŲ‚Ų„ Ų…Ų† %s</string>

View File

@@ -40,7 +40,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch"> <patch id="layout.hide.general.hideLayoutComponentsPatch">
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
<!-- 'Show more' should be translated with the same localized wording that YouTube displays. <!-- 'Show more' should be translated with the same localized wording that YouTube displays.
This button usually appears when searching for a YT creator. --> This button usually appears when searching for a YT creator. -->
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. --> <!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="ad.general.hideAdsResourcePatch"> <patch id="ad.general.hideAdsResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
</patch> </patch>
<patch id="ad.getpremium.hideGetPremiumPatch"> <patch id="ad.getpremium.hideGetPremiumPatch">
</patch> </patch>
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch"> <patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch> </patch>
<patch id="interaction.downloads.downloadsResourcePatch"> <patch id="interaction.downloads.downloadsResourcePatch">
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. --> <!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch"> <patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. --> <!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
<patch id="layout.formfactor.changeFormFactorPatch"> <patch id="layout.formfactor.changeFormFactorPatch">
</patch> </patch>
<patch id="layout.spoofappversion.spoofAppVersionPatch"> <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. -->
</patch> </patch>
<patch id="layout.startpage.changeStartPagePatch"> <patch id="layout.startpage.changeStartPagePatch">
</patch> </patch>
@@ -226,6 +224,8 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>
<patch id="video.speed.remember.rememberPlaybackSpeedPatch"> <patch id="video.speed.remember.rememberPlaybackSpeedPatch">

View File

@@ -137,7 +137,7 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_debug_logs_disabled">Sazlama qeydi qapalÄądÄąr</string> <string name="revanced_debug_logs_disabled">Sazlama qeydi qapalÄądÄąr</string>
<string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string> <string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string>
<string name="revanced_debug_logs_copied_to_clipboard">Qeydlər kÃļçÃŧrÃŧldÃŧ</string> <string name="revanced_debug_logs_copied_to_clipboard">Qeydlər kÃļçÃŧrÃŧldÃŧ</string>
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: $s</string> <string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string> <string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string>
<string name="revanced_debug_logs_clear_buffer_summary">SaxlanÄąlan bÃŧtÃŧn ReVanced sazlama qeydlərini təmizləyir</string> <string name="revanced_debug_logs_clear_buffer_summary">SaxlanÄąlan bÃŧtÃŧn ReVanced sazlama qeydlərini təmizləyir</string>
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string> <string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
@@ -164,9 +164,6 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_hide_expandable_card_title">Genişlənən kartÄą gizlət</string> <string name="revanced_hide_expandable_card_title">Genişlənən kartÄą gizlət</string>
<string name="revanced_hide_expandable_card_summary_on">VideolarÄąn aşağısÄąnda genişlənən kart gizlidir</string> <string name="revanced_hide_expandable_card_summary_on">VideolarÄąn aşağısÄąnda genişlənən kart gizlidir</string>
<string name="revanced_hide_expandable_card_summary_off">VideolarÄąn altÄąnda genişlənən kart gÃļrÃŧnÃŧr</string> <string name="revanced_hide_expandable_card_summary_off">VideolarÄąn altÄąnda genişlənən kart gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_feed_survey_title">Axın sorğuların gizlət</string>
<string name="revanced_hide_feed_survey_summary_on">Axın sorğuları gizlidir</string>
<string name="revanced_hide_feed_survey_summary_off">AxÄąn sorğularÄą gÃļstərilir</string>
<string name="revanced_hide_floating_microphone_button_title">Üzən mikrofon dÃŧyməsini gizlət</string> <string name="revanced_hide_floating_microphone_button_title">Üzən mikrofon dÃŧyməsini gizlət</string>
<string name="revanced_hide_floating_microphone_button_summary_on">AxtarÄąÅŸda Ãŧzən mikrofon dÃŧyməsi gizlidir</string> <string name="revanced_hide_floating_microphone_button_summary_on">AxtarÄąÅŸda Ãŧzən mikrofon dÃŧyməsi gizlidir</string>
<string name="revanced_hide_floating_microphone_button_summary_off">Üzən mikrofon dÃŧyməsi axtarÄąÅŸda gÃļstərilir</string> <string name="revanced_hide_floating_microphone_button_summary_off">Üzən mikrofon dÃŧyməsi axtarÄąÅŸda gÃļstərilir</string>
@@ -192,7 +189,7 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_hide_movies_section_summary_on">Filmlər bÃļlməsi gizlidir</string> <string name="revanced_hide_movies_section_summary_on">Filmlər bÃļlməsi gizlidir</string>
<string name="revanced_hide_movies_section_summary_off">Filmlər bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_movies_section_summary_off">Filmlər bÃļlməsi gÃļstərilir</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
<string name="revanced_hide_notify_me_button_title">\"Mənə bildir\" dÃŧyməsini gizlət</string> <string name="revanced_hide_notify_me_button_title">\"Mənə bildir\" dÃŧyməsini gizlət</string>
<string name="revanced_hide_notify_me_button_summary_on">Mənə bildir dÃŧyməsi gizlidir</string> <string name="revanced_hide_notify_me_button_summary_on">Mənə bildir dÃŧyməsi gizlidir</string>
<string name="revanced_hide_notify_me_button_summary_off">Mənə bildir dÃŧyməsi gÃļrÃŧnÃŧr</string> <string name="revanced_hide_notify_me_button_summary_off">Mənə bildir dÃŧyməsi gÃļrÃŧnÃŧr</string>
@@ -204,6 +201,9 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_hide_show_more_button_title">\'Daha çox gÃļstər\' dÃŧyməsini gizlət</string> <string name="revanced_hide_show_more_button_title">\'Daha çox gÃļstər\' dÃŧyməsini gizlət</string>
<string name="revanced_hide_show_more_button_summary_on">Daha çox gÃļstər dÃŧyməsi axtarÄąÅŸ nəticələrində gizlidir</string> <string name="revanced_hide_show_more_button_summary_on">Daha çox gÃļstər dÃŧyməsi axtarÄąÅŸ nəticələrində gizlidir</string>
<string name="revanced_hide_show_more_button_summary_off">Daha çox gÃļstər dÃŧyməsi axtarÄąÅŸ nəticələrində gÃļrÃŧnÃŧr</string> <string name="revanced_hide_show_more_button_summary_off">Daha çox gÃļstər dÃŧyməsi axtarÄąÅŸ nəticələrində gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_surveys_title">Sorğuları gizlət</string>
<string name="revanced_hide_surveys_summary_on">Sorğular gizlədilib</string>
<string name="revanced_hide_surveys_summary_off">Sorğular gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_ticket_shelf_title">Bilet bÃļlməsin gizlət</string> <string name="revanced_hide_ticket_shelf_title">Bilet bÃļlməsin gizlət</string>
<string name="revanced_hide_ticket_shelf_summary_on">Bilet bÃļlməsi gizlidir</string> <string name="revanced_hide_ticket_shelf_summary_on">Bilet bÃļlməsi gizlidir</string>
<string name="revanced_hide_ticket_shelf_summary_off">Bilet bÃļlməsi gÃļrÃŧnÃŧr</string> <string name="revanced_hide_ticket_shelf_summary_off">Bilet bÃļlməsi gÃļrÃŧnÃŧr</string>
@@ -251,8 +251,8 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_hide_timed_reactions_summary_on">ZamanlanmÄąÅŸ reaksiyalar gizlədilir</string> <string name="revanced_hide_timed_reactions_summary_on">ZamanlanmÄąÅŸ reaksiyalar gizlədilir</string>
<string name="revanced_hide_timed_reactions_summary_off">ZamanlanmÄąÅŸ reaksiyalar gÃļstərilir</string> <string name="revanced_hide_timed_reactions_summary_off">ZamanlanmÄąÅŸ reaksiyalar gÃļstərilir</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">\"AI ilə yaradÄąlan video xÃŧlasəsini\" gizlət</string> <string name="revanced_hide_ai_generated_video_summary_section_title">\"AI ilə yaradÄąlan video xÃŧlasəsini\" gizlət</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Video xÃŧlasə bÃļlməsi gizlədilib</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_on">Sİ ilə yaradÄąlan video xÃŧlasə bÃļlməsi gizlədilib</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Video xÃŧlasə bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_off">Sİ ilə yaradÄąlan video xÃŧlasə bÃļlməsi gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_ask_section_title">Soruş\'u Gizlət</string> <string name="revanced_hide_ask_section_title">Soruş\'u Gizlət</string>
<string name="revanced_hide_ask_section_summary_on">Soruş bÃļlməsi gizlidir</string> <string name="revanced_hide_ask_section_summary_on">Soruş bÃļlməsi gizlidir</string>
<string name="revanced_hide_ask_section_summary_off">\"Soruş\" bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_ask_section_summary_off">\"Soruş\" bÃļlməsi gÃļstərilir</string>
@@ -280,19 +280,19 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_hide_description_components_screen_title">Video təsviri</string> <string name="revanced_hide_description_components_screen_title">Video təsviri</string>
<string name="revanced_hide_description_components_screen_summary">Video təsviri elementlərini gizlət və ya gÃļstər</string> <string name="revanced_hide_description_components_screen_summary">Video təsviri elementlərini gizlət və ya gÃļstər</string>
<string name="revanced_hide_filter_bar_screen_title">Filtr çubuğu</string> <string name="revanced_hide_filter_bar_screen_title">Filtr çubuğu</string>
<string name="revanced_hide_filter_bar_screen_summary">AxÄąnlar, tarixçə, axtarÄąÅŸ nəticələri və əlaqəli videolarda filtr panelini gizlət və ya gÃļstər</string> <string name="revanced_hide_filter_bar_screen_summary">AxÄąnlar, əlaqəli videolar, axtarÄąÅŸ nəticələri və baxÄąÅŸ tarixçəsində filtr cərgəsin gizlət və ya gÃļstər</string>
<string name="revanced_hide_filter_bar_feed_in_feed_title">Axınlarda gizlət</string> <string name="revanced_hide_filter_bar_feed_in_feed_title">Axınlarda gizlət</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">AxÄąnlarda gizlidir</string> <string name="revanced_hide_filter_bar_feed_in_feed_summary_on">AxÄąnlarda gizlidir</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">AxÄąnlarda gÃļstər</string> <string name="revanced_hide_filter_bar_feed_in_feed_summary_off">AxÄąnlarda gÃļstər</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">Tarixçədə gizlət</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Tarixçədə gizlədilib</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Tarixçədə gÃļstərilib</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">AxtarÄąÅŸ nəticələrində gizlət</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">AxtarÄąÅŸ nəticələrində gizlədilib</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">AxtarÄąÅŸ nəticələrində gÃļstərilir</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Əlaqəli videolarda gizlət</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_title">Əlaqəli videolarda gizlət</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Əlaqəli videolarda gizlidir</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Əlaqəli videolarda gizlidir</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Əlaqəli videolarda gÃļrÃŧnÃŧr</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Əlaqəli videolarda gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">AxtarÄąÅŸ nəticələrində gizlət</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">AxtarÄąÅŸ nəticələrində gizlədilib</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">AxtarÄąÅŸ nəticələrində gÃļstərilir</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">BaxÄąÅŸ tarixçəsində gizlət</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">BaxÄąÅŸ tarixçəsində gizlədilib</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">BaxÄąÅŸ tarixçəsində gÃļrÃŧnÃŧr</string>
<string name="revanced_channel_screen_title">Kanal səhifəsi</string> <string name="revanced_channel_screen_title">Kanal səhifəsi</string>
<string name="revanced_channel_screen_summary">Kanal səhifə elementlərini gizlət və ya gÃļstər</string> <string name="revanced_channel_screen_summary">Kanal səhifə elementlərini gizlət və ya gÃļstər</string>
<!-- 'For You' should be translated using the same localized wording YouTube displays. --> <!-- 'For You' should be translated using the same localized wording YouTube displays. -->
@@ -315,12 +315,12 @@ GÃļzlənilməz hallardan xəbərdar olmayacaqsÄąnÄąz."</string>
<string name="revanced_hide_visit_store_button_summary_off">Mağazaya baxÄąn dÃŧyməsi gÃļrÃŧnÃŧr</string> <string name="revanced_hide_visit_store_button_summary_off">Mağazaya baxÄąn dÃŧyməsi gÃļrÃŧnÃŧr</string>
<string name="revanced_comments_screen_title">Şərhlər</string> <string name="revanced_comments_screen_title">Şərhlər</string>
<string name="revanced_comments_screen_summary">Şərhlər bÃļlməsi elementlərin gizlət və ya gÃļstər</string> <string name="revanced_comments_screen_summary">Şərhlər bÃļlməsi elementlərin gizlət və ya gÃļstər</string>
<string name="revanced_hide_comments_ai_chat_summary_title">AI SÃļhbət XÃŧlasəsini Gizlət</string> <string name="revanced_hide_comments_ai_chat_summary_title">Sİ sÃļhbət xÃŧlasəsini gizlət</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_on">SÃļhbət yekunu gizlidir </string> <string name="revanced_hide_comments_ai_chat_summary_summary_on">Sİ sÃļhbət xÃŧlasəsi gizlidir</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">SÃļhbət yekunu gÃļrÃŧnÃŧr</string> <string name="revanced_hide_comments_ai_chat_summary_summary_off">Sİ sÃļhbət xÃŧlasəsi gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_comments_ai_summary_title">AI ášĸərhlər XÃŧlasəsini Gizlət</string> <string name="revanced_hide_comments_ai_summary_title">AI ášĸərhlər XÃŧlasəsini Gizlət</string>
<string name="revanced_hide_comments_ai_summary_summary_on">ášĸərh yekunu gizlidir </string> <string name="revanced_hide_comments_ai_summary_summary_on">Sİ şərhlər xÃŧlasəsi gizlidir</string>
<string name="revanced_hide_comments_ai_summary_summary_off">Şərh yekunu gÃļrÃŧnÃŧr</string> <string name="revanced_hide_comments_ai_summary_summary_off">Sİ şərhlər xÃŧlasəsi gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_comments_channel_guidelines_title">Kanal təlimatlarını gizlət</string> <string name="revanced_hide_comments_channel_guidelines_title">Kanal təlimatlarını gizlət</string>
<string name="revanced_hide_comments_channel_guidelines_summary_on">Kanal təlimatları gizlidir</string> <string name="revanced_hide_comments_channel_guidelines_summary_on">Kanal təlimatları gizlidir</string>
<string name="revanced_hide_comments_channel_guidelines_summary_off">Kanal təlimatlarÄą gÃļrÃŧnÃŧr</string> <string name="revanced_hide_comments_channel_guidelines_summary_off">Kanal təlimatlarÄą gÃļrÃŧnÃŧr</string>
@@ -419,7 +419,6 @@ Bu xÃŧsusiyyət yalnÄąz kÃļhnə cihazlar ÃŧçÃŧn mÃļvcuddur"</string>
<string name="revanced_hide_shopping_links_title">AlÄąÅŸ-veriş linklərini gizlət</string> <string name="revanced_hide_shopping_links_title">AlÄąÅŸ-veriş linklərini gizlət</string>
<string name="revanced_hide_shopping_links_summary_on">AlÄąÅŸ-veriş linkləri video təsvirdə gizlidir</string> <string name="revanced_hide_shopping_links_summary_on">AlÄąÅŸ-veriş linkləri video təsvirdə gizlidir</string>
<string name="revanced_hide_shopping_links_summary_off">AlÄąÅŸ-veriş linkləri video təsvirdə gÃļrÃŧnÃŧr</string> <string name="revanced_hide_shopping_links_summary_off">AlÄąÅŸ-veriş linkləri video təsvirdə gÃļrÃŧnÃŧr</string>
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_view_products_banner_title">“Məhsullara baxın” panelin gizlət</string> <string name="revanced_hide_view_products_banner_title">“Məhsullara baxın” panelin gizlət</string>
<string name="revanced_hide_view_products_banner_summary_on">Məhsullara baxÄąÅŸ etiketi video ÃļrtÃŧyÃŧndə gizlidir</string> <string name="revanced_hide_view_products_banner_summary_on">Məhsullara baxÄąÅŸ etiketi video ÃļrtÃŧyÃŧndə gizlidir</string>
<string name="revanced_hide_view_products_banner_summary_off">Məhsullara baxÄąÅŸ etiketi video ÃļrtÃŧyÃŧndə gÃļrÃŧnÃŧr</string> <string name="revanced_hide_view_products_banner_summary_off">Məhsullara baxÄąÅŸ etiketi video ÃļrtÃŧyÃŧndə gÃļrÃŧnÃŧr</string>
@@ -453,7 +452,7 @@ Bu xÃŧsusiyyət yalnÄąz kÃļhnə cihazlar ÃŧçÃŧn mÃļvcuddur"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialoq gÃļstərilir</string> <string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialoq gÃļstərilir</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Bu, yaş məhdudiyyətini ÃļtÃŧrmÃŧr. Sadəcə birbaşa qəbul edir.</string> <string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Bu, yaş məhdudiyyətini ÃļtÃŧrmÃŧr. Sadəcə birbaşa qəbul edir.</string>
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">CÃŧt toxunuşla fəsil ÃļtÃŧrməsini qapat</string> <string name="revanced_disable_chapter_skip_double_tap_title">CÃŧt toxunuşla fəsil ÃļtÃŧrməsini qapat</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">CÃŧt toxunma heç vaxt nÃļvbəti/əvvəlki fəsilə keçidi zorlaya bilməz</string> <string name="revanced_disable_chapter_skip_double_tap_summary_on">CÃŧt toxunma heç vaxt nÃļvbəti/əvvəlki fəsilə keçidi zorlaya bilməz</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_off">CÃŧt toxunma bəzən nÃļvbəti/əvvəlki fəsilə keçidi zorlaya bilər</string> <string name="revanced_disable_chapter_skip_double_tap_summary_off">CÃŧt toxunma bəzən nÃļvbəti/əvvəlki fəsilə keçidi zorlaya bilər</string>
@@ -469,8 +468,15 @@ Bu xÃŧsusiyyət yalnÄąz kÃļhnə cihazlar ÃŧçÃŧn mÃļvcuddur"</string>
<string name="revanced_external_downloader_action_button_summary_on">YÃŧkləmə dÃŧyməsi, xarici yÃŧkləyicinizi aÃ§Äąr</string> <string name="revanced_external_downloader_action_button_summary_on">YÃŧkləmə dÃŧyməsi, xarici yÃŧkləyicinizi aÃ§Äąr</string>
<string name="revanced_external_downloader_action_button_summary_off">YÃŧkləmə dÃŧyməsi tətbiqə xas yÃŧkləyicini aÃ§Äąr</string> <string name="revanced_external_downloader_action_button_summary_off">YÃŧkləmə dÃŧyməsi tətbiqə xas yÃŧkləyicini aÃ§Äąr</string>
<string name="revanced_external_downloader_name_title">YÃŧkləyici paketi adÄą</string> <string name="revanced_external_downloader_name_title">YÃŧkləyici paketi adÄą</string>
<string name="revanced_external_downloader_name_summary">NewPipe və ya Seal kimi quraşdÄąrÄąlan xarici yÃŧkləmə tətbiqinizin paket adÄą</string> <string name="revanced_external_downloader_name_summary">QuraşdÄąrÄąlan xarici yÃŧkləyici tətbiqinizin paket adÄą</string>
<string name="revanced_external_downloader_other_item_hint">Paket adÄąnÄą yerləşdir</string>
<string name="revanced_external_downloader_other_item">Digər</string>
<string name="revanced_external_downloader_not_found_title">Tətbiq quraşdÄąrÄąlmayÄąb</string>
<string name="revanced_external_downloader_not_installed_warning">%s quraşdÄąrÄąlmayÄąb. LÃŧtfən, bunu quraşdÄąr.</string> <string name="revanced_external_downloader_not_installed_warning">%s quraşdÄąrÄąlmayÄąb. LÃŧtfən, bunu quraşdÄąr.</string>
<string name="revanced_external_downloader_package_not_found_warning">"Paket adÄą ilə quraşdÄąrÄąlan tətbiq tapÄąlmadÄą: %s
Paket adÄąnÄąn dÃŧzgÃŧn olduğun yoxla və tətbiqi quraşdÄąrÄąn"</string>
<string name="revanced_external_downloader_empty_warning">Paket adÄą boş ola bilməz</string>
</patch> </patch>
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch"> <patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">Dəqiq axtarÄąÅŸ jestini qapadÄąn</string> <string name="revanced_disable_precise_seeking_gesture_title">Dəqiq axtarÄąÅŸ jestini qapadÄąn</string>
@@ -730,27 +736,28 @@ Audio trek seçimin gÃļstərmək ÃŧçÃŧn \"Video axÄąnlarÄą saxtalaşdÄąr\"Äą iO
<string name="revanced_disable_rolling_number_animations_summary_off">SÃŧrÃŧşən say animasiyasÄą aÃ§ÄąqdÄąr</string> <string name="revanced_disable_rolling_number_animations_summary_off">SÃŧrÃŧşən say animasiyasÄą aÃ§ÄąqdÄąr</string>
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<string name="revanced_hide_seekbar_title">Video oynadÄącÄąda irəliləyiş cizgisin gizlə</string> <string name="revanced_hide_seekbar_title">Video oynadÄącÄą irəliləyiş cizgisin gizlət</string>
<string name="revanced_hide_seekbar_summary_on">Video oynadÄącÄą irəliləyiş cizgisi gizlidir</string> <string name="revanced_hide_seekbar_summary_on">Video oynadÄącÄą irəliləyiş cizgisi gizlidir</string>
<string name="revanced_hide_seekbar_summary_off">Video oynadÄącÄą irəliləyiş cizgisi gÃļstərilir</string> <string name="revanced_hide_seekbar_summary_off">Video oynadÄącÄą irəliləyiş cizgisi gÃļstərilir</string>
<string name="revanced_hide_seekbar_thumbnail_title">Video miniatÃŧrdə irəliləmə cizgisin gizlə</string> <!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
<string name="revanced_hide_seekbar_thumbnail_summary_on">MiniatÃŧr irəliləmə cizgisi gizlədilib</string> <string name="revanced_hide_seekbar_thumbnail_title">Video miniatÃŧr irəliləyiş cizgisin gizlət</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">MiniatÃŧr irəliləmə cizgisi gÃļstərilir</string> <string name="revanced_hide_seekbar_thumbnail_summary_on">Video miniatÃŧr irəliləyiş cizgisi gizlidir</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">Video miniatÃŧr irəliləyiş cizgisi gÃļrÃŧnÃŧr</string>
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<string name="revanced_shorts_player_screen_title">Shorts oynadÄącÄą</string> <string name="revanced_shorts_player_screen_title">Shorts oynadÄącÄą</string>
<string name="revanced_shorts_player_screen_summary">Shorts oynadÄącÄąda hissəcikləri gizlət və ya gÃļstər</string> <string name="revanced_shorts_player_screen_summary">Shorts oynadÄącÄą elementlərini gizlət və ya gÃļstər</string>
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. --> <!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
<string name="revanced_hide_shorts_home_title">Shorts-u Ev axınında gizlət</string> <string name="revanced_hide_shorts_home_title">Shorts-u Ev axınında gizlət</string>
<string name="revanced_hide_shorts_home_summary_on">Ev axını və əlaqəli videolarda gizlidir</string> <string name="revanced_hide_shorts_home_summary_on">Ev axını və əlaqəli videolarda gizlidir</string>
<string name="revanced_hide_shorts_home_summary_off">Ev axÄąnÄą və əlaqəli videolarda gÃļrÃŧnÃŧr</string> <string name="revanced_hide_shorts_home_summary_off">Ev axÄąnÄą və əlaqəli videolarda gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_shorts_search_title">AxtarÄąÅŸ nəticələrindəki \"Shorts\"u gizlət</string>
<string name="revanced_hide_shorts_search_summary_on">AxtarÄąÅŸ nəticələrində gizlidir</string>
<string name="revanced_hide_shorts_search_summary_off">AxtarÄąÅŸ nəticələrində gÃļrÃŧnÃŧr</string>
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. --> <!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
<string name="revanced_hide_shorts_subscriptions_title">Shorts-u Abunəliklər axınında gizlət</string> <string name="revanced_hide_shorts_subscriptions_title">Shorts-u Abunəliklər axınında gizlət</string>
<string name="revanced_hide_shorts_subscriptions_summary_on">Abunəliklər axınında gizlidir</string> <string name="revanced_hide_shorts_subscriptions_summary_on">Abunəliklər axınında gizlidir</string>
<string name="revanced_hide_shorts_subscriptions_summary_off">Abunəliklər axÄąnÄąnda gÃļrÃŧnÃŧr</string> <string name="revanced_hide_shorts_subscriptions_summary_off">Abunəliklər axÄąnÄąnda gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_shorts_search_title">AxtarÄąÅŸ nəticələrindəki \"Shorts\"u gizlət</string>
<string name="revanced_hide_shorts_search_summary_on">AxtarÄąÅŸ nəticələrində gizlidir</string>
<string name="revanced_hide_shorts_search_summary_off">AxtarÄąÅŸ nəticələrində gÃļrÃŧnÃŧr</string>
<string name="revanced_hide_shorts_history_title">BaxÄąÅŸ tarixçəsində Shorts-u gizlət</string> <string name="revanced_hide_shorts_history_title">BaxÄąÅŸ tarixçəsində Shorts-u gizlət</string>
<string name="revanced_hide_shorts_history_summary_on">BaxÄąÅŸ tarixçəsində gizlidir</string> <string name="revanced_hide_shorts_history_summary_on">BaxÄąÅŸ tarixçəsində gizlidir</string>
<string name="revanced_hide_shorts_history_summary_off">BaxÄąÅŸ tarixçəsində gÃļstərilib</string> <string name="revanced_hide_shorts_history_summary_off">BaxÄąÅŸ tarixçəsində gÃļstərilib</string>
@@ -1189,8 +1196,6 @@ Avtomobil tərtibatı
Bu tətbiqin gÃļrÃŧnÃŧşÃŧn və xÃŧsusiyyətlərin dəyişdirəcək, lakin bilinməyən yan təsirlər ola bilər. Bu tətbiqin gÃļrÃŧnÃŧşÃŧn və xÃŧsusiyyətlərin dəyişdirəcək, lakin bilinməyən yan təsirlər ola bilər.
Sonradan qapadÄąlarsa, UI səhvlərin Ãļnləmək ÃŧçÃŧn tətbiq məlumatlarÄąn silmək tÃļvsiyə olunur."</string> Sonradan qapadÄąlarsa, UI səhvlərin Ãļnləmək ÃŧçÃŧn tətbiq məlumatlarÄąn silmək tÃļvsiyə olunur."</string>
<!-- 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. -->
<string name="revanced_spoof_app_version_target_title">Saxta tətbiq versiyası hədəfi</string> <string name="revanced_spoof_app_version_target_title">Saxta tətbiq versiyası hədəfi</string>
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - KÃļhnə Shorts oynadÄącÄą işarələrin bərpa et</string> <string name="revanced_spoof_app_version_target_entry_1">19.35.36 - KÃļhnə Shorts oynadÄącÄą işarələrin bərpa et</string>
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - KÃļhnə fəaliyyət simvollarÄąn bərpa et</string> <string name="revanced_spoof_app_version_target_entry_2">19.01.34 - KÃļhnə fəaliyyət simvollarÄąn bərpa et</string>
@@ -1459,10 +1464,15 @@ Bunu aktivləşdirmə daha yÃŧksək video keyfiyyətləri əngəlin silə bilər
<string name="revanced_playback_speed_dialog_button_summary_on">DÃŧymə gÃļstərilir. Oynatma sÃŧrətin standart olaraq qaytarmaq ÃŧçÃŧn toxunub saxla</string> <string name="revanced_playback_speed_dialog_button_summary_on">DÃŧymə gÃļstərilir. Oynatma sÃŧrətin standart olaraq qaytarmaq ÃŧçÃŧn toxunub saxla</string>
<string name="revanced_playback_speed_dialog_button_summary_off">DÃŧymə gÃļstərilmir</string> <string name="revanced_playback_speed_dialog_button_summary_off">DÃŧymə gÃļstərilmir</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">Fərdi oynatma sÃŧrəti siyahÄąsÄą</string> <string name="revanced_custom_speed_menu_title">Fərdi oynatma sÃŧrəti siyahÄąsÄą</string>
<string name="revanced_custom_speed_menu_summary_on">Fərdi sÃŧrət siyahÄąsÄą gÃļstərilir</string> <string name="revanced_custom_speed_menu_summary_on">Fərdi sÃŧrət siyahÄąsÄą gÃļstərilir</string>
<string name="revanced_custom_speed_menu_summary_off">Fərdi sÃŧrət siyahÄąsÄą gÃļstərilmir</string> <string name="revanced_custom_speed_menu_summary_off">Fərdi sÃŧrət siyahÄąsÄą gÃļstərilmir</string>
<string name="revanced_restore_old_speed_menu_title">KÃļhnə oynatma sÃŧrəti menyusunu bərpa et</string>
<string name="revanced_restore_old_speed_menu_summary_on">KÃļhnə sÃŧrət menyusu gÃļstərilir</string>
<string name="revanced_restore_old_speed_menu_summary_off">MÃŧasir sÃŧrət menyusu gÃļstərilir</string>
<string name="revanced_custom_playback_speeds_title">Fərdi oynatma sÃŧrəti</string> <string name="revanced_custom_playback_speeds_title">Fərdi oynatma sÃŧrəti</string>
<string name="revanced_custom_playback_speeds_summary">Fərdi oynatma sÃŧrətlərini əlavə et və ya dəyiş</string> <string name="revanced_custom_playback_speeds_summary">Fərdi oynatma sÃŧrətlərini əlavə et və ya dəyiş</string>
<string name="revanced_custom_playback_speeds_invalid">Fərdi sÃŧrətlər %s dəyərindən az olmalÄądÄąr</string> <string name="revanced_custom_playback_speeds_invalid">Fərdi sÃŧrətlər %s dəyərindən az olmalÄądÄąr</string>

View File

@@ -137,7 +137,7 @@ Second \"item\" text"</string>
<string name="revanced_debug_logs_disabled">АдĐģĐ°Đ´Đ°Ņ‡ĐŊаĐĩ ĐģĐ°ĐŗĐ°Đ˛Đ°ĐŊĐŊĐĩ адĐēĐģŅŽŅ‡Đ°ĐŊа</string> <string name="revanced_debug_logs_disabled">АдĐģĐ°Đ´Đ°Ņ‡ĐŊаĐĩ ĐģĐ°ĐŗĐ°Đ˛Đ°ĐŊĐŊĐĩ адĐēĐģŅŽŅ‡Đ°ĐŊа</string>
<string name="revanced_debug_logs_none_found">Đ›Đ°ĐŗŅ– ĐŊĐĩ СĐŊОКдСĐĩĐŊŅ‹</string> <string name="revanced_debug_logs_none_found">Đ›Đ°ĐŗŅ– ĐŊĐĩ СĐŊОКдСĐĩĐŊŅ‹</string>
<string name="revanced_debug_logs_copied_to_clipboard">Đ›Đ°ĐŗŅ– ҁĐēаĐŋŅ–ŅĐ˛Đ°ĐŊŅ‹</string> <string name="revanced_debug_logs_copied_to_clipboard">Đ›Đ°ĐŗŅ– ҁĐēаĐŋŅ–ŅĐ˛Đ°ĐŊŅ‹</string>
<string name="revanced_debug_logs_failed_to_export">НĐĩ Đ°Ņ‚Ņ€Ņ‹ĐŧаĐģĐ°ŅŅ ŅĐēҁĐŋĐ°Ņ€Ņ‚Đ°Đ˛Đ°Ņ†ŅŒ ĐģĐ°ĐŗŅ–: $s</string> <string name="revanced_debug_logs_failed_to_export">НĐĩ ŅžĐ´Đ°ĐģĐžŅŅ ŅĐēҁĐŋĐ°Ņ€Ņ‚Đ°Đ˛Đ°Ņ†ŅŒ ĐļŅƒŅ€ĐŊаĐģŅ‹: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">ĐŅ‡Ņ‹ŅŅ†Ņ–Ņ†ŅŒ адĐģĐ°Đ´Đ°Ņ‡ĐŊŅ‹Ņ ĐģĐ°ĐŗŅ–</string> <string name="revanced_debug_logs_clear_buffer_title">ĐŅ‡Ņ‹ŅŅ†Ņ–Ņ†ŅŒ адĐģĐ°Đ´Đ°Ņ‡ĐŊŅ‹Ņ ĐģĐ°ĐŗŅ–</string>
<string name="revanced_debug_logs_clear_buffer_summary">ĐŅ‡Ņ‹ŅˆŅ‡Đ°Đĩ ŅžŅĐĩ ĐˇĐ°Ņ…Đ°Đ˛Đ°ĐŊŅ‹Ņ адĐģĐ°Đ´Đ°Ņ‡ĐŊŅ‹Ņ ĐģĐ°ĐŗŅ– ReVanced</string> <string name="revanced_debug_logs_clear_buffer_summary">ĐŅ‡Ņ‹ŅˆŅ‡Đ°Đĩ ŅžŅĐĩ ĐˇĐ°Ņ…Đ°Đ˛Đ°ĐŊŅ‹Ņ адĐģĐ°Đ´Đ°Ņ‡ĐŊŅ‹Ņ ĐģĐ°ĐŗŅ– ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Đ›Đ°ĐŗŅ– Đ°Ņ‡Ņ‹ŅˆŅ‡Đ°ĐŊŅ‹</string> <string name="revanced_debug_logs_clear_toast">Đ›Đ°ĐŗŅ– Đ°Ņ‡Ņ‹ŅˆŅ‡Đ°ĐŊŅ‹</string>
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_expandable_card_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ŅĐēĐģадваĐģҌĐŊŅƒŅŽ ĐēĐ°Ņ€Ņ‚Đē҃</string> <string name="revanced_hide_expandable_card_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ŅĐēĐģадваĐģҌĐŊŅƒŅŽ ĐēĐ°Ņ€Ņ‚Đē҃</string>
<string name="revanced_hide_expandable_card_summary_on">Đ Đ°ŅĐēĐģадваĐģҌĐŊĐ°Ņ ĐēĐ°Ņ€Ņ‚Đēа Đŋад Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string> <string name="revanced_hide_expandable_card_summary_on">Đ Đ°ŅĐēĐģадваĐģҌĐŊĐ°Ņ ĐēĐ°Ņ€Ņ‚Đēа Đŋад Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string>
<string name="revanced_hide_expandable_card_summary_off">Đ Đ°ŅĐēĐģадваĐģҌĐŊĐ°Ņ ĐēĐ°Ņ€Ņ‚Đēа Đŋад Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊĐ°Ņ</string> <string name="revanced_hide_expandable_card_summary_off">Đ Đ°ŅĐēĐģадваĐģҌĐŊĐ°Ņ ĐēĐ°Ņ€Ņ‚Đēа Đŋад Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊĐ°Ņ</string>
<string name="revanced_hide_feed_survey_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ аĐŋŅ‹Ņ‚Đ°ĐŊĐŊŅ– ŅŅ‚ŅƒĐļĐēŅ–</string>
<string name="revanced_hide_feed_survey_summary_on">АĐŋŅ‹Ņ‚Đ°ĐŊĐŊŅ– ĐēаĐŊаĐģĐ°Ņž ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹Ņ</string>
<string name="revanced_hide_feed_survey_summary_off">ПаĐēĐ°ĐˇĐ˛Đ°ŅŽŅ†Ņ†Đ° Đ´Đ°ŅĐģĐĩдаваĐŊĐŊŅ– ĐēĐ°Ņ€ĐŧĐžŅž</string>
<string name="revanced_hide_floating_microphone_button_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋĐģĐ°Đ˛Đ°ŅŽŅ‡ŅƒŅŽ ĐēĐŊĐžĐŋĐē҃ ĐŧŅ–ĐēŅ€Đ°Ņ„ĐžĐŊа</string> <string name="revanced_hide_floating_microphone_button_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋĐģĐ°Đ˛Đ°ŅŽŅ‡ŅƒŅŽ ĐēĐŊĐžĐŋĐē҃ ĐŧŅ–ĐēŅ€Đ°Ņ„ĐžĐŊа</string>
<string name="revanced_hide_floating_microphone_button_summary_on">ПĐģĐ°Đ˛Đ°ŅŽŅ‡Đ°Ņ ĐēĐŊĐžĐŋĐēа ĐŧŅ–ĐēŅ€Đ°Ņ„ĐžĐŊа Ņž ĐŋĐžŅˆŅƒĐē҃ ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string> <string name="revanced_hide_floating_microphone_button_summary_on">ПĐģĐ°Đ˛Đ°ŅŽŅ‡Đ°Ņ ĐēĐŊĐžĐŋĐēа ĐŧŅ–ĐēŅ€Đ°Ņ„ĐžĐŊа Ņž ĐŋĐžŅˆŅƒĐē҃ ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string>
<string name="revanced_hide_floating_microphone_button_summary_off">ПĐģĐ°Đ˛Đ°ŅŽŅ‡Đ°Ņ ĐēĐŊĐžĐŋĐēа ĐŧŅ–ĐēŅ€Đ°Ņ„ĐžĐŊа Ņž ĐŋĐžŅˆŅƒĐē҃ ĐŋаĐēаСаĐŊа</string> <string name="revanced_hide_floating_microphone_button_summary_off">ПĐģĐ°Đ˛Đ°ŅŽŅ‡Đ°Ņ ĐēĐŊĐžĐŋĐēа ĐŧŅ–ĐēŅ€Đ°Ņ„ĐžĐŊа Ņž ĐŋĐžŅˆŅƒĐē҃ ĐŋаĐēаСаĐŊа</string>
@@ -192,7 +189,7 @@ Second \"item\" text"</string>
<string name="revanced_hide_movies_section_summary_on">РаСдСĐĩĐģ ҄ҖĐģҌĐŧĐ°Ņž ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_movies_section_summary_on">РаСдСĐĩĐģ ҄ҖĐģҌĐŧĐ°Ņž ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_movies_section_summary_off">ПаĐēаСваĐĩŅ†Ņ†Đ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ҄ҖĐģҌĐŧĐ°Ņž</string> <string name="revanced_hide_movies_section_summary_off">ПаĐēаСваĐĩŅ†Ņ†Đ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ҄ҖĐģҌĐŧĐ°Ņž</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions 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_on">КĐŊĐžĐŋĐēа ÂĢПавĐĩдаĐŧŅ–Ņ†ŅŒ ĐŧĐŊĐĩÂģ ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string>
<string name="revanced_hide_notify_me_button_summary_off">КĐŊĐžĐŋĐēа ÂĢПавĐĩдаĐŧŅ–Ņ†ŅŒ ĐŧĐŊĐĩÂģ ĐŋаĐēаСаĐŊĐ°Ņ</string> <string name="revanced_hide_notify_me_button_summary_off">КĐŊĐžĐŋĐēа ÂĢПавĐĩдаĐŧŅ–Ņ†ŅŒ ĐŧĐŊĐĩÂģ ĐŋаĐēаСаĐŊĐ°Ņ</string>
@@ -204,6 +201,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_show_more_button_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐēĐŊĐžĐŋĐē҃ \"ПаĐēĐ°ĐˇĐ°Ņ†ŅŒ йОĐģҌ҈\"</string> <string name="revanced_hide_show_more_button_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐēĐŊĐžĐŋĐē҃ \"ПаĐēĐ°ĐˇĐ°Ņ†ŅŒ йОĐģҌ҈\"</string>
<string name="revanced_hide_show_more_button_summary_on">КĐŊĐžĐŋĐēа ÂĢПаĐēĐ°ĐˇĐ°Ņ†ŅŒ йОĐģҌ҈Âģ ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃ ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string> <string name="revanced_hide_show_more_button_summary_on">КĐŊĐžĐŋĐēа ÂĢПаĐēĐ°ĐˇĐ°Ņ†ŅŒ йОĐģҌ҈Âģ ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃ ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string>
<string name="revanced_hide_show_more_button_summary_off">КĐŊĐžĐŋĐēа ÂĢПаĐēĐ°ĐˇĐ°Ņ†ŅŒ йОĐģҌ҈Âģ ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃ ĐŋаĐēаСаĐŊĐ°Ņ</string> <string name="revanced_hide_show_more_button_summary_off">КĐŊĐžĐŋĐēа ÂĢПаĐēĐ°ĐˇĐ°Ņ†ŅŒ йОĐģҌ҈Âģ ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃ ĐŋаĐēаСаĐŊĐ°Ņ</string>
<string name="revanced_hide_surveys_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ аĐŋŅ‹Ņ‚Đ°ĐŊĐŊŅ–</string>
<string name="revanced_hide_surveys_summary_on">АĐŋŅ‹Ņ‚Đ°ĐŊĐŊŅ– ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹Ņ</string>
<string name="revanced_hide_surveys_summary_off">АĐŋŅ‹Ņ‚Đ°ĐŊĐŊŅ– ĐŋаĐēаСаĐŊŅ‹</string>
<string name="revanced_hide_ticket_shelf_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋаĐģŅ–Ņ†Ņƒ ĐąŅ–ĐģĐĩŅ‚Đ°Ņž</string> <string name="revanced_hide_ticket_shelf_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋаĐģŅ–Ņ†Ņƒ ĐąŅ–ĐģĐĩŅ‚Đ°Ņž</string>
<string name="revanced_hide_ticket_shelf_summary_on">ПаĐģŅ–Ņ†Đ° ĐąŅ–ĐģĐĩŅ‚Đ°Ņž ŅŅ…Đ°Đ˛Đ°ĐŊа</string> <string name="revanced_hide_ticket_shelf_summary_on">ПаĐģŅ–Ņ†Đ° ĐąŅ–ĐģĐĩŅ‚Đ°Ņž ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_ticket_shelf_summary_off">ПаĐģŅ–Ņ†Đ° ĐąŅ–ĐģĐĩŅ‚Đ°Ņž ĐŋаĐēаСаĐŊа</string> <string name="revanced_hide_ticket_shelf_summary_off">ПаĐģŅ–Ņ†Đ° ĐąŅ–ĐģĐĩŅ‚Đ°Ņž ĐŋаĐēаСаĐŊа</string>
@@ -251,8 +251,8 @@ Second \"item\" text"</string>
<string name="revanced_hide_timed_reactions_summary_on">Đ§Đ°ŅĐžĐ˛Ņ‹Ņ Ņ€ŅĐ°Đē҆ҋҖ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹Ņ</string> <string name="revanced_hide_timed_reactions_summary_on">Đ§Đ°ŅĐžĐ˛Ņ‹Ņ Ņ€ŅĐ°Đē҆ҋҖ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹Ņ</string>
<string name="revanced_hide_timed_reactions_summary_off">ПаĐēĐ°ĐˇĐ˛Đ°ŅŽŅ†Ņ†Đ° Ņ€ŅĐ°Đē҆ҋҖ Đŋа Ņ‡Đ°ŅĐĩ</string> <string name="revanced_hide_timed_reactions_summary_off">ПаĐēĐ°ĐˇĐ˛Đ°ŅŽŅ†Ņ†Đ° Ņ€ŅĐ°Đē҆ҋҖ Đŋа Ņ‡Đ°ŅĐĩ</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ÂĢЗводĐē҃ Đ˛Ņ–Đ´ŅĐ°, ĐˇĐŗĐĩĐŊŅŅ€Đ°Đ˛Đ°ĐŊŅƒŅŽ ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°ĐŧÂģ</string> <string name="revanced_hide_ai_generated_video_summary_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ÂĢЗводĐē҃ Đ˛Ņ–Đ´ŅĐ°, ĐˇĐŗĐĩĐŊŅŅ€Đ°Đ˛Đ°ĐŊŅƒŅŽ ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°ĐŧÂģ</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">РаСдСĐĩĐģ СвОдĐēŅ– Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_on">РаСдСĐĩĐģ ĐˇĐŗĐĩĐŊĐĩŅ€Đ°Đ˛Đ°ĐŊҋ҅ ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ Đ˛Ņ–Đ´ŅĐ°-Ņ€ŅĐˇŅŽĐŧŅ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">РаСдСĐĩĐģ СвОдĐēŅ– Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊŅ‹</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_off">ПаĐēаСаĐŊŅ‹ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ СвОдĐēŅ– Đ˛Ņ–Đ´ŅĐ°, ŅŅ‚Đ˛ĐžŅ€Đ°ĐŊаК ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ</string>
<string name="revanced_hide_ask_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ÂĢĐĄĐŋŅ‹Ņ‚Đ°Ņ†ŅŒÂģ</string> <string name="revanced_hide_ask_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ÂĢĐĄĐŋŅ‹Ņ‚Đ°Ņ†ŅŒÂģ</string>
<string name="revanced_hide_ask_section_summary_on">РаСдСĐĩĐģ ÂĢĐĄĐŋŅ‹Ņ‚Đ°Ņ†ŅŒÂģ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_ask_section_summary_on">РаСдСĐĩĐģ ÂĢĐĄĐŋŅ‹Ņ‚Đ°Ņ†ŅŒÂģ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_ask_section_summary_off">РаСдСĐĩĐģ ÂĢĐĄĐŋŅ‹Ņ‚Đ°Ņ†ŅŒÂģ ĐŋаĐēаСаĐŊŅ‹</string> <string name="revanced_hide_ask_section_summary_off">РаСдСĐĩĐģ ÂĢĐĄĐŋŅ‹Ņ‚Đ°Ņ†ŅŒÂģ ĐŋаĐēаСаĐŊŅ‹</string>
@@ -280,19 +280,19 @@ Second \"item\" text"</string>
<string name="revanced_hide_description_components_screen_title">АĐŋŅ–ŅĐ°ĐŊĐŊĐĩ Đ˛Ņ–Đ´ŅĐ°</string> <string name="revanced_hide_description_components_screen_title">АĐŋŅ–ŅĐ°ĐŊĐŊĐĩ Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_description_components_screen_summary">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ айО ĐŋаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ аĐŋŅ–ŅĐ°ĐŊĐŊŅ Đ˛Ņ–Đ´ŅĐ°</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_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_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ ŅŅ‚ŅƒĐļĐēĐ°Ņ…</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ŅŅ‚ŅƒĐļĐēĐ°Ņ…</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> <string name="revanced_hide_filter_bar_feed_in_feed_summary_off">ПаĐēаСаĐŊа Ņž ŅŅ‚ŅƒĐļĐēĐ°Ņ…</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ–</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ–</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">ПаĐēаСаĐŊа Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ–</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">ПаĐēаСаĐŊа Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">ПаĐēаСаĐŊа Ņž ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">ПаĐēаСаĐŊа Ņž ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">ПаĐēаСаĐŊа Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҃ ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">ПаĐēаСаĐŊŅ‹ Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string>
<string name="revanced_channel_screen_title">ĐĄŅ‚Đ°Ņ€ĐžĐŊĐēа ĐēаĐŊаĐģа</string> <string name="revanced_channel_screen_title">ĐĄŅ‚Đ°Ņ€ĐžĐŊĐēа ĐēаĐŊаĐģа</string>
<string name="revanced_channel_screen_summary">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ айО ĐŋаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ ŅŅ‚Đ°Ņ€ĐžĐŊĐēŅ– ĐēаĐŊаĐģа</string> <string name="revanced_channel_screen_summary">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ айО ĐŋаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ ŅŅ‚Đ°Ņ€ĐžĐŊĐēŅ– ĐēаĐŊаĐģа</string>
<!-- 'For You' should be translated using the same localized wording YouTube displays. --> <!-- 'For You' should be translated using the same localized wording YouTube displays. -->
@@ -316,11 +316,11 @@ Second \"item\" text"</string>
<string name="revanced_comments_screen_title">КаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹Ņ–</string> <string name="revanced_comments_screen_title">КаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹Ņ–</string>
<string name="revanced_comments_screen_summary">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ айО ĐŋаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž</string> <string name="revanced_comments_screen_summary">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ айО ĐŋаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž</string>
<string name="revanced_hide_comments_ai_chat_summary_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ СвОдĐē҃ Ņ‡Đ°Ņ‚Đ° ŅĐ° ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ</string> <string name="revanced_hide_comments_ai_chat_summary_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ СвОдĐē҃ Ņ‡Đ°Ņ‚Đ° ŅĐ° ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_on">ЗводĐēа Ņ‡Đ°Ņ‚Đ° ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string> <string name="revanced_hide_comments_ai_chat_summary_summary_on">ЗводĐēа Ņ‡Đ°Ņ‚Đ° ŅĐ° ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">ЗводĐēа Ņ‡Đ°Ņ‚Đ° ĐŋаĐēаСаĐŊĐ°Ņ</string> <string name="revanced_hide_comments_ai_chat_summary_summary_off">ЗводĐēа Ņ‡Đ°Ņ‚Đ° ŅĐ° ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ ĐŋаĐēаСаĐŊа</string>
<string name="revanced_hide_comments_ai_summary_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ СвОдĐē҃ ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž ŅĐ° ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ</string> <string name="revanced_hide_comments_ai_summary_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ СвОдĐē҃ ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž ŅĐ° ŅˆŅ‚ŅƒŅ‡ĐŊŅ‹Đŧ Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Đ°Đŧ</string>
<string name="revanced_hide_comments_ai_summary_summary_on">ЗводĐēа ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž ŅŅ…Đ°Đ˛Đ°ĐŊĐ°Ņ</string> <string name="revanced_hide_comments_ai_summary_summary_on">ЗводĐēа ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž ŅˆŅ‚ŅƒŅ‡ĐŊĐ°ĐŗĐ° Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Ņƒ ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_comments_ai_summary_summary_off">ЗводĐēа ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž ĐŋаĐēаСаĐŊĐ°Ņ</string> <string name="revanced_hide_comments_ai_summary_summary_off">ЗводĐēа ĐēаĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ‹ŅŅž ŅˆŅ‚ŅƒŅ‡ĐŊĐ°ĐŗĐ° Ņ–ĐŊŅ‚ŅĐģĐĩĐēŅ‚Ņƒ ĐŋаĐēаСаĐŊа</string>
<string name="revanced_hide_comments_channel_guidelines_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋŅ€Đ°Đ˛Ņ–ĐģŅ‹ ĐēаĐŊаĐģа</string> <string name="revanced_hide_comments_channel_guidelines_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋŅ€Đ°Đ˛Ņ–ĐģŅ‹ ĐēаĐŊаĐģа</string>
<string name="revanced_hide_comments_channel_guidelines_summary_on">Đ ŅĐēаĐŧĐĩĐŊĐ´Đ°Ņ†Ņ‹Ņ– ĐēаĐŊаĐģа ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_comments_channel_guidelines_summary_on">Đ ŅĐēаĐŧĐĩĐŊĐ´Đ°Ņ†Ņ‹Ņ– ĐēаĐŊаĐģа ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_comments_channel_guidelines_summary_off">Đ ŅĐēаĐŧĐĩĐŊĐ´Đ°Ņ†Ņ‹Ņ– ĐēаĐŊаĐģа ĐŋаĐēаСаĐŊŅ‹</string> <string name="revanced_hide_comments_channel_guidelines_summary_off">Đ ŅĐēаĐŧĐĩĐŊĐ´Đ°Ņ†Ņ‹Ņ– ĐēаĐŊаĐģа ĐŋаĐēаСаĐŊŅ‹</string>
@@ -419,7 +419,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_shopping_links_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҁĐŋĐ°ŅŅ‹ĐģĐēŅ– Đ´ĐģŅ ĐŋаĐē҃ĐŋаĐē</string> <string name="revanced_hide_shopping_links_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ҁĐŋĐ°ŅŅ‹ĐģĐēŅ– Đ´ĐģŅ ĐŋаĐē҃ĐŋаĐē</string>
<string name="revanced_hide_shopping_links_summary_on">ĐĄĐŋĐ°ŅŅ‹ĐģĐēŅ– ĐŊа ĐŋаĐē҃ĐŋĐēŅ– Ņž аĐŋŅ–ŅĐ°ĐŊĐŊŅ– Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹Ņ</string> <string name="revanced_hide_shopping_links_summary_on">ĐĄĐŋĐ°ŅŅ‹ĐģĐēŅ– ĐŊа ĐŋаĐē҃ĐŋĐēŅ– Ņž аĐŋŅ–ŅĐ°ĐŊĐŊŅ– Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹Ņ</string>
<string name="revanced_hide_shopping_links_summary_off">ĐĄĐŋĐ°ŅŅ‹ĐģĐēŅ– ĐŊа ĐŋаĐē҃ĐŋĐēŅ– Ņž аĐŋŅ–ŅĐ°ĐŊĐŊŅ– Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊŅ‹</string> <string name="revanced_hide_shopping_links_summary_off">ĐĄĐŋĐ°ŅŅ‹ĐģĐēŅ– ĐŊа ĐŋаĐē҃ĐŋĐēŅ– Ņž аĐŋŅ–ŅĐ°ĐŊĐŊŅ– Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊŅ‹</string>
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_view_products_banner_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ йаĐŊŅŅ€ \"ĐŸŅ€Đ°ĐŗĐģĐĩдСĐĩŅ†ŅŒ Ņ‚Đ°Đ˛Đ°Ņ€Ņ‹\"</string> <string name="revanced_hide_view_products_banner_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ йаĐŊŅŅ€ \"ĐŸŅ€Đ°ĐŗĐģĐĩдСĐĩŅ†ŅŒ Ņ‚Đ°Đ˛Đ°Ņ€Ņ‹\"</string>
<string name="revanced_hide_view_products_banner_summary_on">БаĐŊĐĩŅ€ ÂĢĐŸĐ°ĐŗĐģŅĐ´ĐˇĐĩŅ†ŅŒ Ņ‚Đ°Đ˛Đ°Ņ€Ņ‹Âģ Ņž ĐŊаĐēĐģĐ°Đ´Ņ†Ņ‹ Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_view_products_banner_summary_on">БаĐŊĐĩŅ€ ÂĢĐŸĐ°ĐŗĐģŅĐ´ĐˇĐĩŅ†ŅŒ Ņ‚Đ°Đ˛Đ°Ņ€Ņ‹Âģ Ņž ĐŊаĐēĐģĐ°Đ´Ņ†Ņ‹ Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_view_products_banner_summary_off">БаĐŊĐĩŅ€ ÂĢĐŸĐ°ĐŗĐģŅĐ´ĐˇĐĩŅ†ŅŒ Ņ‚Đ°Đ˛Đ°Ņ€Ņ‹Âģ Ņž ĐŊаĐēĐģĐ°Đ´Ņ†Ņ‹ Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊŅ‹</string> <string name="revanced_hide_view_products_banner_summary_off">БаĐŊĐĩŅ€ ÂĢĐŸĐ°ĐŗĐģŅĐ´ĐˇĐĩŅ†ŅŒ Ņ‚Đ°Đ˛Đ°Ņ€Ņ‹Âģ Ņž ĐŊаĐēĐģĐ°Đ´Ņ†Ņ‹ Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊŅ‹</string>
@@ -453,7 +452,7 @@ Second \"item\" text"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Đ‘ŅƒĐ´ĐˇĐĩ ĐŋаĐēаСаĐŊа Đ´Ņ‹ŅĐģĐžĐŗĐ°Đ˛Đ°Đĩ аĐēĐŊĐž</string> <string name="revanced_remove_viewer_discretion_dialog_summary_off">Đ‘ŅƒĐ´ĐˇĐĩ ĐŋаĐēаСаĐŊа Đ´Ņ‹ŅĐģĐžĐŗĐ°Đ˛Đ°Đĩ аĐēĐŊĐž</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Đ“ŅŅ‚Đ° ĐŊĐĩ Đ°ĐąŅ‹Ņ…ĐžĐ´ĐˇŅ–Ņ†ŅŒ ŅƒĐˇŅ€ĐžŅŅ‚Đ°Đ˛Đ°Đĩ айĐŧĐĩĐļаваĐŊĐŊĐĩ. ЁĐŊ ĐŋŅ€ĐžŅŅ‚Đ° ĐŋҀҋĐŧаĐĩ ĐŗŅŅ‚Đ° Đ°ŅžŅ‚Đ°ĐŧĐ°Ņ‚Ņ‹Ņ‡ĐŊа.</string> <string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Đ“ŅŅ‚Đ° ĐŊĐĩ Đ°ĐąŅ‹Ņ…ĐžĐ´ĐˇŅ–Ņ†ŅŒ ŅƒĐˇŅ€ĐžŅŅ‚Đ°Đ˛Đ°Đĩ айĐŧĐĩĐļаваĐŊĐŊĐĩ. ЁĐŊ ĐŋŅ€ĐžŅŅ‚Đ° ĐŋҀҋĐŧаĐĩ ĐŗŅŅ‚Đ° Đ°ŅžŅ‚Đ°ĐŧĐ°Ņ‚Ņ‹Ņ‡ĐŊа.</string>
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">АдĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ ĐŋŅ€Đ°Đŋ҃ҁĐē Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа Đŋа дваКĐŊŅ‹Đŧ ĐŊĐ°Ņ†Ņ–ŅĐē҃</string> <string name="revanced_disable_chapter_skip_double_tap_title">АдĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ ĐŋŅ€Đ°Đŋ҃ҁĐē Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа Đŋа дваКĐŊŅ‹Đŧ ĐŊĐ°Ņ†Ņ–ŅĐē҃</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">ДвайĐŊŅ‹ ĐŊĐ°Ņ†Ņ–ŅĐē ĐŊŅ–ĐēĐžĐģŅ– ĐŊĐĩ ĐŧĐžĐļа Đ˛Ņ‹ĐēĐģŅ–ĐēĐ°Ņ†ŅŒ ĐŋŅ€Đ°Đŋ҃ҁĐē да ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ°ĐŗĐ°/ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅĐŗĐ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа</string> <string name="revanced_disable_chapter_skip_double_tap_summary_on">ДвайĐŊŅ‹ ĐŊĐ°Ņ†Ņ–ŅĐē ĐŊŅ–ĐēĐžĐģŅ– ĐŊĐĩ ĐŧĐžĐļа Đ˛Ņ‹ĐēĐģŅ–ĐēĐ°Ņ†ŅŒ ĐŋŅ€Đ°Đŋ҃ҁĐē да ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ°ĐŗĐ°/ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅĐŗĐ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_off">ДвайĐŊŅ‹ ĐŊĐ°Ņ†Ņ–ŅĐē ĐŧĐžĐļа Ņ‡Đ°Ņ ад Ņ‡Đ°ŅŅƒ Đ˛Ņ‹ĐēĐģŅ–ĐēĐ°Ņ†ŅŒ ĐŋŅ€Đ°Đŋ҃ҁĐē да ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ°ĐŗĐ°/ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅĐŗĐ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа</string> <string name="revanced_disable_chapter_skip_double_tap_summary_off">ДвайĐŊŅ‹ ĐŊĐ°Ņ†Ņ–ŅĐē ĐŧĐžĐļа Ņ‡Đ°Ņ ад Ņ‡Đ°ŅŅƒ Đ˛Ņ‹ĐēĐģŅ–ĐēĐ°Ņ†ŅŒ ĐŋŅ€Đ°Đŋ҃ҁĐē да ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ°ĐŗĐ°/ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅĐŗĐ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģа</string>
@@ -469,8 +468,15 @@ Second \"item\" text"</string>
<string name="revanced_external_downloader_action_button_summary_on">КĐŊĐžĐŋĐēа \"ĐĄĐŋаĐŧĐŋĐ°Đ˛Đ°Ņ†ŅŒ\" адĐēŅ€Ņ‹Đ˛Đ°Đĩ Đ˛Đ°Ņˆ СĐŊĐĩ҈ĐŊŅ– ĐˇĐ°ĐŗŅ€ŅƒĐˇĐŊŅ–Đē</string> <string name="revanced_external_downloader_action_button_summary_on">КĐŊĐžĐŋĐēа \"ĐĄĐŋаĐŧĐŋĐ°Đ˛Đ°Ņ†ŅŒ\" адĐēŅ€Ņ‹Đ˛Đ°Đĩ Đ˛Đ°Ņˆ СĐŊĐĩ҈ĐŊŅ– ĐˇĐ°ĐŗŅ€ŅƒĐˇĐŊŅ–Đē</string>
<string name="revanced_external_downloader_action_button_summary_off">КĐŊĐžĐŋĐēа \"ĐĄĐŋаĐŧĐŋĐ°Đ˛Đ°Ņ†ŅŒ\" адĐēŅ€Ņ‹Đ˛Đ°Đĩ ŅžĐģĐ°ŅĐŊŅƒŅŽ ĐŋŅ€Đ°ĐŗŅ€Đ°Đŧ҃ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēŅ– Ņž ĐŋŅ€Đ°ĐŗŅ€Đ°ĐŧĐĩ</string> <string name="revanced_external_downloader_action_button_summary_off">КĐŊĐžĐŋĐēа \"ĐĄĐŋаĐŧĐŋĐ°Đ˛Đ°Ņ†ŅŒ\" адĐēŅ€Ņ‹Đ˛Đ°Đĩ ŅžĐģĐ°ŅĐŊŅƒŅŽ ĐŋŅ€Đ°ĐŗŅ€Đ°Đŧ҃ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēŅ– Ņž ĐŋŅ€Đ°ĐŗŅ€Đ°ĐŧĐĩ</string>
<string name="revanced_external_downloader_name_title">Назва ĐŋаĐēĐĩŅ‚Đ° ĐˇĐ°ĐŗŅ€ŅƒĐˇĐŊŅ–Đēа</string> <string name="revanced_external_downloader_name_title">Назва ĐŋаĐēĐĩŅ‚Đ° ĐˇĐ°ĐŗŅ€ŅƒĐˇĐŊŅ–Đēа</string>
<string name="revanced_external_downloader_name_summary">ІĐŧŅ ĐŋаĐēĐĩŅ‚Đ° ŅžŅŅ‚Đ°ĐģŅĐ˛Đ°ĐŊаК СĐŊĐĩ҈ĐŊŅĐš ĐŋŅ€Đ°ĐŗŅ€Đ°ĐŧŅ‹ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēŅ–, ĐŊаĐŋҀҋĐēĐģад NewPipe айО Seal</string> <string name="revanced_external_downloader_name_summary">Назва ĐŋаĐēĐĩŅ‚Đ° Đ˛Đ°ŅˆĐ°ĐŗĐ° ŅžŅŅ‚Đ°ĐģŅĐ˛Đ°ĐŊĐ°ĐŗĐ° СĐŊĐĩ҈ĐŊŅĐŗĐ° ҁĐŋаĐŧĐŋĐžŅžŅˆŅ‡Ņ‹Đēа ĐŋŅ€Đ°ĐŗŅ€Đ°ĐŧŅ‹</string>
<string name="revanced_external_downloader_other_item_hint">ĐŖĐ˛ŅĐ´ĐˇŅ–Ņ†Đĩ ĐŊĐ°ĐˇĐ˛Ņƒ ĐŋаĐēĐĩŅ‚Đ°</string>
<string name="revanced_external_downloader_other_item">ІĐŊŅˆĐ°Đĩ</string>
<string name="revanced_external_downloader_not_found_title">ĐŸŅ€Đ°ĐŗŅ€Đ°Đŧа ĐŊĐĩ ŅžŅŅ‚Đ°ĐŊĐžŅžĐģĐĩĐŊа</string>
<string name="revanced_external_downloader_not_installed_warning">%s ĐŊĐĩ ŅžŅŅ‚Đ°ĐģŅĐ˛Đ°ĐŊŅ‹. КаĐģŅ– ĐģĐ°ŅĐēа, ŅƒŅŅ‚Đ°ĐģŅŽĐšŅ†Đĩ ŅĐŗĐž.</string> <string name="revanced_external_downloader_not_installed_warning">%s ĐŊĐĩ ŅžŅŅ‚Đ°ĐģŅĐ˛Đ°ĐŊŅ‹. КаĐģŅ– ĐģĐ°ŅĐēа, ŅƒŅŅ‚Đ°ĐģŅŽĐšŅ†Đĩ ŅĐŗĐž.</string>
<string name="revanced_external_downloader_package_not_found_warning">"НĐĩ ŅžĐ´Đ°ĐģĐžŅŅ СĐŊĐ°ĐšŅŅ†Ņ– ŅžŅŅ‚Đ°ĐŊĐžŅžĐģĐĩĐŊŅƒŅŽ ĐŋŅ€Đ°ĐŗŅ€Đ°Đŧ҃ С ĐŊаСваК ĐŋаĐēĐĩŅ‚Đ°: %s
ĐŸŅ€Đ°Đ˛ĐĩҀ҆Đĩ, ҆Җ ĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊĐ°Ņ ĐŊаСва ĐŋаĐēĐĩŅ‚Đ° Ņ– ҆Җ ŅžŅŅ‚Đ°ĐŊĐžŅžĐģĐĩĐŊа ĐŋŅ€Đ°ĐŗŅ€Đ°Đŧа"</string>
<string name="revanced_external_downloader_empty_warning">Назва ĐŋаĐēĐĩŅ‚Đ° ĐŊĐĩ ĐŧĐžĐļа ĐąŅ‹Ņ†ŅŒ ĐŋŅƒŅŅ‚ĐžĐš</string>
</patch> </patch>
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch"> <patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">АдĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ ĐļŅŅŅ‚ даĐēĐģадĐŊĐ°ĐŗĐ° ĐŋĐžŅˆŅƒĐē҃</string> <string name="revanced_disable_precise_seeking_gesture_title">АдĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ ĐļŅŅŅ‚ даĐēĐģадĐŊĐ°ĐŗĐ° ĐŋĐžŅˆŅƒĐē҃</string>
@@ -730,27 +736,28 @@ Second \"item\" text"</string>
<string name="revanced_disable_rolling_number_animations_summary_off">ĐŸŅ€Đ°ĐēĐ°Ņ‚ĐŊŅ‹Ņ ĐģŅ–Ņ‡ĐąŅ‹ аĐŊŅ–ĐŧŅ–Ņ€Đ°Đ˛Đ°ĐŊŅ‹Ņ</string> <string name="revanced_disable_rolling_number_animations_summary_off">ĐŸŅ€Đ°ĐēĐ°Ņ‚ĐŊŅ‹Ņ ĐģŅ–Ņ‡ĐąŅ‹ аĐŊŅ–ĐŧŅ–Ņ€Đ°Đ˛Đ°ĐŊŅ‹Ņ</string>
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<string name="revanced_hide_seekbar_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ Ņž Đ˛Ņ–Đ´ŅĐ°ĐŋĐģŅĐĩҀҋ</string> <string name="revanced_hide_seekbar_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋаĐŊŅĐģҌ ĐŋŅ€Đ°ĐŗŅ€ŅŅŅƒ Đ˛Ņ–Đ´ŅĐ°ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐģҌĐŊŅ–Đēа</string>
<string name="revanced_hide_seekbar_summary_on">ПаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ Đ˛Ņ–Đ´ŅĐ°ĐŋĐģŅĐĩŅ€Đ° ŅŅ…Đ°Đ˛Đ°ĐŊа</string> <string name="revanced_hide_seekbar_summary_on">ПаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ Đ˛Ņ–Đ´ŅĐ°ĐŋĐģŅĐĩŅ€Đ° ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_seekbar_summary_off">АдĐģŅŽŅŅ‚Ņ€ĐžŅžĐ˛Đ°ĐĩŅ†Ņ†Đ° ĐŋаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ Đ˛Ņ–Đ´ŅĐ°ĐŋĐģŅĐĩŅ€Đ°</string> <string name="revanced_hide_seekbar_summary_off">АдĐģŅŽŅŅ‚Ņ€ĐžŅžĐ˛Đ°ĐĩŅ†Ņ†Đ° ĐŋаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ Đ˛Ņ–Đ´ŅĐ°ĐŋĐģŅĐĩŅ€Đ°</string>
<string name="revanced_hide_seekbar_thumbnail_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ Ņž ĐŧŅ–ĐŊŅ–ŅŅ†ŅŽŅ€Đ°Ņ… Đ˛Ņ–Đ´ŅĐ°</string> <!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
<string name="revanced_hide_seekbar_thumbnail_summary_on">ПаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ ŅŅĐēŅ–ĐˇĐ°Ņž ŅŅ…Đ°Đ˛Đ°ĐŊа</string> <string name="revanced_hide_seekbar_thumbnail_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐŋаĐŊŅĐģҌ ĐŋŅ€Đ°ĐŗŅ€ŅŅŅƒ С ŅŅĐēŅ–ĐˇĐ°ĐŧŅ– Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">АдĐģŅŽŅŅ‚Ņ€ĐžŅžĐ˛Đ°ĐĩŅ†Ņ†Đ° ĐŋаĐŊŅĐģҌ ĐŋĐžŅˆŅƒĐē҃ ŅŅĐēŅ–ĐˇĐ°Ņž</string> <string name="revanced_hide_seekbar_thumbnail_summary_on">ПаĐŊŅĐģҌ ĐŋŅ€Đ°ĐŗŅ€ŅŅŅƒ С ŅŅĐēŅ–ĐˇĐ°ĐŧŅ– Đ˛Ņ–Đ´ŅĐ° ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">ПаĐŊŅĐģҌ ĐŋŅ€Đ°ĐŗŅ€ŅŅŅƒ С ŅŅĐēŅ–ĐˇĐ°ĐŧŅ– Đ˛Ņ–Đ´ŅĐ° ĐŋаĐēаСаĐŊа</string>
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<string name="revanced_shorts_player_screen_title">ĐŸŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐģҌĐŊŅ–Đē Shorts</string> <string name="revanced_shorts_player_screen_title">ĐŸŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐģҌĐŊŅ–Đē Shorts</string>
<string name="revanced_shorts_player_screen_summary">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ айО ĐŋаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ Ņž ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐģҌĐŊŅ–Đē҃ Shorts</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. --> <!-- '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_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Shorts ҃ ŅŅ‚ŅƒĐļ҆ҋ ÂĢГаĐģĐžŅžĐŊĐ°ŅÂģ</string>
<string name="revanced_hide_shorts_home_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢГаĐģĐžŅžĐŊĐ°ŅÂģ Ņ– ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string> <string name="revanced_hide_shorts_home_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢГаĐģĐžŅžĐŊĐ°ŅÂģ Ņ– ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_shorts_home_summary_off">ПаĐēаСаĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢГаĐģĐžŅžĐŊĐ°ŅÂģ Ņ– ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string> <string name="revanced_hide_shorts_home_summary_off">ПаĐēаСаĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢГаĐģĐžŅžĐŊĐ°ŅÂģ Ņ– ĐˇĐ˛ŅĐˇĐ°ĐŊҋ҅ Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_hide_shorts_search_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Shorts ҃ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_shorts_search_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊŅ‹ Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<string name="revanced_hide_shorts_search_summary_off">ПаĐēаСаĐŊа Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</string>
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. --> <!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
<string name="revanced_hide_shorts_subscriptions_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Shorts ҃ ŅŅ‚ŅƒĐļ҆ҋ ÂĢПадĐŋҖҁĐēŅ–Âģ</string> <string name="revanced_hide_shorts_subscriptions_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Shorts ҃ ŅŅ‚ŅƒĐļ҆ҋ ÂĢПадĐŋҖҁĐēŅ–Âģ</string>
<string name="revanced_hide_shorts_subscriptions_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢПадĐŋҖҁĐēŅ–Âģ</string> <string name="revanced_hide_shorts_subscriptions_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢПадĐŋҖҁĐēŅ–Âģ</string>
<string name="revanced_hide_shorts_subscriptions_summary_off">ПаĐēаСаĐŊа Ņž ŅŅ‚ŅƒĐļ҆ҋ ÂĢПадĐŋҖҁĐēŅ–Âģ</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">ĐĄŅ…Đ°Đ˛Đ°ĐŊŅ‹ Ņž Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņ… ĐŋĐžŅˆŅƒĐē҃</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_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Shorts С ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string>
<string name="revanced_hide_shorts_history_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string> <string name="revanced_hide_shorts_history_summary_on">ĐĄŅ…Đ°Đ˛Đ°ĐŊа Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string>
<string name="revanced_hide_shorts_history_summary_off">ПаĐēаСаĐŊŅ‹ Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string> <string name="revanced_hide_shorts_history_summary_off">ПаĐēаСаĐŊŅ‹ Ņž ĐŗŅ–ŅŅ‚ĐžŅ€Ņ‹Ņ– ĐŋŅ€Đ°ĐŗĐģŅĐ´Đ°Ņž</string>
@@ -1191,8 +1198,6 @@ Second \"item\" text"</string>
Đ“ŅŅ‚Đ° СĐŧĐĩĐŊŅ–Ņ†ŅŒ СĐŊĐĩ҈ĐŊŅ– Đ˛Ņ‹ĐŗĐģŅĐ´ Ņ– Ņ„ŅƒĐŊĐē҆ҋҖ ĐŋҀҋĐēĐģадаĐŊĐŊŅ, аĐģĐĩ ĐŧĐžĐŗŅƒŅ†ŅŒ ŅƒĐˇĐŊŅ–ĐēĐŊŅƒŅ†ŅŒ ĐŊĐĩĐ˛ŅĐ´ĐžĐŧŅ‹Ņ ĐŋĐ°ĐąĐžŅ‡ĐŊŅ‹Ņ ŅŅ„ĐĩĐē҂ҋ. Đ“ŅŅ‚Đ° СĐŧĐĩĐŊŅ–Ņ†ŅŒ СĐŊĐĩ҈ĐŊŅ– Đ˛Ņ‹ĐŗĐģŅĐ´ Ņ– Ņ„ŅƒĐŊĐē҆ҋҖ ĐŋҀҋĐēĐģадаĐŊĐŊŅ, аĐģĐĩ ĐŧĐžĐŗŅƒŅ†ŅŒ ŅƒĐˇĐŊŅ–ĐēĐŊŅƒŅ†ŅŒ ĐŊĐĩĐ˛ŅĐ´ĐžĐŧŅ‹Ņ ĐŋĐ°ĐąĐžŅ‡ĐŊŅ‹Ņ ŅŅ„ĐĩĐē҂ҋ.
КаĐģŅ– ĐŋаСĐŊĐĩĐš ĐąŅƒĐ´ĐˇĐĩ адĐēĐģŅŽŅ‡Đ°ĐŊа, Ņ€ŅĐēаĐŧĐĩĐŊĐ´ŅƒĐĩŅ†Ņ†Đ° Đ°Ņ‡Ņ‹ŅŅ†Ņ–Ņ†ŅŒ даĐŊŅ‹Ņ ĐŋҀҋĐēĐģадаĐŊĐŊŅ, Đēай ĐŋаСйĐĩĐŗĐŊŅƒŅ†ŅŒ ĐŋаĐŧŅ‹ĐģаĐē ҃ Ņ–ĐŊŅ‚ŅŅ€Ņ„ĐĩĐšŅĐĩ."</string> КаĐģŅ– ĐŋаСĐŊĐĩĐš ĐąŅƒĐ´ĐˇĐĩ адĐēĐģŅŽŅ‡Đ°ĐŊа, Ņ€ŅĐēаĐŧĐĩĐŊĐ´ŅƒĐĩŅ†Ņ†Đ° Đ°Ņ‡Ņ‹ŅŅ†Ņ–Ņ†ŅŒ даĐŊŅ‹Ņ ĐŋҀҋĐēĐģадаĐŊĐŊŅ, Đēай ĐŋаСйĐĩĐŗĐŊŅƒŅ†ŅŒ ĐŋаĐŧŅ‹ĐģаĐē ҃ Ņ–ĐŊŅ‚ŅŅ€Ņ„ĐĩĐšŅĐĩ."</string>
<!-- 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. -->
<string name="revanced_spoof_app_version_target_title">ĐŸĐ°Đ´Ņ€ĐžĐąĐēа ĐŧŅŅ‚Đ°Đ˛Đ°Đš вĐĩҀҁҖҖ ĐŋŅ€Đ°ĐŗŅ€Đ°ĐŧŅ‹</string> <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_1">19.35.36 — Đ’ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ŅŅ‚Đ°Ņ€Ņ‹Đĩ СĐŊĐ°Ņ‡Đēи ĐŋĐģĐĩĐĩŅ€Đ° Shorts</string>
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - АдĐŊĐ°ŅžĐģĐĩĐŊĐŊĐĩ ŅŅ‚Đ°Ņ€Ņ‹Ņ… СĐŊĐ°Ņ‡ĐēĐžŅž ĐŊĐ°Đ˛Ņ–ĐŗĐ°Ņ†Ņ‹Ņ–</string> <string name="revanced_spoof_app_version_target_entry_2">19.01.34 - АдĐŊĐ°ŅžĐģĐĩĐŊĐŊĐĩ ŅŅ‚Đ°Ņ€Ņ‹Ņ… СĐŊĐ°Ņ‡ĐēĐžŅž ĐŊĐ°Đ˛Ņ–ĐŗĐ°Ņ†Ņ‹Ņ–</string>
@@ -1461,10 +1466,18 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">КĐŊĐžĐŋĐēа ĐŋаĐēаСаĐŊа. ĐĐ°Ņ†Ņ–ŅĐŊҖ҆Đĩ Ņ– ŅžŅ‚Ņ€Ņ‹ĐŧĐģŅ–Đ˛Đ°ĐšŅ†Đĩ, Đēай ҁĐēŅ–ĐŊŅƒŅ†ŅŒ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†ŅŒ ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊŅ да ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊаК</string> <string name="revanced_playback_speed_dialog_button_summary_on">КĐŊĐžĐŋĐēа ĐŋаĐēаСаĐŊа. ĐĐ°Ņ†Ņ–ŅĐŊҖ҆Đĩ Ņ– ŅžŅ‚Ņ€Ņ‹ĐŧĐģŅ–Đ˛Đ°ĐšŅ†Đĩ, Đēай ҁĐēŅ–ĐŊŅƒŅ†ŅŒ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†ŅŒ ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊŅ да ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊаК</string>
<string name="revanced_playback_speed_dialog_button_summary_off">КĐŊĐžĐŋĐēа ĐŊĐĩ ĐŋаĐēаСваĐĩŅ†Ņ†Đ°</string> <string name="revanced_playback_speed_dialog_button_summary_off">КĐŊĐžĐŋĐēа ĐŊĐĩ ĐŋаĐēаСваĐĩŅ†Ņ†Đ°</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
<string name="revanced_video_quality_dialog_button_title">ПаĐēĐ°ĐˇĐ°Ņ†ŅŒ ĐēĐŊĐžĐŋĐē҃ ŅĐēĐ°ŅŅ†Ņ– Đ˛Ņ–Đ´ŅĐ°</string>
<string name="revanced_video_quality_dialog_button_summary_on">КĐŊĐžĐŋĐēа ĐŋаĐēаСаĐŊа. ĐĐ°Ņ†Ņ–ŅĐŊҖ҆Đĩ Ņ– ŅžŅ‚Ņ€Ņ‹ĐŧĐģŅ–Đ˛Đ°ĐšŅ†Đĩ, Đēай ҁĐēŅ–ĐŊŅƒŅ†ŅŒ ŅĐēĐ°ŅŅ†ŅŒ да Đŋа СĐŧĐ°ŅžŅ‡Đ°ĐŊĐŊŅ–</string>
<string name="revanced_video_quality_dialog_button_summary_off">КĐŊĐžĐŋĐēа ĐŊĐĩ ĐŋаĐēаСваĐĩŅ†Ņ†Đ°</string>
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">МĐĩĐŊŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēОК ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊĐ¸Ņ</string> <string name="revanced_custom_speed_menu_title">МĐĩĐŊŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēОК ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊĐ¸Ņ</string>
<string name="revanced_custom_speed_menu_summary_on">МĐĩĐŊŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēОК ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐžŅ‚ĐžĐąŅ€Đ°ĐļаĐĩŅ‚ŅŅ</string> <string name="revanced_custom_speed_menu_summary_on">МĐĩĐŊŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēОК ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐžŅ‚ĐžĐąŅ€Đ°ĐļаĐĩŅ‚ŅŅ</string>
<string name="revanced_custom_speed_menu_summary_off">МĐĩĐŊŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēОК ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐŊĐĩ ĐžŅ‚ĐžĐąŅ€Đ°ĐļаĐĩŅ‚ŅŅ</string> <string name="revanced_custom_speed_menu_summary_off">МĐĩĐŊŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēОК ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐŊĐĩ ĐžŅ‚ĐžĐąŅ€Đ°ĐļаĐĩŅ‚ŅŅ</string>
<string name="revanced_restore_old_speed_menu_title">АдĐŊĐ°Đ˛Ņ–Ņ†ŅŒ ŅŅ‚Đ°Ņ€ĐžĐĩ ĐŧĐĩĐŊŅŽ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ– ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊŅ</string>
<string name="revanced_restore_old_speed_menu_summary_on">ПаĐēаСаĐŊа ŅŅ‚Đ°Ņ€ĐžĐĩ ĐŧĐĩĐŊŅŽ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ–</string>
<string name="revanced_restore_old_speed_menu_summary_off">ПаĐēаСаĐŊа ŅŅƒŅ‡Đ°ŅĐŊаĐĩ ĐŧĐĩĐŊŅŽ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ–</string>
<string name="revanced_custom_playback_speeds_title">ĐšĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊҖ҆ĐēŅ–Ņ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ– ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊŅ</string> <string name="revanced_custom_playback_speeds_title">ĐšĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊҖ҆ĐēŅ–Ņ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ– ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊŅ</string>
<string name="revanced_custom_playback_speeds_summary">Đ”ĐžĐąĐ°Đ˛ŅŒŅ‚Đĩ иĐģи иСĐŧĐĩĐŊĐ¸Ņ‚Đĩ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēŅƒŅŽ ҁĐēĐžŅ€ĐžŅŅ‚ŅŒ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊĐ¸Ņ</string> <string name="revanced_custom_playback_speeds_summary">Đ”ĐžĐąĐ°Đ˛ŅŒŅ‚Đĩ иĐģи иСĐŧĐĩĐŊĐ¸Ņ‚Đĩ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēŅƒŅŽ ҁĐēĐžŅ€ĐžŅŅ‚ŅŒ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊĐ¸Ņ</string>
<string name="revanced_custom_playback_speeds_invalid">НĐĩŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ‹Ņ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ– ĐŋĐ°Đ˛Ņ–ĐŊĐŊŅ‹ ĐąŅ‹Ņ†ŅŒ ĐŧĐĩĐŊ҈ Са %s</string> <string name="revanced_custom_playback_speeds_invalid">НĐĩŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ‹Ņ Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†Ņ– ĐŋĐ°Đ˛Ņ–ĐŊĐŊŅ‹ ĐąŅ‹Ņ†ŅŒ ĐŧĐĩĐŊ҈ Са %s</string>

View File

@@ -137,7 +137,7 @@ Second \"item\" text"</string>
<string name="revanced_debug_logs_disabled">ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩŅ‚Đž ĐŊа ĐŗŅ€Đĩ҈Đēи Đĩ Đ´ĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐž</string> <string name="revanced_debug_logs_disabled">ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩŅ‚Đž ĐŊа ĐŗŅ€Đĩ҈Đēи Đĩ Đ´ĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐž</string>
<string name="revanced_debug_logs_none_found">НĐĩ ŅĐ° ĐŊаĐŧĐĩŅ€ĐĩĐŊи ĐģĐžĐŗĐžĐ˛Đĩ</string> <string name="revanced_debug_logs_none_found">НĐĩ ŅĐ° ĐŊаĐŧĐĩŅ€ĐĩĐŊи ĐģĐžĐŗĐžĐ˛Đĩ</string>
<string name="revanced_debug_logs_copied_to_clipboard">Đ›ĐžĐŗĐžĐ˛ĐĩŅ‚Đĩ ŅĐ° ĐēĐžĐŋĐ¸Ņ€Đ°ĐŊи</string> <string name="revanced_debug_logs_copied_to_clipboard">Đ›ĐžĐŗĐžĐ˛ĐĩŅ‚Đĩ ŅĐ° ĐēĐžĐŋĐ¸Ņ€Đ°ĐŊи</string>
<string name="revanced_debug_logs_failed_to_export">НĐĩ҃ҁĐŋĐĩ҈ĐŊĐž ĐĩĐēҁĐŋĐžŅ€Ņ‚Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐģĐžĐŗĐžĐ˛Đĩ: $s</string> <string name="revanced_debug_logs_failed_to_export">НĐĩ҃ҁĐŋĐĩ҈ĐŊĐž ĐĩĐēҁĐŋĐžŅ€Ņ‚Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐģĐžĐŗĐžĐ˛Đĩ: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Đ˜ĐˇŅ‡Đ¸ŅŅ‚Đ˛Đ°ĐŊĐĩ ĐŊа ĐģĐžĐŗĐžĐ˛ĐĩŅ‚Đĩ Са ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŗŅ€Đĩ҈Đēи</string> <string name="revanced_debug_logs_clear_buffer_title">Đ˜ĐˇŅ‡Đ¸ŅŅ‚Đ˛Đ°ĐŊĐĩ ĐŊа ĐģĐžĐŗĐžĐ˛ĐĩŅ‚Đĩ Са ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŗŅ€Đĩ҈Đēи</string>
<string name="revanced_debug_logs_clear_buffer_summary">Đ˜ĐˇŅ‡Đ¸ŅŅ‚Đ˛Đ° Đ˛ŅĐ¸Ņ‡Đēи ŅŅŠŅ…Ņ€Đ°ĐŊĐĩĐŊи ĐģĐžĐŗĐžĐ˛Đĩ Са ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŗŅ€Đĩ҈Đēи ĐŊа ReVanced</string> <string name="revanced_debug_logs_clear_buffer_summary">Đ˜ĐˇŅ‡Đ¸ŅŅ‚Đ˛Đ° Đ˛ŅĐ¸Ņ‡Đēи ŅŅŠŅ…Ņ€Đ°ĐŊĐĩĐŊи ĐģĐžĐŗĐžĐ˛Đĩ Са ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŗŅ€Đĩ҈Đēи ĐŊа ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Đ›ĐžĐŗĐžĐ˛ĐĩŅ‚Đĩ ŅĐ° Đ¸ĐˇŅ‡Đ¸ŅŅ‚ĐĩĐŊи</string> <string name="revanced_debug_logs_clear_toast">Đ›ĐžĐŗĐžĐ˛ĐĩŅ‚Đĩ ŅĐ° Đ¸ĐˇŅ‡Đ¸ŅŅ‚ĐĩĐŊи</string>
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_expandable_card_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€Đ°ĐˇĐŗŅŠĐ˛Đ°ĐĩĐŧĐ°Ņ‚Đ° ĐēĐ°Ņ€Ņ‚Đ°</string> <string name="revanced_hide_expandable_card_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€Đ°ĐˇĐŗŅŠĐ˛Đ°ĐĩĐŧĐ°Ņ‚Đ° ĐēĐ°Ņ€Ņ‚Đ°</string>
<string name="revanced_hide_expandable_card_summary_on">Đ Đ°ĐˇĐŗŅŠĐ˛Đ°ĐĩĐŧĐ°Ņ‚Đ° ĐēĐ°Ņ€Ņ‚Đ° ĐŋОд видĐĩĐžĐēĐģиĐŋОвĐĩŅ‚Đĩ Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string> <string name="revanced_hide_expandable_card_summary_on">Đ Đ°ĐˇĐŗŅŠĐ˛Đ°ĐĩĐŧĐ°Ņ‚Đ° ĐēĐ°Ņ€Ņ‚Đ° ĐŋОд видĐĩĐžĐēĐģиĐŋОвĐĩŅ‚Đĩ Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string>
<string name="revanced_hide_expandable_card_summary_off">Đ Đ°ĐˇĐŗŅŠĐ˛Đ°ĐĩĐŧĐ°Ņ‚Đ° ĐēĐ°Ņ€Ņ‚Đ° ĐŋОд видĐĩĐžĐēĐģиĐŋОвĐĩŅ‚Đĩ Đĩ ĐŋĐžĐēаСаĐŊа</string> <string name="revanced_hide_expandable_card_summary_off">Đ Đ°ĐˇĐŗŅŠĐ˛Đ°ĐĩĐŧĐ°Ņ‚Đ° ĐēĐ°Ņ€Ņ‚Đ° ĐŋОд видĐĩĐžĐēĐģиĐŋОвĐĩŅ‚Đĩ Đĩ ĐŋĐžĐēаСаĐŊа</string>
<string name="revanced_hide_feed_survey_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа аĐŊĐēĐĩŅ‚Đ¸ в ĐĩĐŧĐ¸ŅĐ¸Đ¸Ņ‚Đĩ</string>
<string name="revanced_hide_feed_survey_summary_on">АĐŊĐēĐĩŅ‚Đ¸Ņ‚Đĩ Са ĐĩĐŧĐ¸ŅĐ¸Đ¸ ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string>
<string name="revanced_hide_feed_survey_summary_off">АĐŊĐēĐĩŅ‚Đ¸Ņ‚Đĩ Са ĐĩĐŧĐ¸ŅĐ¸Đ¸ ҁĐĩ ĐŋĐžĐēĐ°ĐˇĐ˛Đ°Ņ‚</string>
<string name="revanced_hide_floating_microphone_button_title">ПĐģĐ°Đ˛Đ°Ņ‰ ĐąŅƒŅ‚ĐžĐŊ Са ĐŧиĐēŅ€ĐžŅ„ĐžĐŊа</string> <string name="revanced_hide_floating_microphone_button_title">ПĐģĐ°Đ˛Đ°Ņ‰ ĐąŅƒŅ‚ĐžĐŊ Са ĐŧиĐēŅ€ĐžŅ„ĐžĐŊа</string>
<string name="revanced_hide_floating_microphone_button_summary_on">ПĐģĐ°Đ˛Đ°Ņ‰ ĐąŅƒŅ‚ĐžĐŊ Са ĐŧиĐēŅ€ĐžŅ„ĐžĐŊ ĐŋŅ€Đ¸ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ Đĩ ҁĐēŅ€Đ¸Ņ‚</string> <string name="revanced_hide_floating_microphone_button_summary_on">ПĐģĐ°Đ˛Đ°Ņ‰ ĐąŅƒŅ‚ĐžĐŊ Са ĐŧиĐēŅ€ĐžŅ„ĐžĐŊ ĐŋŅ€Đ¸ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ Đĩ ҁĐēŅ€Đ¸Ņ‚</string>
<string name="revanced_hide_floating_microphone_button_summary_off">ПĐģĐ°Đ˛Đ°Ņ‰Đ¸ŅŅ‚ ĐąŅƒŅ‚ĐžĐŊ Са ĐŧиĐēŅ€ĐžŅ„ĐžĐŊ в Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_floating_microphone_button_summary_off">ПĐģĐ°Đ˛Đ°Ņ‰Đ¸ŅŅ‚ ĐąŅƒŅ‚ĐžĐŊ Са ĐŧиĐēŅ€ĐžŅ„ĐžĐŊ в Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž Đĩ ĐŋĐžĐēаСаĐŊ</string>
@@ -192,7 +189,7 @@ Second \"item\" text"</string>
<string name="revanced_hide_movies_section_summary_on">ĐĄĐĩĐēŅ†Đ¸ŅŅ‚Đ° ҁ ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸ Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string> <string name="revanced_hide_movies_section_summary_on">ĐĄĐĩĐēŅ†Đ¸ŅŅ‚Đ° ҁ ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸ Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string>
<string name="revanced_hide_movies_section_summary_off">РаСдĐĩĐģŅŠŅ‚ Са Ņ„Đ¸ĐģĐŧи Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_movies_section_summary_off">РаСдĐĩĐģŅŠŅ‚ Са Ņ„Đ¸ĐģĐŧи Đĩ ĐŋĐžĐēаСаĐŊ</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions 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_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ŅƒĐ˛ĐĩĐ´ĐžĐŧŅĐ˛Đ°ĐŊĐĩ Đĩ ҁĐēŅ€Đ¸Ņ‚</string>
<string name="revanced_hide_notify_me_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ŅƒĐ˛ĐĩĐ´ĐžĐŧŅĐ˛Đ°ĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_notify_me_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ŅƒĐ˛ĐĩĐ´ĐžĐŧŅĐ˛Đ°ĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string>
@@ -204,6 +201,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_show_more_button_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐąŅƒŅ‚ĐžĐŊа \"ПоĐēаĐļи ĐžŅ‰Đĩ\"</string> <string name="revanced_hide_show_more_button_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐąŅƒŅ‚ĐžĐŊа \"ПоĐēаĐļи ĐžŅ‰Đĩ\"</string>
<string name="revanced_hide_show_more_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐžŅ‰Đĩ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ Đĩ ҁĐēŅ€Đ¸Ņ‚</string> <string name="revanced_hide_show_more_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐžŅ‰Đĩ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ Đĩ ҁĐēŅ€Đ¸Ņ‚</string>
<string name="revanced_hide_show_more_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐžŅ‰Đĩ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_show_more_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐžŅ‰Đĩ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string>
<string name="revanced_hide_surveys_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžŅƒŅ‡Đ˛Đ°ĐŊĐ¸Ņ</string>
<string name="revanced_hide_surveys_summary_on">АĐŊĐēĐĩŅ‚Đ¸Ņ‚Đĩ ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string>
<string name="revanced_hide_surveys_summary_off">АĐŊĐēĐĩŅ‚Đ¸Ņ‚Đĩ ŅĐ° ĐŋĐžĐēаСаĐŊи</string>
<string name="revanced_hide_ticket_shelf_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€Đ°Ņ„Ņ‚Đ° Са йиĐģĐĩŅ‚Đ¸</string> <string name="revanced_hide_ticket_shelf_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€Đ°Ņ„Ņ‚Đ° Са йиĐģĐĩŅ‚Đ¸</string>
<string name="revanced_hide_ticket_shelf_summary_on">Đ Đ°Ņ„Ņ‚ŅŠŅ‚ Са йиĐģĐĩŅ‚Đ¸ Đĩ ҁĐēŅ€Đ¸Ņ‚</string> <string name="revanced_hide_ticket_shelf_summary_on">Đ Đ°Ņ„Ņ‚ŅŠŅ‚ Са йиĐģĐĩŅ‚Đ¸ Đĩ ҁĐēŅ€Đ¸Ņ‚</string>
<string name="revanced_hide_ticket_shelf_summary_off">Đ Đ°Ņ„Ņ‚ŅŠŅ‚ Са йиĐģĐĩŅ‚Đ¸ Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_ticket_shelf_summary_off">Đ Đ°Ņ„Ņ‚ŅŠŅ‚ Са йиĐģĐĩŅ‚Đ¸ Đĩ ĐŋĐžĐēаСаĐŊ</string>
@@ -251,8 +251,8 @@ Second \"item\" text"</string>
<string name="revanced_hide_timed_reactions_summary_on">Đ’Ņ€ĐĩĐŧĐĩĐ˛Đ¸Ņ‚Đĩ Ņ€ĐĩаĐēŅ†Đ¸Đ¸ ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string> <string name="revanced_hide_timed_reactions_summary_on">Đ’Ņ€ĐĩĐŧĐĩĐ˛Đ¸Ņ‚Đĩ Ņ€ĐĩаĐēŅ†Đ¸Đ¸ ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string>
<string name="revanced_hide_timed_reactions_summary_off">Đ’Ņ€ĐĩĐŧĐĩĐ˛Đ¸Ņ‚Đĩ Ņ€ĐĩаĐēŅ†Đ¸Đ¸ ҁĐĩ ĐŋĐžĐēĐ°ĐˇĐ˛Đ°Ņ‚</string> <string name="revanced_hide_timed_reactions_summary_off">Đ’Ņ€ĐĩĐŧĐĩĐ˛Đ¸Ņ‚Đĩ Ņ€ĐĩаĐēŅ†Đ¸Đ¸ ҁĐĩ ĐŋĐžĐēĐ°ĐˇĐ˛Đ°Ņ‚</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа \"AI-ĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€Đ°ĐŊĐž видĐĩĐž Ņ€ĐĩĐˇŅŽĐŧĐĩ\"</string> <string name="revanced_hide_ai_generated_video_summary_section_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа \"AI-ĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€Đ°ĐŊĐž видĐĩĐž Ņ€ĐĩĐˇŅŽĐŧĐĩ\"</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">ĐĄĐēŅ€Đ¸Ņ‚ Đĩ Ņ€Đ°ĐˇĐ´ĐĩĐģŅŠŅ‚ ҁ видĐĩĐž Ņ€ĐĩĐˇŅŽĐŧĐĩ</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_on">РаСдĐĩĐģŅŠŅ‚ Са Ņ€ĐĩĐˇŅŽĐŧĐĩ ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ, ĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€Đ°ĐŊи ĐžŅ‚ AI, Đĩ ҁĐēŅ€Đ¸Ņ‚</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">ПоĐēаСва ҁĐĩ Ņ€Đ°ĐˇĐ´ĐĩĐģŅŠŅ‚ ҁ видĐĩĐž Ņ€ĐĩĐˇŅŽĐŧĐĩ</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_off">РаСдĐĩĐģŅŠŅ‚ ҁ ĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€Đ°ĐŊи ĐžŅ‚ AI Ņ€ĐĩĐˇŅŽĐŧĐĩŅ‚Đ° ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string>
<string name="revanced_hide_ask_section_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа „ПоĐŋĐ¸Ņ‚Đ°Đšâ€œ</string> <string name="revanced_hide_ask_section_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа „ПоĐŋĐ¸Ņ‚Đ°Đšâ€œ</string>
<string name="revanced_hide_ask_section_summary_on">ĐĄĐēŅ€Đ¸Ņ‚ Ņ€Đ°ĐˇĐ´ĐĩĐģ „ПоĐŋĐ¸Ņ‚Đ°Đšâ€œ</string> <string name="revanced_hide_ask_section_summary_on">ĐĄĐēŅ€Đ¸Ņ‚ Ņ€Đ°ĐˇĐ´ĐĩĐģ „ПоĐŋĐ¸Ņ‚Đ°Đšâ€œ</string>
<string name="revanced_hide_ask_section_summary_off">ПоĐēаСваĐŊĐĩ ĐŊа Ņ€Đ°ĐˇĐ´ĐĩĐģ „ПоĐŋĐ¸Ņ‚Đ°Đšâ€œ</string> <string name="revanced_hide_ask_section_summary_off">ПоĐēаСваĐŊĐĩ ĐŊа Ņ€Đ°ĐˇĐ´ĐĩĐģ „ПоĐŋĐ¸Ņ‚Đ°Đšâ€œ</string>
@@ -280,19 +280,19 @@ Second \"item\" text"</string>
<string name="revanced_hide_description_components_screen_title">ОĐŋĐ¸ŅĐ°ĐŊиĐĩ ĐŊа видĐĩĐžŅ‚Đž</string> <string name="revanced_hide_description_components_screen_title">ОĐŋĐ¸ŅĐ°ĐŊиĐĩ ĐŊа видĐĩĐžŅ‚Đž</string>
<string name="revanced_hide_description_components_screen_summary">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚Đ¸Ņ‚Đĩ Са ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩŅ‚Đĩ</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_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_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в ĐĩĐŧĐ¸ŅĐ¸Đ¸</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đ¸ в ĐĩĐŧĐ¸ŅĐ¸Đ¸</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> <string name="revanced_hide_filter_bar_feed_in_feed_summary_off">ПоĐēаСаĐŊи в ĐĩĐŧĐ¸ŅĐ¸Đ¸</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ°</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đ¸ в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ°</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">ПоĐēаСаĐŊи в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ°</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">ПоĐēаСаĐŊĐž в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в ŅŅ€ĐžĐ´ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в ŅŅ€ĐžĐ´ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в ŅŅ€ĐžĐ´ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в ŅŅ€ĐžĐ´ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">ПоĐēаСаĐŊĐž в ŅŅ€ĐžĐ´ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">ПоĐēаСаĐŊĐž в ŅŅ€ĐžĐ´ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">ПоĐēаСаĐŊĐž в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐ¸ŅŅ‚Đ°</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">ПоĐēаСаĐŊĐž в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐ¸ŅŅ‚Đ°</string>
<string name="revanced_channel_screen_title">ĐĄŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đ° ĐŊа ĐēаĐŊаĐģа</string> <string name="revanced_channel_screen_title">ĐĄŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đ° ĐŊа ĐēаĐŊаĐģа</string>
<string name="revanced_channel_screen_summary">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚Đ¸ ĐŊа ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đ°Ņ‚Đ° ĐŊа ĐēаĐŊаĐģа</string> <string name="revanced_channel_screen_summary">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚Đ¸ ĐŊа ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đ°Ņ‚Đ° ĐŊа ĐēаĐŊаĐģа</string>
<!-- 'For You' should be translated using the same localized wording YouTube displays. --> <!-- 'For You' should be translated using the same localized wording YouTube displays. -->
@@ -315,12 +315,12 @@ Second \"item\" text"</string>
<string name="revanced_hide_visit_store_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ â€žĐŸĐžŅĐĩŅ‚ĐĩŅ‚Đĩ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊа“ Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_visit_store_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ â€žĐŸĐžŅĐĩŅ‚ĐĩŅ‚Đĩ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊа“ Đĩ ĐŋĐžĐēаСаĐŊ</string>
<string name="revanced_comments_screen_title">КоĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸</string> <string name="revanced_comments_screen_title">КоĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸</string>
<string name="revanced_comments_screen_summary">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ҁĐĩĐēŅ†Đ¸ŅŅ‚Đ° Са ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸</string> <string name="revanced_comments_screen_summary">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ҁĐĩĐēŅ†Đ¸ŅŅ‚Đ° Са ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸</string>
<string name="revanced_hide_comments_ai_chat_summary_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI Chat</string> <string name="revanced_hide_comments_ai_chat_summary_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI Ņ‡Đ°Ņ‚Đ°</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа Ņ‡Đ°Ņ‚Đ° Đĩ ҁĐēŅ€Đ¸Ņ‚Đž</string> <string name="revanced_hide_comments_ai_chat_summary_summary_on">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI Ņ‡Đ°Ņ‚Đ° Đĩ ҁĐēŅ€Đ¸Ņ‚Đž</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа Ņ‡Đ°Ņ‚Đ° Đĩ ĐŋĐžĐēаСаĐŊĐž</string> <string name="revanced_hide_comments_ai_chat_summary_summary_off">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI Ņ‡Đ°Ņ‚Đ° Đĩ ĐŋĐžĐēаСаĐŊĐž</string>
<string name="revanced_hide_comments_ai_summary_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Ņ‚Đĩ</string> <string name="revanced_hide_comments_ai_summary_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ€ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Ņ‚Đĩ</string>
<string name="revanced_hide_comments_ai_summary_summary_on">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Ņ‚Đĩ Đĩ ҁĐēŅ€Đ¸Ņ‚Đž</string> <string name="revanced_hide_comments_ai_summary_summary_on">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸ Đĩ ҁĐēŅ€Đ¸Ņ‚Đž</string>
<string name="revanced_hide_comments_ai_summary_summary_off">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Ņ‚Đĩ Đĩ ĐŋĐžĐēаСаĐŊĐž</string> <string name="revanced_hide_comments_ai_summary_summary_off">Đ ĐĩĐˇŅŽĐŧĐĩŅ‚Đž ĐŊа AI ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸ Đĩ ĐŋĐžĐēаСаĐŊĐž</string>
<string name="revanced_hide_comments_channel_guidelines_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐŊĐ°ŅĐžĐēĐ¸Ņ‚Đĩ ĐŊа ĐēаĐŊаĐģа</string> <string name="revanced_hide_comments_channel_guidelines_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐŊĐ°ŅĐžĐēĐ¸Ņ‚Đĩ ĐŊа ĐēаĐŊаĐģа</string>
<string name="revanced_hide_comments_channel_guidelines_summary_on">ĐŖĐēаСаĐŊĐ¸ŅŅ‚Đ° Са ĐēаĐŊаĐģа ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string> <string name="revanced_hide_comments_channel_guidelines_summary_on">ĐŖĐēаСаĐŊĐ¸ŅŅ‚Đ° Са ĐēаĐŊаĐģа ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string>
<string name="revanced_hide_comments_channel_guidelines_summary_off">ĐŖĐēаСаĐŊĐ¸ŅŅ‚Đ° Са ĐēаĐŊаĐģа ŅĐ° ĐŋĐžĐēаСаĐŊи</string> <string name="revanced_hide_comments_channel_guidelines_summary_off">ĐŖĐēаСаĐŊĐ¸ŅŅ‚Đ° Са ĐēаĐŊаĐģа ŅĐ° ĐŋĐžĐēаСаĐŊи</string>
@@ -419,7 +419,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_shopping_links_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Đ˛Ņ€ŅŠĐˇĐēи Са ĐŋĐ°ĐˇĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐĩ</string> <string name="revanced_hide_shopping_links_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Đ˛Ņ€ŅŠĐˇĐēи Са ĐŋĐ°ĐˇĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐĩ</string>
<string name="revanced_hide_shopping_links_summary_on">ЛиĐŊĐēОвĐĩŅ‚Đĩ Са ĐŋĐ°ĐˇĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐĩ Đ˛ŅŠĐ˛ видĐĩĐž ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩŅ‚Đž ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string> <string name="revanced_hide_shopping_links_summary_on">ЛиĐŊĐēОвĐĩŅ‚Đĩ Са ĐŋĐ°ĐˇĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐĩ Đ˛ŅŠĐ˛ видĐĩĐž ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩŅ‚Đž ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸</string>
<string name="revanced_hide_shopping_links_summary_off">ЛиĐŊĐēОвĐĩŅ‚Đĩ Са ĐŋĐ°ĐˇĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐĩ в ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩŅ‚Đž ĐŊа видĐĩĐžĐēĐģиĐŋа ŅĐ° ĐŋĐžĐēаСаĐŊи</string> <string name="revanced_hide_shopping_links_summary_off">ЛиĐŊĐēОвĐĩŅ‚Đĩ Са ĐŋĐ°ĐˇĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐĩ в ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩŅ‚Đž ĐŊа видĐĩĐžĐēĐģиĐŋа ŅĐ° ĐŋĐžĐēаСаĐŊи</string>
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_view_products_banner_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа йаĐŊĐĩŅ€Đ° â€žĐŸŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸â€œ</string> <string name="revanced_hide_view_products_banner_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа йаĐŊĐĩŅ€Đ° â€žĐŸŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸â€œ</string>
<string name="revanced_hide_view_products_banner_summary_on">БаĐŊĐĩŅ€ŅŠŅ‚ Са ĐŋŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸ Đ˛ŅŠĐ˛ видĐĩĐž ĐŊĐ°ŅĐģĐ°ĐŗĐ˛Đ°ĐŊĐĩŅ‚Đž Đĩ ҁĐēŅ€Đ¸Ņ‚</string> <string name="revanced_hide_view_products_banner_summary_on">БаĐŊĐĩŅ€ŅŠŅ‚ Са ĐŋŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸ Đ˛ŅŠĐ˛ видĐĩĐž ĐŊĐ°ŅĐģĐ°ĐŗĐ˛Đ°ĐŊĐĩŅ‚Đž Đĩ ҁĐēŅ€Đ¸Ņ‚</string>
<string name="revanced_hide_view_products_banner_summary_off">БаĐŊĐĩŅ€ŅŠŅ‚ Са ĐŋŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸ Đ˛ŅŠĐ˛ видĐĩĐž ĐŊĐ°ŅĐģĐ°ĐŗĐ˛Đ°ĐŊĐĩŅ‚Đž Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_hide_view_products_banner_summary_off">БаĐŊĐĩŅ€ŅŠŅ‚ Са ĐŋŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸ Đ˛ŅŠĐ˛ видĐĩĐž ĐŊĐ°ŅĐģĐ°ĐŗĐ˛Đ°ĐŊĐĩŅ‚Đž Đĩ ĐŋĐžĐēаСаĐŊ</string>
@@ -453,7 +452,7 @@ Second \"item\" text"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">ДиаĐģĐžĐŗĐžĐ˛Đ¸ŅŅ‚ ĐŋŅ€ĐžĐˇĐžŅ€Đĩ҆ ҉Đĩ ĐąŅŠĐ´Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_remove_viewer_discretion_dialog_summary_off">ДиаĐģĐžĐŗĐžĐ˛Đ¸ŅŅ‚ ĐŋŅ€ĐžĐˇĐžŅ€Đĩ҆ ҉Đĩ ĐąŅŠĐ´Đĩ ĐŋĐžĐēаСаĐŊ</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">ĐĸаСи Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ ĐŊĐĩ СаОйиĐēаĐģŅ Đ˛ŅŠĐˇŅ€Đ°ŅŅ‚ĐžĐ˛ĐžŅ‚Đž ĐžĐŗŅ€Đ°ĐŊĐ¸Ņ‡ĐĩĐŊиĐĩ. ĐĸŅ ĐŋŅ€ĐžŅŅ‚Đž ĐŋŅ€Đ¸ĐĩĐŧа Đ˛ŅŠĐˇŅ€Đ°ŅŅ‚ĐžĐ˛Đ°Ņ‚Đ° ĐŗŅ€Đ°ĐŊĐ¸Ņ†Đ° Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž.</string> <string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">ĐĸаСи Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ ĐŊĐĩ СаОйиĐēаĐģŅ Đ˛ŅŠĐˇŅ€Đ°ŅŅ‚ĐžĐ˛ĐžŅ‚Đž ĐžĐŗŅ€Đ°ĐŊĐ¸Ņ‡ĐĩĐŊиĐĩ. ĐĸŅ ĐŋŅ€ĐžŅŅ‚Đž ĐŋŅ€Đ¸ĐĩĐŧа Đ˛ŅŠĐˇŅ€Đ°ŅŅ‚ĐžĐ˛Đ°Ņ‚Đ° ĐŗŅ€Đ°ĐŊĐ¸Ņ†Đ° Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž.</string>
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">ДĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžĐŋ҃ҁĐēаĐŊĐĩ ĐŊа ĐŗĐģава ҁ двОКĐŊĐž Đ´ĐžĐēĐžŅĐ˛Đ°ĐŊĐĩ</string> <string name="revanced_disable_chapter_skip_double_tap_title">ДĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžĐŋ҃ҁĐēаĐŊĐĩ ĐŊа ĐŗĐģава ҁ двОКĐŊĐž Đ´ĐžĐēĐžŅĐ˛Đ°ĐŊĐĩ</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">ДвойĐŊĐžŅ‚Đž Đ´ĐžĐēĐžŅĐ˛Đ°ĐŊĐĩ ĐŊиĐēĐžĐŗĐ° ĐŊĐĩ ĐŧĐžĐļĐĩ да ĐŋŅ€ĐĩдиСвиĐēа ĐŋŅ€ĐžĐŋ҃ҁĐēаĐŊĐĩ Đ´Đž ҁĐģĐĩĐ´Đ˛Đ°Ņ‰Đ°/ĐŋŅ€ĐĩĐ´Đ¸ŅˆĐŊа ĐŗĐģава</string> <string name="revanced_disable_chapter_skip_double_tap_summary_on">ДвойĐŊĐžŅ‚Đž Đ´ĐžĐēĐžŅĐ˛Đ°ĐŊĐĩ ĐŊиĐēĐžĐŗĐ° ĐŊĐĩ ĐŧĐžĐļĐĩ да ĐŋŅ€ĐĩдиСвиĐēа ĐŋŅ€ĐžĐŋ҃ҁĐēаĐŊĐĩ Đ´Đž ҁĐģĐĩĐ´Đ˛Đ°Ņ‰Đ°/ĐŋŅ€ĐĩĐ´Đ¸ŅˆĐŊа ĐŗĐģава</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_off">ДвойĐŊĐžŅ‚Đž Đ´ĐžĐēĐžŅĐ˛Đ°ĐŊĐĩ ĐŧĐžĐļĐĩ ĐŋĐžĐŊŅĐēĐžĐŗĐ° да ĐŋŅ€ĐĩдиСвиĐēа ĐŋŅ€ĐžĐŋ҃ҁĐēаĐŊĐĩ Đ´Đž ҁĐģĐĩĐ´Đ˛Đ°Ņ‰Đ°/ĐŋŅ€ĐĩĐ´Đ¸ŅˆĐŊа ĐŗĐģава</string> <string name="revanced_disable_chapter_skip_double_tap_summary_off">ДвойĐŊĐžŅ‚Đž Đ´ĐžĐēĐžŅĐ˛Đ°ĐŊĐĩ ĐŧĐžĐļĐĩ ĐŋĐžĐŊŅĐēĐžĐŗĐ° да ĐŋŅ€ĐĩдиСвиĐēа ĐŋŅ€ĐžĐŋ҃ҁĐēаĐŊĐĩ Đ´Đž ҁĐģĐĩĐ´Đ˛Đ°Ņ‰Đ°/ĐŋŅ€ĐĩĐ´Đ¸ŅˆĐŊа ĐŗĐģава</string>
@@ -469,8 +468,15 @@ Second \"item\" text"</string>
<string name="revanced_external_downloader_action_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ ĐžŅ‚Đ˛Đ°Ņ€Ņ Đ¸ĐˇĐąŅ€Đ°ĐŊĐžŅ‚Đž ĐžŅ‚ Đ’Đ°Ņ Đ˛ŅŠĐŊ҈ĐŊĐž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ</string> <string name="revanced_external_downloader_action_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ ĐžŅ‚Đ˛Đ°Ņ€Ņ Đ¸ĐˇĐąŅ€Đ°ĐŊĐžŅ‚Đž ĐžŅ‚ Đ’Đ°Ņ Đ˛ŅŠĐŊ҈ĐŊĐž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ</string>
<string name="revanced_external_downloader_action_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ ĐžŅ‚Đ˛Đ°Ņ€Ņ Đ˛ĐŗŅ€Đ°Đ´ĐĩĐŊĐžŅ‚Đž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ</string> <string name="revanced_external_downloader_action_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ ĐžŅ‚Đ˛Đ°Ņ€Ņ Đ˛ĐŗŅ€Đ°Đ´ĐĩĐŊĐžŅ‚Đž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ</string>
<string name="revanced_external_downloader_name_title">ИĐŧĐĩ ĐŊа ĐŋаĐēĐĩŅ‚Đ° ĐŊа Đ¸ĐˇŅ‚ĐĩĐŗĐģŅŅ‰ĐžŅ‚Đž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ</string> <string name="revanced_external_downloader_name_title">ИĐŧĐĩ ĐŊа ĐŋаĐēĐĩŅ‚Đ° ĐŊа Đ¸ĐˇŅ‚ĐĩĐŗĐģŅŅ‰ĐžŅ‚Đž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ</string>
<string name="revanced_external_downloader_name_summary">ИĐŧĐĩ ĐŊа ĐŋаĐēĐĩŅ‚Đ° ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ, ĐēĐ°Ņ‚Đž NewPipe иĐģи Seal</string> <string name="revanced_external_downloader_name_summary">ИĐŧĐĩ ĐŊа ĐŋаĐēĐĩŅ‚Đ° ĐŊа Đ˛Đ°ŅˆĐĩŅ‚Đž иĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐŊĐž Đ˛ŅŠĐŊ҈ĐŊĐž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Са Đ¸ĐˇŅ‚ĐĩĐŗĐģŅĐŊĐĩ</string>
<string name="revanced_external_downloader_other_item_hint">Đ’ŅŠĐ˛ĐĩĐ´ĐĩŅ‚Đĩ иĐŧĐĩŅ‚Đž ĐŊа ĐŋаĐēĐĩŅ‚Đ°</string>
<string name="revanced_external_downloader_other_item">Đ”Ņ€ŅƒĐŗĐ¸</string>
<string name="revanced_external_downloader_not_found_title">ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž ĐŊĐĩ Đĩ иĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐŊĐž</string>
<string name="revanced_external_downloader_not_installed_warning">%s ĐŊĐĩ Đĩ иĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐŊ. ИĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐšŅ‚Đĩ ĐŗĐž.</string> <string name="revanced_external_downloader_not_installed_warning">%s ĐŊĐĩ Đĩ иĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐŊ. ИĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐšŅ‚Đĩ ĐŗĐž.</string>
<string name="revanced_external_downloader_package_not_found_warning">"НĐĩ ĐŧĐžĐļĐĩ да ĐąŅŠĐ´Đĩ ĐŊаĐŧĐĩŅ€ĐĩĐŊĐž иĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐŊĐž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ҁ иĐŧĐĩ ĐŊа ĐŋаĐēĐĩŅ‚: %s
ĐŸŅ€ĐžĐ˛ĐĩŅ€ĐĩŅ‚Đĩ даĐģи иĐŧĐĩŅ‚Đž ĐŊа ĐŋаĐēĐĩŅ‚Đ° Đĩ ĐŋŅ€Đ°Đ˛Đ¸ĐģĐŊĐž и ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž Đĩ иĐŊŅŅ‚Đ°ĐģĐ¸Ņ€Đ°ĐŊĐž"</string>
<string name="revanced_external_downloader_empty_warning">ИĐŧĐĩŅ‚Đž ĐŊа ĐŋаĐēĐĩŅ‚Đ° ĐŊĐĩ ĐŧĐžĐļĐĩ да ĐąŅŠĐ´Đĩ ĐŋŅ€Đ°ĐˇĐŊĐž</string>
</patch> </patch>
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch"> <patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">ДĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐļĐĩŅŅ‚Đ° Са Ņ‚ĐžŅ‡ĐŊĐž Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ</string> <string name="revanced_disable_precise_seeking_gesture_title">ДĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐļĐĩŅŅ‚Đ° Са Ņ‚ĐžŅ‡ĐŊĐž Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ</string>
@@ -730,27 +736,28 @@ Second \"item\" text"</string>
<string name="revanced_disable_rolling_number_animations_summary_off">АĐŊиĐŧĐ°Ņ†Đ¸ŅŅ‚Đ° Đĩ аĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊа</string> <string name="revanced_disable_rolling_number_animations_summary_off">АĐŊиĐŧĐ°Ņ†Đ¸ŅŅ‚Đ° Đĩ аĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊа</string>
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<string name="revanced_hide_seekbar_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐģĐĩĐŊŅ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŊа ĐŋĐģĐĩĐšŅŠŅ€Đ°</string> <string name="revanced_hide_seekbar_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐģĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ ĐŊа видĐĩĐž ĐŋĐģĐĩĐšŅŠŅ€</string>
<string name="revanced_hide_seekbar_summary_on">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŊа ĐŋĐģĐĩĐšŅŠŅ€Đ° Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string> <string name="revanced_hide_seekbar_summary_on">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŊа ĐŋĐģĐĩĐšŅŠŅ€Đ° Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string>
<string name="revanced_hide_seekbar_summary_off">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŊа ĐŋĐģĐĩĐšŅŠŅ€Đ° ҁĐĩ ĐŋĐžĐēаСва</string> <string name="revanced_hide_seekbar_summary_off">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŊа ĐŋĐģĐĩĐšŅŠŅ€Đ° ҁĐĩ ĐŋĐžĐēаСва</string>
<string name="revanced_hide_seekbar_thumbnail_title">ĐĄĐēŅ€. ĐģĐĩĐŊŅ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŋŅ€Đ¸ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸Ņ‚Đĩ</string> <!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
<string name="revanced_hide_seekbar_thumbnail_summary_on">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŋŅ€Đ¸ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸Ņ‚Đĩ Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string> <string name="revanced_hide_seekbar_thumbnail_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐģĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ ĐŊа ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸ ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Đ˛Ņ€ĐĩĐŧĐĩ ĐŋŅ€Đ¸ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸Ņ‚Đĩ ҁĐĩ ĐŋĐžĐēаСва</string> <string name="revanced_hide_seekbar_thumbnail_summary_on">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ ĐŊа ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸ ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ Đĩ ҁĐēŅ€Đ¸Ņ‚Đ°</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">ЛĐĩĐŊŅ‚Đ°Ņ‚Đ° Са Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ ĐŊа ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸ ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ Đĩ ĐŋĐžĐēаСаĐŊа</string>
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<string name="revanced_shorts_player_screen_title">Đ˜ĐŗŅ€Đ°Ņ‡ ĐŊа Shorts</string> <string name="revanced_shorts_player_screen_title">Đ˜ĐŗŅ€Đ°Ņ‡ ĐŊа Shorts</string>
<string name="revanced_shorts_player_screen_summary">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ иĐģи ĐŋĐžĐēаСваĐŊĐĩ ĐŊа ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚Đ¸ в Shorts ĐŋĐģĐĩĐšŅŠŅ€Đ°</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. --> <!-- '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_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Shorts в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° ĐĐ°Ņ‡Đ°ĐģĐž</string>
<string name="revanced_hide_shorts_home_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° ĐĐ°Ņ‡Đ°ĐģĐž и ŅĐ˛ŅŠŅ€ĐˇĐ°ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string> <string name="revanced_hide_shorts_home_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° ĐĐ°Ņ‡Đ°ĐģĐž и ŅĐ˛ŅŠŅ€ĐˇĐ°ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
<string name="revanced_hide_shorts_home_summary_off">ПоĐēаСаĐŊĐž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° ĐĐ°Ņ‡Đ°ĐģĐž и ŅĐ˛ŅŠŅ€ĐˇĐ°ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string> <string name="revanced_hide_shorts_home_summary_off">ПоĐēаСаĐŊĐž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° ĐĐ°Ņ‡Đ°ĐģĐž и ŅĐ˛ŅŠŅ€ĐˇĐ°ĐŊи видĐĩĐžĐēĐģиĐŋОвĐĩ</string>
<string name="revanced_hide_shorts_search_title">Shorts в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_shorts_search_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đ¸ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_shorts_search_summary_off">ПоĐēаСаĐŊĐž в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. --> <!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
<string name="revanced_hide_shorts_subscriptions_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Shorts в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° АйОĐŊаĐŧĐĩĐŊŅ‚Đ¸</string> <string name="revanced_hide_shorts_subscriptions_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Shorts в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° АйОĐŊаĐŧĐĩĐŊŅ‚Đ¸</string>
<string name="revanced_hide_shorts_subscriptions_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° АйОĐŊаĐŧĐĩĐŊŅ‚Đ¸</string> <string name="revanced_hide_shorts_subscriptions_summary_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° АйОĐŊаĐŧĐĩĐŊŅ‚Đ¸</string>
<string name="revanced_hide_shorts_subscriptions_summary_off">ПоĐēаСаĐŊĐž в ĐĩĐŧĐ¸ŅĐ¸ŅŅ‚Đ° АйОĐŊаĐŧĐĩĐŊŅ‚Đ¸</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">ĐĄĐēŅ€Đ¸Ņ‚Đ¸ в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_shorts_search_summary_off">ПоĐēаСаĐŊĐž в Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸Ņ‚Đĩ ĐžŅ‚ Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž</string>
<string name="revanced_hide_shorts_history_title">ĐĄĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ŅˆĐžŅ€Ņ‚Đ¸Ņ‚Đĩ в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</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_on">ĐĄĐēŅ€Đ¸Ņ‚Đž в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string>
<string name="revanced_hide_shorts_history_summary_off">ПоĐēаСва ҁĐĩ в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string> <string name="revanced_hide_shorts_history_summary_off">ПоĐēаСва ҁĐĩ в Đ¸ŅŅ‚ĐžŅ€Đ¸ŅŅ‚Đ° ĐŊа ĐŗĐģĐĩдаĐŊĐĩ</string>
@@ -1190,8 +1197,6 @@ Second \"item\" text"</string>
ĐĸОва ҉Đĩ ĐŋŅ€ĐžĐŧĐĩĐŊи Đ˛ŅŠĐŊ҈ĐŊĐ¸Ņ вид и Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸Ņ‚Đĩ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž, ĐŊĐž ĐŧĐžĐļĐĩ да Đ˛ŅŠĐˇĐŊиĐēĐŊĐ°Ņ‚ ĐŊĐĩиСвĐĩҁ҂ĐŊи ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ‡ĐŊи ĐĩŅ„ĐĩĐēŅ‚Đ¸. ĐĸОва ҉Đĩ ĐŋŅ€ĐžĐŧĐĩĐŊи Đ˛ŅŠĐŊ҈ĐŊĐ¸Ņ вид и Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸Ņ‚Đĩ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž, ĐŊĐž ĐŧĐžĐļĐĩ да Đ˛ŅŠĐˇĐŊиĐēĐŊĐ°Ņ‚ ĐŊĐĩиСвĐĩҁ҂ĐŊи ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ‡ĐŊи ĐĩŅ„ĐĩĐēŅ‚Đ¸.
АĐēĐž ĐŋĐž-ĐēҊҁĐŊĐž ĐąŅŠĐ´Đĩ иСĐēĐģŅŽŅ‡ĐĩĐŊĐž, ĐŋŅ€ĐĩĐŋĐžŅ€ŅŠŅ‡Đ¸Ņ‚ĐĩĐģĐŊĐž Đĩ да Đ¸ĐˇŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đĩ даĐŊĐŊĐ¸Ņ‚Đĩ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž, Са да ĐŋŅ€ĐĩĐ´ĐžŅ‚Đ˛Ņ€Đ°Ņ‚Đ¸Ņ‚Đĩ ĐŗŅ€Đĩ҈Đēи в ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēĐ¸Ņ иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ."</string> АĐēĐž ĐŋĐž-ĐēҊҁĐŊĐž ĐąŅŠĐ´Đĩ иСĐēĐģŅŽŅ‡ĐĩĐŊĐž, ĐŋŅ€ĐĩĐŋĐžŅ€ŅŠŅ‡Đ¸Ņ‚ĐĩĐģĐŊĐž Đĩ да Đ¸ĐˇŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đĩ даĐŊĐŊĐ¸Ņ‚Đĩ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž, Са да ĐŋŅ€ĐĩĐ´ĐžŅ‚Đ˛Ņ€Đ°Ņ‚Đ¸Ņ‚Đĩ ĐŗŅ€Đĩ҈Đēи в ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēĐ¸Ņ иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ."</string>
<!-- 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. -->
<string name="revanced_spoof_app_version_target_title">ПодĐģŅŠĐŗĐ˛Đ°ĐŊĐĩ Са вĐĩŅ€ŅĐ¸ŅŅ‚Đ° ĐŊа</string> <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_1">19.35.36 - Đ’ŅŠĐˇŅŅ‚Đ°ĐŊОвĐĩŅ‚Đĩ ŅŅ‚Đ°Ņ€Đ¸Ņ‚Đĩ иĐēĐžĐŊи ĐŊа Shorts в ĐŋĐģĐĩĐšŅŠŅ€Đ°</string>
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Đ’ŅŠĐˇŅŅ‚Đ°ĐŊĐžĐ˛ŅĐ˛Đ°ĐŊĐĩ ĐŊа ŅŅ‚Đ°Ņ€Đ¸ иĐēĐžĐŊи Са ĐŊĐ°Đ˛Đ¸ĐŗĐ°Ņ†Đ¸Ņ</string> <string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Đ’ŅŠĐˇŅŅ‚Đ°ĐŊĐžĐ˛ŅĐ˛Đ°ĐŊĐĩ ĐŊа ŅŅ‚Đ°Ņ€Đ¸ иĐēĐžĐŊи Са ĐŊĐ°Đ˛Đ¸ĐŗĐ°Ņ†Đ¸Ņ</string>
@@ -1460,10 +1465,18 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Đĩ ĐŋĐžĐēаСаĐŊ. ДоĐēĐžŅĐŊĐĩŅ‚Đĩ и ĐˇĐ°Đ´Ņ€ŅŠĐļŅ‚Đĩ, Са да Đ˛ŅŠŅ€ĐŊĐĩŅ‚Đĩ ҁĐēĐžŅ€ĐžŅŅ‚Ņ‚Đ° ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ ĐēҊĐŧ ŅŅ‚ĐžĐšĐŊĐžŅŅ‚Ņ‚Đ° ĐŋĐž ĐŋĐžĐ´Ņ€Đ°ĐˇĐąĐ¸Ņ€Đ°ĐŊĐĩ</string> <string name="revanced_playback_speed_dialog_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Đĩ ĐŋĐžĐēаСаĐŊ. ДоĐēĐžŅĐŊĐĩŅ‚Đĩ и ĐˇĐ°Đ´Ņ€ŅŠĐļŅ‚Đĩ, Са да Đ˛ŅŠŅ€ĐŊĐĩŅ‚Đĩ ҁĐēĐžŅ€ĐžŅŅ‚Ņ‚Đ° ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ ĐēҊĐŧ ŅŅ‚ĐžĐšĐŊĐžŅŅ‚Ņ‚Đ° ĐŋĐž ĐŋĐžĐ´Ņ€Đ°ĐˇĐąĐ¸Ņ€Đ°ĐŊĐĩ</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ ĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string> <string name="revanced_playback_speed_dialog_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ ĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
<string name="revanced_video_quality_dialog_button_title">ПоĐēаĐļи ĐąŅƒŅ‚ĐžĐŊа Са ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đž ĐŊа видĐĩĐžŅ‚Đž</string>
<string name="revanced_video_quality_dialog_button_summary_on">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ Đĩ ĐŋĐžĐēаСаĐŊ. ДоĐēĐžŅĐŊĐĩŅ‚Đĩ и ĐˇĐ°Đ´Ņ€ŅŠĐļŅ‚Đĩ, Са да Đ˛ŅŠĐˇŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛ĐžŅ‚Đž Đ´Đž ĐŋĐžĐ´Ņ€Đ°ĐˇĐąĐ¸Ņ€Đ°ĐŊĐĩ</string>
<string name="revanced_video_quality_dialog_button_summary_off">Đ‘ŅƒŅ‚ĐžĐŊŅŠŅ‚ ĐŊĐĩ Đĩ ĐŋĐžĐēаСаĐŊ</string>
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">МĐĩĐŊŅŽŅ‚Đž Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēа ҁĐēĐžŅ€ĐžŅŅ‚</string> <string name="revanced_custom_speed_menu_title">МĐĩĐŊŅŽŅ‚Đž Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēа ҁĐēĐžŅ€ĐžŅŅ‚</string>
<string name="revanced_custom_speed_menu_summary_on">МĐĩĐŊŅŽŅ‚Đž Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēа ҁĐēĐžŅ€ĐžŅŅ‚ ҁĐĩ ĐŋĐžĐēаСва</string> <string name="revanced_custom_speed_menu_summary_on">МĐĩĐŊŅŽŅ‚Đž Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēа ҁĐēĐžŅ€ĐžŅŅ‚ ҁĐĩ ĐŋĐžĐēаСва</string>
<string name="revanced_custom_speed_menu_summary_off">МĐĩĐŊŅŽŅ‚Đž Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēа ҁĐēĐžŅ€ĐžŅŅ‚ ĐŊĐĩ ҁĐĩ ĐŋĐžĐēаСва</string> <string name="revanced_custom_speed_menu_summary_off">МĐĩĐŊŅŽŅ‚Đž Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēа ҁĐēĐžŅ€ĐžŅŅ‚ ĐŊĐĩ ҁĐĩ ĐŋĐžĐēаСва</string>
<string name="revanced_restore_old_speed_menu_title">Đ’ŅŠĐˇŅŅ‚Đ°ĐŊĐžĐ˛ŅĐ˛Đ°ĐŊĐĩ ĐŊа ŅŅ‚Đ°Ņ€ĐžŅ‚Đž ĐŧĐĩĐŊŅŽ Са ҁĐēĐžŅ€ĐžŅŅ‚ ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ</string>
<string name="revanced_restore_old_speed_menu_summary_on">ПоĐēаСва ҁĐĩ ŅŅ‚Đ°Ņ€ĐžŅ‚Đž ĐŧĐĩĐŊŅŽ Са ҁĐēĐžŅ€ĐžŅŅ‚</string>
<string name="revanced_restore_old_speed_menu_summary_off">ПоĐēаСва ҁĐĩ ĐŧОдĐĩŅ€ĐŊĐžŅ‚Đž ĐŧĐĩĐŊŅŽ Са ҁĐēĐžŅ€ĐžŅŅ‚</string>
<string name="revanced_custom_playback_speeds_title">ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐŊи ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ</string> <string name="revanced_custom_playback_speeds_title">ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐŊи ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ</string>
<string name="revanced_custom_playback_speeds_summary">ДобавĐĩŅ‚Đĩ иĐģи ĐŋŅ€ĐžĐŧĐĩĐŊĐĩŅ‚Đĩ ҁĐēĐžŅ€ĐžŅŅ‚a ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ</string> <string name="revanced_custom_playback_speeds_summary">ДобавĐĩŅ‚Đĩ иĐģи ĐŋŅ€ĐžĐŧĐĩĐŊĐĩŅ‚Đĩ ҁĐēĐžŅ€ĐžŅŅ‚a ĐŊа Đ˛ŅŠĐˇĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐļдаĐŊĐĩ</string>
<string name="revanced_custom_playback_speeds_invalid">ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐŊĐ¸Ņ‚Đĩ ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ Ņ‚Ņ€ŅĐąĐ˛Đ° да ŅĐ° ĐŋĐž-ĐŧаĐģĐēи ĐžŅ‚ %s</string> <string name="revanced_custom_playback_speeds_invalid">ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐŊĐ¸Ņ‚Đĩ ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ Ņ‚Ņ€ŅĐąĐ˛Đ° да ŅĐ° ĐŋĐž-ĐŧаĐģĐēи ĐžŅ‚ %s</string>

View File

@@ -133,7 +133,7 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_debug_logs_disabled">āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ—āĻŋāĻ‚ āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋāϝāĻŧ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_debug_logs_disabled">āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ—āĻŋāĻ‚ āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋāϝāĻŧ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_debug_logs_none_found">āϕ⧋āύ⧋ āϞāĻ— āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧāύāĻŋ</string> <string name="revanced_debug_logs_none_found">āϕ⧋āύ⧋ āϞāĻ— āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧāύāĻŋ</string>
<string name="revanced_debug_logs_copied_to_clipboard">āϞāĻ— āĻ…āύ⧁āϞāĻŋāĻĒāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_debug_logs_copied_to_clipboard">āϞāĻ— āĻ…āύ⧁āϞāĻŋāĻĒāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_debug_logs_failed_to_export">āϞāĻ— āϰāĻĒā§āϤāĻžāύāĻŋ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻ°ā§āĻĨ: $s</string> <string name="revanced_debug_logs_failed_to_export">āϞāĻ— āĻāĻ•ā§āϏāĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻž āϝāĻžāϝāĻŧāύāĻŋ: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ—āϗ⧁āϞāĻŋ āϏāĻžāĻĢ āĻ•āϰ⧁āύ</string> <string name="revanced_debug_logs_clear_buffer_title">āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ—āϗ⧁āϞāĻŋ āϏāĻžāĻĢ āĻ•āϰ⧁āύ</string>
<string name="revanced_debug_logs_clear_buffer_summary">āϏāĻŽāĻ¸ā§āϤ āϏāĻžā§āϚāĻŋāϤ ReVanced āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ— āϏāĻžāĻĢ āĻ•āϰ⧇</string> <string name="revanced_debug_logs_clear_buffer_summary">āϏāĻŽāĻ¸ā§āϤ āϏāĻžā§āϚāĻŋāϤ ReVanced āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ— āϏāĻžāĻĢ āĻ•āϰ⧇</string>
<string name="revanced_debug_logs_clear_toast">āϞāĻ— āϏāĻžāĻĢ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_debug_logs_clear_toast">āϞāĻ— āϏāĻžāĻĢ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇</string>
@@ -160,9 +160,6 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_expandable_card_title">āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āĻžāĻ°ā§āĻĄ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_expandable_card_title">āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āĻžāĻ°ā§āĻĄ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_expandable_card_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻšā§‡ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āĻžāĻ°ā§āĻĄ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_expandable_card_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻšā§‡ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āĻžāĻ°ā§āĻĄ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_expandable_card_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻšā§‡ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āĻžāĻ°ā§āĻĄ āĻĻ⧇āĻ–āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_expandable_card_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻšā§‡ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āĻžāĻ°ā§āĻĄ āĻĻ⧇āĻ–āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_feed_survey_title">āĻĢāĻŋāĻĄ āϜāϰāĻŋāĻĒ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_feed_survey_summary_on">āĻĢāĻŋāĻĄ āϜāϰāĻŋāĻĒ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_feed_survey_summary_off">āĻĢāĻŋāĻĄ āϜāϰāĻŋāĻĒ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_floating_microphone_button_title">āĻ­āĻžāϏāĻŽāĻžāύ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻĢā§‹āύ āĻŦā§‹āϤāĻžāĻŽ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_floating_microphone_button_title">āĻ­āĻžāϏāĻŽāĻžāύ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻĢā§‹āύ āĻŦā§‹āϤāĻžāĻŽ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_floating_microphone_button_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇ āĻĢā§āϞ⧋āϟāĻŋāĻ‚ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻĢā§‹āύ āĻŦā§‹āϤāĻžāĻŽ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_floating_microphone_button_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇ āĻĢā§āϞ⧋āϟāĻŋāĻ‚ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻĢā§‹āύ āĻŦā§‹āϤāĻžāĻŽ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_floating_microphone_button_summary_off">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇ āĻ­āĻžāϏāĻŽāĻžāύ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻĢā§‹āύ āĻŦā§‹āϤāĻžāĻŽ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ</string> <string name="revanced_hide_floating_microphone_button_summary_off">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇ āĻ­āĻžāϏāĻŽāĻžāύ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻĢā§‹āύ āĻŦā§‹āϤāĻžāĻŽ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ</string>
@@ -188,7 +185,7 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_movies_section_summary_on">āϚāϞāĻšā§āϚāĻŋāĻ¤ā§āϰ āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_movies_section_summary_on">āϚāϞāĻšā§āϚāĻŋāĻ¤ā§āϰ āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_movies_section_summary_off">āϚāϞāĻšā§āϚāĻŋāĻ¤ā§āϰ āĻŦāĻŋāĻ­āĻžāĻ— āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_movies_section_summary_off">āϚāϞāĻšā§āϚāĻŋāĻ¤ā§āϰ āĻŦāĻŋāĻ­āĻžāĻ— āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays. <!-- '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. --> This item appear in the Subscriptions 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_on">āφāĻŽāĻžāϕ⧇ āϜāĻžāύāĻžāύ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_notify_me_button_summary_off">āφāĻŽāĻžāϕ⧇ āϜāĻžāύāĻžāύ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_hide_notify_me_button_summary_off">āφāĻŽāĻžāϕ⧇ āϜāĻžāύāĻžāύ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
@@ -200,6 +197,9 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_show_more_button_title">\'āφāϰāĻ“ āĻĻ⧇āĻ–āĻžāύ\' āĻŦā§‹āϤāĻžāĻŽ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_show_more_button_title">\'āφāϰāĻ“ āĻĻ⧇āĻ–āĻžāύ\' āĻŦā§‹āϤāĻžāĻŽ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_show_more_button_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ \"āφāϰāĻ“ āĻĻ⧇āĻ–āĻžāύ\" āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_show_more_button_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ \"āφāϰāĻ“ āĻĻ⧇āĻ–āĻžāύ\" āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_show_more_button_summary_off">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ \"āφāϰāĻ“ āĻĻ⧇āĻ–āĻžāύ\" āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_hide_show_more_button_summary_off">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ \"āφāϰāĻ“ āĻĻ⧇āĻ–āĻžāύ\" āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_surveys_title">āϏāĻžāĻ°ā§āϭ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_surveys_summary_on">āϜāϰāĻŋāĻĒāϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_surveys_summary_off">āϜāϰāĻŋāĻĒāϗ⧁āϞāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_ticket_shelf_title">āϟāĻŋāĻ•āĻŋāϟ āϤāĻžāĻ• āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_ticket_shelf_title">āϟāĻŋāĻ•āĻŋāϟ āϤāĻžāĻ• āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_ticket_shelf_summary_on">āϟāĻŋāĻ•āĻŋāϟ āϤāĻžāĻ• āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_ticket_shelf_summary_on">āϟāĻŋāĻ•āĻŋāϟ āϤāĻžāĻ• āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_ticket_shelf_summary_off">āϟāĻŋāĻ•āĻŋāϟ āϤāĻžāĻ• āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_hide_ticket_shelf_summary_off">āϟāĻŋāĻ•āĻŋāϟ āϤāĻžāĻ• āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
@@ -247,8 +247,8 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_timed_reactions_summary_on">āϏāĻŽā§Ÿ āĻ…āύ⧁āϝāĻžā§Ÿā§€ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋ⧟āĻž āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_timed_reactions_summary_on">āϏāĻŽā§Ÿ āĻ…āύ⧁āϝāĻžā§Ÿā§€ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋ⧟āĻž āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_timed_reactions_summary_off">āϏāĻŽā§Ÿ āĻ…āύ⧁āϝāĻžā§Ÿā§€ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋ⧟āĻž āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_timed_reactions_summary_off">āϏāĻŽā§Ÿ āĻ…āύ⧁āϝāĻžā§Ÿā§€ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋ⧟āĻž āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">\'AI-āĻœā§‡āύāĻžāϰ⧇āĻŸā§‡āĻĄ āĻ­āĻŋāĻĄāĻŋāĻ“ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ\' āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_ai_generated_video_summary_section_title">\'AI-āĻœā§‡āύāĻžāϰ⧇āĻŸā§‡āĻĄ āĻ­āĻŋāĻĄāĻŋāĻ“ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ\' āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_on">āĻāφāχ-āĻœā§‡āύāĻžāϰ⧇āĻŸā§‡āĻĄ āĻ­āĻŋāĻĄāĻŋāĻ“ āϏāĻžāϰāĻžāĻ‚āĻļ āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ āĻŦāĻŋāĻ­āĻžāĻ— āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_ai_generated_video_summary_section_summary_off">āĻāφāχ-āĻœā§‡āύāĻžāϰ⧇āĻŸā§‡āĻĄ āĻ­āĻŋāĻĄāĻŋāĻ“ āϏāĻžāϰāĻžāĻ‚āĻļ āĻŦāĻŋāĻ­āĻžāĻ— āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_ask_section_title">āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_ask_section_title">āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_ask_section_summary_on">āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_ask_section_summary_on">āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_ask_section_summary_off">āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻŦāĻŋāĻ­āĻžāĻ— āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_ask_section_summary_off">āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻŦāĻŋāĻ­āĻžāĻ— āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string>
@@ -276,19 +276,19 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_description_components_screen_title">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āĻŦāĻŋāĻŦāϰāĻŖ</string> <string name="revanced_hide_description_components_screen_title">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āĻŦāĻŋāĻŦāϰāĻŖ</string>
<string name="revanced_hide_description_components_screen_summary">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻŦāĻŋāĻŦāϰāĻŖ āĻāϰ āωāĻĒāĻžāĻĻāĻžāύ āϞ⧁āĻ•āĻžāύ āĻŦāĻž āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧁āύ</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_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_title">āĻĢāĻŋāĻĄā§‡ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">āĻĢāĻŋāĻĄā§‡ āϞ⧁āĻ•āĻžāύ⧋</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> <string name="revanced_hide_filter_bar_feed_in_feed_summary_off">āĻĢāĻŋāĻĄā§‡ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">āχāϤāĻŋāĻšāĻžāϏ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">āχāϤāĻŋāĻšāĻžāϏ⧇ āϞ⧁āĻ•āĻžāύ⧋</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">āχāϤāĻŋāĻšāĻžāϏ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_title">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_filter_bar_feed_in_history_title">āĻĻ⧇āĻ–āĻžāϰ āχāϤāĻŋāĻšāĻžāϏ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">āĻĻ⧇āĻ–āĻžāϰ āχāϤāĻŋāĻšāĻžāϏ⧇ āϞ⧁āĻ•āĻžāύ⧋</string>
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">āĻĻ⧇āĻ–āĻžāϰ āχāϤāĻŋāĻšāĻžāϏ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_channel_screen_title">āĻšā§āϝāĻžāύ⧇āϞ āĻĒ⧃āĻˇā§āĻ āĻž</string> <string name="revanced_channel_screen_title">āĻšā§āϝāĻžāύ⧇āϞ āĻĒ⧃āĻˇā§āĻ āĻž</string>
<string name="revanced_channel_screen_summary">āĻšā§āϝāĻžāύ⧇āϞ āĻĒ⧃āĻˇā§āĻ āĻžāϰ āωāĻĒāĻžāĻĻāĻžāύāϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ āĻŦāĻž āĻĻ⧇āĻ–āĻžāύ</string> <string name="revanced_channel_screen_summary">āĻšā§āϝāĻžāύ⧇āϞ āĻĒ⧃āĻˇā§āĻ āĻžāϰ āωāĻĒāĻžāĻĻāĻžāύāϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ āĻŦāĻž āĻĻ⧇āĻ–āĻžāύ</string>
<!-- 'For You' should be translated using the same localized wording YouTube displays. --> <!-- 'For You' should be translated using the same localized wording YouTube displays. -->
@@ -311,12 +311,12 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_visit_store_button_summary_off">āĻ¸ā§āĻŸā§‹āϰ āĻ­āĻŋāϜāĻŋāϟ āĻŦāĻžāϟāύ āĻĻ⧇āĻ–āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_visit_store_button_summary_off">āĻ¸ā§āĻŸā§‹āϰ āĻ­āĻŋāϜāĻŋāϟ āĻŦāĻžāϟāύ āĻĻ⧇āĻ–āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_comments_screen_title">āĻŽāĻ¨ā§āϤāĻŦā§āϝ</string> <string name="revanced_comments_screen_title">āĻŽāĻ¨ā§āϤāĻŦā§āϝ</string>
<string name="revanced_comments_screen_summary">āĻŽāĻ¨ā§āϤāĻŦā§āϝ āĻŦāĻŋāĻ­āĻžāϗ⧇āϰ āωāĻĒāĻžāĻĻāĻžāύāϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ āĻŦāĻž āĻĻ⧇āĻ–āĻžāύ⧎</string> <string name="revanced_comments_screen_summary">āĻŽāĻ¨ā§āϤāĻŦā§āϝ āĻŦāĻŋāĻ­āĻžāϗ⧇āϰ āωāĻĒāĻžāĻĻāĻžāύāϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ āĻŦāĻž āĻĻ⧇āĻ–āĻžāύ⧎</string>
<string name="revanced_hide_comments_ai_chat_summary_title">āĻāφāχ āĻšā§āϝāĻžāϟ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_comments_ai_chat_summary_title">āĻāφāχ āĻšā§āϝāĻžāϟ āϏāĻžāϰāĻžāĻ‚āĻļ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_on">āĻšā§āϝāĻžāϟ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_comments_ai_chat_summary_summary_on">āĻāφāχ āĻšā§āϝāĻžāϟ āϏāĻžāϰāĻžāĻ‚āĻļ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">āĻšā§āϝāĻžāϟ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_comments_ai_chat_summary_summary_off">āĻāφāχ āĻšā§āϝāĻžāϟ āϏāĻžāϰāĻžāĻ‚āĻļ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_comments_ai_summary_title">āĻāφāχ āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_comments_ai_summary_title">āĻāφāχ āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_comments_ai_summary_summary_on">āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_comments_ai_summary_summary_on">āĻāφāχ āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϏāĻžāϰāĻžāĻ‚āĻļ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_comments_ai_summary_summary_off">āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϏāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_comments_ai_summary_summary_off">āĻāφāχ āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϏāĻžāϰāĻžāĻ‚āĻļ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_comments_channel_guidelines_title">āĻšā§āϝāĻžāύ⧇āϞ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_comments_channel_guidelines_title">āĻšā§āϝāĻžāύ⧇āϞ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_comments_channel_guidelines_summary_on">āĻšā§āϝāĻžāύ⧇āϞ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž āϞ⧁āĻ•āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_comments_channel_guidelines_summary_on">āĻšā§āϝāĻžāύ⧇āϞ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž āϞ⧁āĻ•āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_comments_channel_guidelines_summary_off">āĻšā§āϝāĻžāύ⧇āϞ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_comments_channel_guidelines_summary_off">āĻšā§āϝāĻžāύ⧇āϞ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string>
@@ -415,7 +415,6 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_hide_shopping_links_title">āϕ⧇āύāĻžāĻ•āĻžāϟāĻžāϰ āϞāĻŋāĻ™ā§āĻ• āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_shopping_links_title">āϕ⧇āύāĻžāĻ•āĻžāϟāĻžāϰ āϞāĻŋāĻ™ā§āĻ• āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_shopping_links_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻŦāĻŋāĻŦāϰāϪ⧇ āϕ⧇āύāĻžāĻ•āĻžāϟāĻžāϰ āϞāĻŋāĻ™ā§āĻ• āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_shopping_links_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻŦāĻŋāĻŦāϰāϪ⧇ āϕ⧇āύāĻžāĻ•āĻžāϟāĻžāϰ āϞāĻŋāĻ™ā§āĻ• āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_shopping_links_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻŦāĻ°ā§āĻŖāύāĻžāϝāĻŧ āϕ⧇āύāĻžāĻ•āĻžāϟāĻžāϰ āϞāĻŋāĻ™ā§āĻ• āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ</string> <string name="revanced_hide_shopping_links_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻŦāĻ°ā§āĻŖāύāĻžāϝāĻŧ āϕ⧇āύāĻžāĻ•āĻžāϟāĻžāϰ āϞāĻŋāĻ™ā§āĻ• āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ</string>
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_view_products_banner_title">\'āĻĒāĻŖā§āϝ āĻĻ⧇āϖ⧁āύ\' āĻŦā§āϝāĻžāύāĻžāϰ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_view_products_banner_title">\'āĻĒāĻŖā§āϝ āĻĻ⧇āϖ⧁āύ\' āĻŦā§āϝāĻžāύāĻžāϰ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_view_products_banner_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ“āĻ­āĻžāϰāϞ⧇āϤ⧇ \"āĻĒāĻŖā§āϝ āĻĻ⧇āϖ⧁āύ\" āĻŦā§āϝāĻžāύāĻžāϰ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_view_products_banner_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ“āĻ­āĻžāϰāϞ⧇āϤ⧇ \"āĻĒāĻŖā§āϝ āĻĻ⧇āϖ⧁āύ\" āĻŦā§āϝāĻžāύāĻžāϰ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_view_products_banner_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ“āĻ­āĻžāϰāϞ⧇āϤ⧇ \"āĻĒāĻŖā§āϝ āĻĻ⧇āϖ⧁āύ\" āĻŦā§āϝāĻžāύāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_hide_view_products_banner_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ“āĻ­āĻžāϰāϞ⧇āϤ⧇ \"āĻĒāĻŖā§āϝ āĻĻ⧇āϖ⧁āύ\" āĻŦā§āϝāĻžāύāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
@@ -449,7 +448,7 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_remove_viewer_discretion_dialog_summary_off">āĻĄāĻžā§ŸāĻžāϞāĻ— āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšāĻŦ⧇</string> <string name="revanced_remove_viewer_discretion_dialog_summary_off">āĻĄāĻžā§ŸāĻžāϞāĻ— āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšāĻŦ⧇</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">āĻāϟāĻŋ āĻŦāϝāĻŧāϏ⧇āϰ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻžāϕ⧇ āĻŦāĻžāχāĻĒāĻžāϏ āĻ•āϰ⧇ āύāĻžāĨ¤ āĻāϟāĻž āĻļ⧁āϧ⧁ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤</string> <string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">āĻāϟāĻŋ āĻŦāϝāĻŧāϏ⧇āϰ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻžāϕ⧇ āĻŦāĻžāχāĻĒāĻžāϏ āĻ•āϰ⧇ āύāĻžāĨ¤ āĻāϟāĻž āĻļ⧁āϧ⧁ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤</string>
</patch> </patch>
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch"> <patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">āĻĄāĻžāĻŦāϞ āĻŸā§āϝāĻžāĻĒ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ āĻ¸ā§āĻ•āĻŋāĻĒ āĻ…āĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ</string> <string name="revanced_disable_chapter_skip_double_tap_title">āĻĄāĻžāĻŦāϞ āĻŸā§āϝāĻžāĻĒ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ āĻ¸ā§āĻ•āĻŋāĻĒ āĻ…āĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">āĻĄāĻžāĻŦāϞ āĻŸā§āϝāĻžāĻĒ āĻ•āĻ–āύāĻ“ āĻĒāϰāĻŦāĻ°ā§āϤ⧀/āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ⧇ āĻ¸ā§āĻ•āĻŋāĻĒ āĻŸā§āϰāĻŋāĻ—āĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āύāĻž</string> <string name="revanced_disable_chapter_skip_double_tap_summary_on">āĻĄāĻžāĻŦāϞ āĻŸā§āϝāĻžāĻĒ āĻ•āĻ–āύāĻ“ āĻĒāϰāĻŦāĻ°ā§āϤ⧀/āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ⧇ āĻ¸ā§āĻ•āĻŋāĻĒ āĻŸā§āϰāĻŋāĻ—āĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āύāĻž</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_off">āĻĄāĻžāĻŦāϞ āĻŸā§āϝāĻžāĻĒ āĻŽāĻžāĻā§‡ āĻŽāĻžāĻā§‡ āĻĒāϰāĻŦāĻ°ā§āϤ⧀/āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ⧇ āĻ¸ā§āĻ•āĻŋāĻĒ āĻŸā§āϰāĻŋāĻ—āĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇</string> <string name="revanced_disable_chapter_skip_double_tap_summary_off">āĻĄāĻžāĻŦāϞ āĻŸā§āϝāĻžāĻĒ āĻŽāĻžāĻā§‡ āĻŽāĻžāĻā§‡ āĻĒāϰāĻŦāĻ°ā§āϤ⧀/āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āĻ…āĻ§ā§āϝāĻžāϝāĻŧ⧇ āĻ¸ā§āĻ•āĻŋāĻĒ āĻŸā§āϰāĻŋāĻ—āĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇</string>
@@ -465,8 +464,15 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_external_downloader_action_button_summary_on">āĻĄāĻžāωāύāϞ⧋āĻĄ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āφāĻĒāύāĻžāϰ āĻŦāĻžāĻšāĻŋāϰ⧇āϰ āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ āϖ⧁āϞāĻŦ⧇</string> <string name="revanced_external_downloader_action_button_summary_on">āĻĄāĻžāωāύāϞ⧋āĻĄ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āφāĻĒāύāĻžāϰ āĻŦāĻžāĻšāĻŋāϰ⧇āϰ āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ āϖ⧁āϞāĻŦ⧇</string>
<string name="revanced_external_downloader_action_button_summary_off">āĻĄāĻžāωāύāϞ⧋āĻĄ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āύ⧇āϟāĻŋāĻ­ āχāύ-āĻ…ā§āϝāĻžāĻĒ āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ āϖ⧁āϞāĻŦ⧇</string> <string name="revanced_external_downloader_action_button_summary_off">āĻĄāĻžāωāύāϞ⧋āĻĄ āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āύ⧇āϟāĻŋāĻ­ āχāύ-āĻ…ā§āϝāĻžāĻĒ āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ āϖ⧁āϞāĻŦ⧇</string>
<string name="revanced_external_downloader_name_title">āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ⧇āϰ āĻĒā§āϝāĻžāϕ⧇āϜ āύāĻžāĻŽ</string> <string name="revanced_external_downloader_name_title">āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ⧇āϰ āĻĒā§āϝāĻžāϕ⧇āϜ āύāĻžāĻŽ</string>
<string name="revanced_external_downloader_name_summary">āφāĻĒāύāĻžāϰ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āĻŦāĻžāχāϰ⧇āϰ āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ āĻ…ā§āϝāĻžāĻĒ⧇āϰ āĻĒā§āϝāĻžāϕ⧇āϜ āύāĻžāĻŽ, āϝ⧇āĻŽāύ NewPipe āĻŦāĻž Seal</string> <string name="revanced_external_downloader_name_summary">āφāĻĒāύāĻžāϰ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āĻŦāĻžāĻšā§āϝāĻŋāĻ• āĻĄāĻžāωāύāϞ⧋āĻĄāĻžāϰ āĻ…ā§āϝāĻžāĻĒ⧇āϰ āĻĒā§āϝāĻžāϕ⧇āĻœā§‡āϰ āύāĻžāĻŽ</string>
<string name="revanced_external_downloader_other_item_hint">āĻĒā§āϝāĻžāϕ⧇āĻœā§‡āϰ āύāĻžāĻŽ āϞāĻŋāϖ⧁āύ</string>
<string name="revanced_external_downloader_other_item">āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ</string>
<string name="revanced_external_downloader_not_found_title">āĻ…ā§āϝāĻžāĻĒ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āύ⧇āχ</string>
<string name="revanced_external_downloader_not_installed_warning">%s āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āύ⧇āχ, āχāύāĻ¸ā§āϟāϞ āĻ•āϰ⧁āύāĨ¤</string> <string name="revanced_external_downloader_not_installed_warning">%s āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āύ⧇āχ, āχāύāĻ¸ā§āϟāϞ āĻ•āϰ⧁āύāĨ¤</string>
<string name="revanced_external_downloader_package_not_found_warning">"āĻĒā§āϝāĻžāϕ⧇āĻœā§‡āϰ āύāĻžāĻŽ: %s āϏāĻš āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āĻ…ā§āϝāĻžāĻĒāϟāĻŋ āϖ⧁āρāĻœā§‡ āĻĒāĻžāĻ“ā§ŸāĻž āϝāĻžā§ŸāύāĻŋ
āĻĒā§āϝāĻžāϕ⧇āĻœā§‡āϰ āύāĻžāĻŽāϟāĻŋ āϏāĻ āĻŋāĻ• āĻāĻŦāĻ‚ āĻ…ā§āϝāĻžāĻĒāϟāĻŋ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻž āφāϛ⧇ āĻ•āĻŋāύāĻž āϤāĻž āϝāĻžāϚāĻžāχ āĻ•āϰ⧁āύ"</string>
<string name="revanced_external_downloader_empty_warning">āĻĒā§āϝāĻžāϕ⧇āĻœā§‡āϰ āύāĻžāĻŽ āĻ–āĻžāϞāĻŋ āϰāĻžāĻ–āĻž āϝāĻžāĻŦ⧇ āύāĻž</string>
</patch> </patch>
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch"> <patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļ⧇ āϝāĻžāĻ“ā§ŸāĻžāϰ āĻ…āĻ™ā§āĻ—āĻ­āĻ™ā§āĻ—āĻŋ āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋ⧟ āĻ•āϰ⧁āύ</string> <string name="revanced_disable_precise_seeking_gesture_title">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļ⧇ āϝāĻžāĻ“ā§ŸāĻžāϰ āĻ…āĻ™ā§āĻ—āĻ­āĻ™ā§āĻ—āĻŋ āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋ⧟ āĻ•āϰ⧁āύ</string>
@@ -726,27 +732,28 @@ MicroG-āĻāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻžāϟāĻžāϰāĻŋ āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāϜ
<string name="revanced_disable_rolling_number_animations_summary_off">āϰ⧋āϞāĻŋāĻ‚ āύāĻžāĻŽā§āĻŦāĻžāϰ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻŸā§‡āĻĄ</string> <string name="revanced_disable_rolling_number_animations_summary_off">āϰ⧋āϞāĻŋāĻ‚ āύāĻžāĻŽā§āĻŦāĻžāϰ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻŸā§‡āĻĄ</string>
</patch> </patch>
<patch id="layout.hide.seekbar.hideSeekbarPatch"> <patch id="layout.hide.seekbar.hideSeekbarPatch">
<string name="revanced_hide_seekbar_title">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_seekbar_title">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āϞ⧇āϝāĻŧāĻžāϰ⧇āϰ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_seekbar_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_seekbar_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_seekbar_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_seekbar_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_seekbar_thumbnail_title">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻžāύ</string> <!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
<string name="revanced_hide_seekbar_thumbnail_summary_on">āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_seekbar_thumbnail_title">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ⧇ āϏāĻŋāĻ•āĻŦāĻžāϰ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_seekbar_thumbnail_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāĻŋāĻ•āĻŦāĻžāϰ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāĻŋāĻ•āĻŦāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
</patch> </patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch"> <patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<string name="revanced_shorts_player_screen_title">Shorts āĻĒā§āϞ⧇āϝāĻŧāĻžāϰ</string> <string name="revanced_shorts_player_screen_title">Shorts āĻĒā§āϞ⧇āϝāĻŧāĻžāϰ</string>
<string name="revanced_shorts_player_screen_summary">Shorts āĻĒā§āϞ⧇āϝāĻŧāĻžāϰ⧇ āωāĻĒāĻžāĻĻāĻžāύ āϞ⧁āĻ•āĻžāύ⧋ āĻŦāĻž āĻĻ⧇āĻ–āĻžāύ⧋</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. --> <!-- '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_title">āĻšā§‹āĻŽ āĻĢāĻŋāĻĄā§‡ Shorts āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_shorts_home_summary_on">āĻšā§‹āĻŽ āĻĢāĻŋāĻĄ āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_shorts_home_summary_on">āĻšā§‹āĻŽ āĻĢāĻŋāĻĄ āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_shorts_home_summary_off">āĻšā§‹āĻŽ āĻĢāĻŋāĻĄ āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string> <string name="revanced_hide_shorts_home_summary_off">āĻšā§‹āĻŽ āĻĢāĻŋāĻĄ āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ­āĻŋāĻĄāĻŋāĻ“āϤ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_hide_shorts_search_title">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ Shorts āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_shorts_search_summary_on">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āϞ⧁āĻ•āĻžāύ⧋</string>
<string name="revanced_hide_shorts_search_summary_off">āϏāĻžāĻ°ā§āϚ āϰ⧇āϜāĻžāĻ˛ā§āĻŸā§‡ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇</string>
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. --> <!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
<string name="revanced_hide_shorts_subscriptions_title">āϏāĻžāĻŦāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒāĻļāύāϏ āĻĢāĻŋāĻĄā§‡ Shorts āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_shorts_subscriptions_title">āϏāĻžāĻŦāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒāĻļāύāϏ āĻĢāĻŋāĻĄā§‡ Shorts āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_shorts_subscriptions_summary_on">āϏāĻžāĻŦāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒāĻļāύāϏ āĻĢāĻŋāĻĄā§‡ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_shorts_subscriptions_summary_on">āϏāĻžāĻŦāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒāĻļāύāϏ āĻĢāĻŋāĻĄā§‡ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_shorts_subscriptions_summary_off">āϏāĻžāĻŦāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒāĻļāύāϏ āĻĢāĻŋāĻĄā§‡ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</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">āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ⧇ āϞ⧁āĻ•āĻžāύ⧋</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_title">Shortsāϗ⧁āϞāĻŋāϕ⧇ āĻ“āϝāĻŧāĻžāϚ āχāϤāĻŋāĻšāĻžāϏ⧇ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_shorts_history_summary_on">āĻ“āϝāĻŧāĻžāϚ āĻšāĻŋāĻ¸ā§āĻŸā§āϰāĻŋāϤ⧇ āϞ⧁āĻ•āĻžāύ⧋</string> <string name="revanced_hide_shorts_history_summary_on">āĻ“āϝāĻŧāĻžāϚ āĻšāĻŋāĻ¸ā§āĻŸā§āϰāĻŋāϤ⧇ āϞ⧁āĻ•āĻžāύ⧋</string>
<string name="revanced_hide_shorts_history_summary_off">āĻ“āϝāĻŧāĻžāϚ āχāϤāĻŋāĻšāĻžāϏ⧇ āĻĻ⧇āĻ–āĻžāύ⧋</string> <string name="revanced_hide_shorts_history_summary_off">āĻ“āϝāĻŧāĻžāϚ āχāϤāĻŋāĻšāĻžāϏ⧇ āĻĻ⧇āĻ–āĻžāύ⧋</string>
@@ -1186,8 +1193,6 @@ YouTube āϏ⧇āϟāĻŋāĻ‚āϏ⧇ āĻ…āĻŸā§‹ āĻĒā§āϞ⧇ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ
āĻāϟāĻŋ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύāϟāĻŋāϰ āĻšā§‡āĻšāĻžāϰāĻž āĻāĻŦāĻ‚ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāĻŦ⧇, āϤāĻŦ⧇ āĻ…āϜāĻžāύāĻž āĻĒāĻžāĻ°ā§āĻļā§āĻŦ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāϟāĻŋ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύāϟāĻŋāϰ āĻšā§‡āĻšāĻžāϰāĻž āĻāĻŦāĻ‚ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāĻŦ⧇, āϤāĻŦ⧇ āĻ…āϜāĻžāύāĻž āĻĒāĻžāĻ°ā§āĻļā§āĻŦ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤
āĻĒāϰ⧇ āϝāĻĻāĻŋ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻž āĻšāϝāĻŧ, UI āĻŦāĻžāĻ— āĻāĻĄāĻŧāĻžāϤ⧇ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āĻĄā§‡āϟāĻž āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰāĻžāϰ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻ⧇āĻ“āϝāĻŧāĻž āĻšāϝāĻŧāĨ¤"</string> āĻĒāϰ⧇ āϝāĻĻāĻŋ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻž āĻšāϝāĻŧ, UI āĻŦāĻžāĻ— āĻāĻĄāĻŧāĻžāϤ⧇ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āĻĄā§‡āϟāĻž āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰāĻžāϰ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻ⧇āĻ“āϝāĻŧāĻž āĻšāϝāĻŧāĨ¤"</string>
<!-- 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. -->
<string name="revanced_spoof_app_version_target_title">āĻ¸ā§āĻĒ⧁āĻĢ āĻ…ā§āϝāĻžāĻĒ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āϞāĻ•ā§āĻˇā§āϝ</string> <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_1">19.35.36 - āĻĒ⧁āϰāύ⧋ Shorts āĻĒā§āϞ⧇āϝāĻŧāĻžāϰ āφāχāĻ•āύ āĻĒ⧁āύāϰ⧁āĻĻā§āϧāĻžāϰ āĻ•āϰ⧁āύ</string>
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - āĻĒ⧁āϰāύ⧋ āύ⧇āĻ­āĻŋāϗ⧇āĻļāύ āφāχāĻ•āύ āĻĒ⧁āύāϰ⧁āĻĻā§āϧāĻžāϰ āĻ•āϰ⧁āύ</string> <string name="revanced_spoof_app_version_target_entry_2">19.01.34 - āĻĒ⧁āϰāύ⧋ āύ⧇āĻ­āĻŋāϗ⧇āĻļāύ āφāχāĻ•āύ āĻĒ⧁āύāϰ⧁āĻĻā§āϧāĻžāϰ āĻ•āϰ⧁āύ</string>
@@ -1456,10 +1461,18 @@ DeArrow āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāϰāĻ“ āϜāĻžāύāϤ⧇ āĻāĻ–āĻžāύ⧇ āϟ
<string name="revanced_playback_speed_dialog_button_summary_on">āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇āĨ¤ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ¸ā§āĻĒā§€āĻĄ āĻĄāĻŋāĻĢāĻ˛ā§āĻŸā§‡ āϰāĻŋāϏ⧇āϟ āĻ•āϰāϤ⧇ āĻŸā§āϝāĻžāĻĒ āĻ•āϰ⧇ āϧāϰ⧇ āϰāĻžāϖ⧁āύāĨ¤</string> <string name="revanced_playback_speed_dialog_button_summary_on">āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇āĨ¤ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ¸ā§āĻĒā§€āĻĄ āĻĄāĻŋāĻĢāĻ˛ā§āĻŸā§‡ āϰāĻŋāϏ⧇āϟ āĻ•āϰāϤ⧇ āĻŸā§āϝāĻžāĻĒ āĻ•āϰ⧇ āϧāϰ⧇ āϰāĻžāϖ⧁āύāĨ¤</string>
<string name="revanced_playback_speed_dialog_button_summary_off">āĻŦā§‹āϤāĻžāĻŽ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§ŸāύāĻŋ</string> <string name="revanced_playback_speed_dialog_button_summary_off">āĻŦā§‹āϤāĻžāĻŽ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§ŸāύāĻŋ</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch">
<string name="revanced_video_quality_dialog_button_title">āĻ­āĻŋāĻĄāĻŋāĻ“ āϗ⧁āĻŖāĻŽāĻžāύ āĻŦā§‹āϤāĻžāĻŽ āĻĻ⧇āĻ–āĻžāύ</string>
<string name="revanced_video_quality_dialog_button_summary_on">āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇āĨ¤ āϗ⧁āĻŖāĻŽāĻžāύ āĻĄāĻŋāĻĢāĻ˛ā§āĻŸā§‡ āϰāĻŋāϏ⧇āϟ āĻ•āϰāϤ⧇ āĻŸā§āϝāĻžāĻĒ āĻ•āϰ⧇ āϧāϰ⧇ āϰāĻžāϖ⧁āύāĨ¤</string>
<string name="revanced_video_quality_dialog_button_summary_off">āĻŦā§‹āϤāĻžāĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧāύāĻŋāĨ¤</string>
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ—āϤāĻŋ āĻŽā§‡āύ⧁</string> <string name="revanced_custom_speed_menu_title">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ—āϤāĻŋ āĻŽā§‡āύ⧁</string>
<string name="revanced_custom_speed_menu_summary_on">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ¸ā§āĻĒāĻŋāĻĄ āĻŽā§‡āύ⧁ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻšā§āϛ⧇</string> <string name="revanced_custom_speed_menu_summary_on">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ¸ā§āĻĒāĻŋāĻĄ āĻŽā§‡āύ⧁ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻšā§āϛ⧇</string>
<string name="revanced_custom_speed_menu_summary_off">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ¸ā§āĻĒāĻŋāĻĄ āĻŽā§‡āύ⧁ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻšā§āϛ⧇ āύāĻž</string> <string name="revanced_custom_speed_menu_summary_off">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ¸ā§āĻĒāĻŋāĻĄ āĻŽā§‡āύ⧁ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻšā§āϛ⧇ āύāĻž</string>
<string name="revanced_restore_old_speed_menu_title">āĻĒ⧁āϰāĻžāύ⧋ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ—āϤāĻŋ āĻŽā§‡āύ⧁ āĻĒ⧁āύāϰ⧁āĻĻā§āϧāĻžāϰ āĻ•āϰ⧁āύ</string>
<string name="revanced_restore_old_speed_menu_summary_on">āĻĒ⧁āϰāĻžāύ⧋ āĻ—āϤāĻŋāϰ āĻŽā§‡āύ⧁ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_restore_old_speed_menu_summary_off">āφāϧ⧁āύāĻŋāĻ• āĻ—āϤāĻŋāϰ āĻŽā§‡āύ⧁ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāϝāĻŧ⧇āϛ⧇</string>
<string name="revanced_custom_playback_speeds_title">āύāĻŋāϜāĻ¸ā§āĻŦ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ¸ā§āĻĒāĻŋāĻĄ</string> <string name="revanced_custom_playback_speeds_title">āύāĻŋāϜāĻ¸ā§āĻŦ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ¸ā§āĻĒāĻŋāĻĄ</string>
<string name="revanced_custom_playback_speeds_summary">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ—āϤāĻŋ āϝ⧋āĻ— āĻ•āϰ⧁āύ āĻ…āĻĨāĻŦāĻž āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧁āύ</string> <string name="revanced_custom_playback_speeds_summary">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ—āϤāĻŋ āϝ⧋āĻ— āĻ•āϰ⧁āύ āĻ…āĻĨāĻŦāĻž āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧁āύ</string>
<string name="revanced_custom_playback_speeds_invalid">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ—āϤāĻŋ %s āĻāϰ āĻšā§‡āϝāĻŧ⧇ āĻ•āĻŽ āĻšāϤ⧇ āĻšāĻŦ⧇</string> <string name="revanced_custom_playback_speeds_invalid">āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ—āϤāĻŋ %s āĻāϰ āĻšā§‡āϝāĻŧ⧇ āĻ•āĻŽ āĻšāϤ⧇ āĻšāĻŦ⧇</string>

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