Compare commits

...

76 Commits

Author SHA1 Message Date
semantic-release-bot
678ef4052e chore: Release v5.37.0-dev.1 [skip ci]
# [5.37.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0-dev.1) (2025-09-14)

### Features

* **Viber:** Add `Hide ads` patch ([#5826](https://github.com/ReVanced/revanced-patches/issues/5826)) ([0abfab7](0abfab79d7))
2025-09-14 11:52:21 +00:00
Samo Hribar
0abfab79d7 feat(Viber): Add Hide ads patch (#5826) 2025-09-14 15:49:52 +04:00
LisoUseInAIKyrios
61cadf72cd refactor(Spoof video streams): Back port code from v22 branch to support patching the latest YT Music. Using any target above 7.49.52 is untested and only recommended for experimental or development purposes. 2025-09-14 15:49:35 +04:00
github-actions[bot]
e12359b94f chore: Sync translations (#5829) 2025-09-14 15:46:32 +04:00
semantic-release-bot
c001daba4a chore: Release v5.36.0 [skip ci]
# [5.36.0](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0) (2025-09-14)

### Bug Fixes

* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](88b47ef414))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](8cd8e59bbc))
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](a53b00dd51))

### Features

* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](9d4aa5cd16))
2025-09-14 06:56:22 +00:00
LisoUseInAIKyrios
e136f62d6e chore: Merge branch dev to main (#5800) 2025-09-14 10:53:28 +04:00
semantic-release-bot
8ec405a359 chore: Release v5.36.0-dev.1 [skip ci]
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)

### Bug Fixes

* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](88b47ef414))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](8cd8e59bbc))
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](a53b00dd51))

### Features

* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](9d4aa5cd16))
2025-09-13 15:31:54 +00:00
github-actions[bot]
2f4b3a887b chore: Sync translations (#5821) 2025-09-13 19:28:15 +04:00
semantic-release-bot
d1fabb242b chore: Release v5.36.0-dev.1 [skip ci]
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)

### Bug Fixes

* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](88b47ef414))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](8cd8e59bbc))
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](a53b00dd51))

### Features

* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](9d4aa5cd16))
2025-09-13 15:15:40 +00:00
LisoUseInAIKyrios
a53b00dd51 fix(YouTube Music): Resolve playback issues, change recommended app target to 7.29.52 (#5813) 2025-09-13 19:12:00 +04:00
semantic-release-bot
850c13e98e chore: Release v5.36.0-dev.1 [skip ci]
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)

### Bug Fixes

* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](88b47ef414))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](8cd8e59bbc))

### Features

* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](9d4aa5cd16))
2025-09-13 07:00:16 +00:00
LisoUseInAIKyrios
4310789a26 chore: Fix api 2025-09-13 10:56:43 +04:00
semantic-release-bot
c4a720fbd3 chore: Release v5.36.0-dev.1 [skip ci]
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-12)

### Bug Fixes

* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](88b47ef414))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](8cd8e59bbc))

### Features

* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](9d4aa5cd16))
2025-09-12 15:08:03 +00:00
LisoUseInAIKyrios
3bdb8dbce0 chore(YouTube - SponsorBlock): Adjust strings for consistency / clarity
Strings taken from https://github.com/ajayyy/ExtensionTranslations/blob/master/en/messages.json
2025-09-12 18:49:34 +04:00
LisoUseInAIKyrios
4894f33c96 chore: fix compilation 2025-09-12 18:49:33 +04:00
semantic-release-bot
7f6093ee66 chore: Release v5.36.0-dev.1 [skip ci]
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.1-dev.1...v5.36.0-dev.1) (2025-09-12)

### Features

* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](9d4aa5cd16))
2025-09-12 01:59:47 +00:00
LisoUseInAIKyrios
9d4aa5cd16 feat(YouTube - SponsorBlock): Add 'Hook' segment category (#5783) 2025-09-12 05:56:50 +04:00
oSumAtrIX
5ace6f587c chore: Add ads.fund verification file [skip ci] (#5786) 2025-09-11 16:00:24 +02:00
semantic-release-bot
796f56745e chore: Release v5.35.1-dev.1 [skip ci]
## [5.35.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.35.1-dev.1) (2025-09-11)

### Bug Fixes

* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](88b47ef414))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](8cd8e59bbc))
2025-09-11 01:29:16 +00:00
hoodles
88b47ef414 fix(Duolingo - Disable ads): Support latest app target (#5782) 2025-09-11 03:26:28 +02:00
LisoUseInAIKyrios
8cd8e59bbc fix(YouTube - Hide layout components): Hide new type of Playable shelf 2025-09-11 03:24:09 +02:00
LisoUseInAIKyrios
6e72b14d07 refactor(YouTube - Video Quality): Handle extremely slow internet connections that initially can use -1 quality index 2025-09-11 02:58:33 +02:00
LisoUseInAIKyrios
52b088327b chore: Fix api dump 2025-09-10 21:58:27 +02:00
semantic-release-bot
8e934cc56b chore: Release v5.35.0 [skip ci]
# [5.35.0](https://github.com/ReVanced/revanced-patches/compare/v5.34.0...v5.35.0) (2025-09-09)

### Bug Fixes

* **Instagram - Hide navigation buttons:** Fix Manager patching error ([0a8cd7a](0a8cd7a7db))
* **Proton mail:** Constrain patches to last working app target ([1895291](189529151a))
* Revert dependency updates to fix Manager pre-release patching ([9256aa4](9256aa4548))
* **Spotify - Unlock Premium:** Make compatible with latest versions again by fixing fingerprint ([#5684](https://github.com/ReVanced/revanced-patches/issues/5684)) ([23496c7](23496c7c36))
* **YouTube - Hide layout components:** Hide Playable shelf header ([1473db0](1473db0bef))

### Features

* **BaconReader:** Add `Fix Redgifs API` patch ([#5761](https://github.com/ReVanced/revanced-patches/issues/5761)) ([144af2f](144af2f07e))
* **Boost/Sync for Reddit:** Add `Fix Redgifs` patch  ([#5725](https://github.com/ReVanced/revanced-patches/issues/5725)) ([c66c42e](c66c42e946))
* **Instagram:** Add `Hide navigation buttons` patch ([#5678](https://github.com/ReVanced/revanced-patches/issues/5678)) ([1dbc2d4](1dbc2d4057))
* **Instagram:** Add `Hide Stories from Home` patch ([#5756](https://github.com/ReVanced/revanced-patches/issues/5756)) ([b8629aa](b8629aacb6))
2025-09-09 19:38:18 +00:00
LisoUseInAIKyrios
b3140d909b chore: Merge branch dev to main (#5691) 2025-09-09 21:34:30 +02:00
github-actions[bot]
97645aa9f4 chore: Sync translations (#5777) 2025-09-09 21:32:56 +02:00
semantic-release-bot
603e2d018c chore: Release v5.35.0-dev.5 [skip ci]
# [5.35.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.4...v5.35.0-dev.5) (2025-09-06)

### Features

* **BaconReader:** Add `Fix Redgifs API` patch ([#5761](https://github.com/ReVanced/revanced-patches/issues/5761)) ([144af2f](144af2f07e))
* **Instagram:** Add `Hide Stories from Home` patch ([#5756](https://github.com/ReVanced/revanced-patches/issues/5756)) ([b8629aa](b8629aacb6))
2025-09-06 10:56:54 +00:00
Eric Ahn
144af2f07e feat(BaconReader): Add Fix Redgifs API patch (#5761) 2025-09-06 12:53:26 +02:00
PainfulPaladins
b8629aacb6 feat(Instagram): Add Hide Stories from Home patch (#5756) 2025-09-06 12:53:08 +02:00
github-actions[bot]
3951527f51 chore: Sync translations (#5768) 2025-09-06 12:52:48 +02:00
semantic-release-bot
7a8b618c4e chore: Release v5.35.0-dev.4 [skip ci]
# [5.35.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.3...v5.35.0-dev.4) (2025-09-04)

### Features

* **Boost/Sync for Reddit:** Add `Fix Redgifs` patch  ([#5725](https://github.com/ReVanced/revanced-patches/issues/5725)) ([c66c42e](c66c42e946))
2025-09-04 21:33:33 +00:00
Eric Ahn
c66c42e946 feat(Boost/Sync for Reddit): Add Fix Redgifs patch (#5725) 2025-09-04 23:29:58 +02:00
semantic-release-bot
b340769cf3 chore: Release v5.35.0-dev.3 [skip ci]
# [5.35.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.2...v5.35.0-dev.3) (2025-09-04)

### Bug Fixes

* **Instagram - Hide navigation buttons:** Fix Manager patching error ([0a8cd7a](0a8cd7a7db))
2025-09-04 14:06:03 +00:00
LisoUseInAIKyrios
0a8cd7a7db fix(Instagram - Hide navigation buttons): Fix Manager patching error 2025-09-04 16:01:50 +02:00
semantic-release-bot
39f90e4b11 chore: Release v5.35.0-dev.2 [skip ci]
# [5.35.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.1...v5.35.0-dev.2) (2025-09-04)

### Bug Fixes

* Revert dependency updates to fix Manager pre-release patching ([9256aa4](9256aa4548))
2025-09-04 10:27:39 +00:00
LisoUseInAIKyrios
9256aa4548 fix: Revert dependency updates to fix Manager pre-release patching 2025-09-04 12:23:56 +02:00
semantic-release-bot
7973c75552 chore: Release v5.35.0-dev.1 [skip ci]
# [5.35.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.3...v5.35.0-dev.1) (2025-09-03)

### Features

* **Instagram:** Add `Hide navigation buttons` patch ([#5678](https://github.com/ReVanced/revanced-patches/issues/5678)) ([1dbc2d4](1dbc2d4057))
2025-09-03 17:43:47 +00:00
github-actions[bot]
2b2307416a chore: Sync translations (#5755) 2025-09-03 19:41:04 +02:00
PainfulPaladins
1dbc2d4057 feat(Instagram): Add Hide navigation buttons patch (#5678)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2025-09-03 19:39:25 +02:00
dependabot[bot]
f6917dc361 chore(deps): Bump com.google.protobuf:protoc from 4.31.1 to 4.32.0 (#5751) 2025-09-02 18:28:15 +02:00
dependabot[bot]
d2f043e11a chore(deps): Bump com.google.protobuf:protobuf-javalite from 4.31.1 to 4.32.0 (#5750) 2025-09-02 17:10:45 +02:00
dependabot[bot]
a392bc0dfd chore(deps): Bump actions/setup-java from 4 to 5 (#5746) 2025-09-02 12:43:12 +02:00
dependabot[bot]
dfc127048a chore(deps): Bump actions/attest-build-provenance from 2 to 3 (#5743) 2025-09-02 12:42:08 +02:00
dependabot[bot]
ed31d0cab6 chore(deps): Bump actions/checkout from 4 to 5 (#5745) 2025-09-02 12:41:29 +02:00
dependabot[bot]
0df6315f9c chore(deps): Bump cycjimmy/semantic-release-action from 4 to 5 (#5741) 2025-09-02 12:40:08 +02:00
semantic-release-bot
f14259f9ef chore: Release v5.34.1-dev.3 [skip ci]
## [5.34.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.2...v5.34.1-dev.3) (2025-08-24)

### Bug Fixes

* **YouTube - Hide layout components:** Hide Playable shelf header ([1473db0](1473db0bef))
2025-08-24 03:30:00 +00:00
LisoUseInAIKyrios
1473db0bef fix(YouTube - Hide layout components): Hide Playable shelf header 2025-08-23 23:26:02 -04:00
github-actions[bot]
829ca58a55 chore: Sync translations (#5707) 2025-08-23 23:23:49 -04:00
semantic-release-bot
aace741e25 chore: Release v5.34.1-dev.2 [skip ci]
## [5.34.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.1...v5.34.1-dev.2) (2025-08-22)

### Bug Fixes

* **Proton mail:** Constrain patches to last working app target ([1895291](189529151a))
2025-08-22 04:12:59 +00:00
LisoUseInAIKyrios
189529151a fix(Proton mail): Constrain patches to last working app target 2025-08-22 00:10:03 -04:00
semantic-release-bot
51237c177a chore: Release v5.34.1-dev.1 [skip ci]
## [5.34.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.34.0...v5.34.1-dev.1) (2025-08-21)

### Bug Fixes

* **Spotify - Unlock Premium:** Make compatible with latest versions again by fixing fingerprint ([#5684](https://github.com/ReVanced/revanced-patches/issues/5684)) ([23496c7](23496c7c36))
2025-08-21 19:20:39 +00:00
Nuckyz
23496c7c36 fix(Spotify - Unlock Premium): Make compatible with latest versions again by fixing fingerprint (#5684) 2025-08-21 15:17:29 -04:00
semantic-release-bot
e6823d8924 chore: Release v5.34.0 [skip ci]
# [5.34.0](https://github.com/ReVanced/revanced-patches/compare/v5.33.0...v5.34.0) (2025-08-19)

### Bug Fixes

* **Backdrops:** Remove broken patch that is no longer supported ([#5627](https://github.com/ReVanced/revanced-patches/issues/5627)) ([c3e571e](c3e571e765))
* **pixiv - Hide ads:** Constrain patch to last working app target ([b702dce](b702dceda0))
* **Twitch:** Constrain patches to last working app targets ([#5373](https://github.com/ReVanced/revanced-patches/issues/5373)) ([d7eb6e8](d7eb6e87a5))
* **YouTube - Hide layout components:** Do not hide community posts on channel profiles ([#5634](https://github.com/ReVanced/revanced-patches/issues/5634)) ([61824ad](61824ade23))
* **YouTube - Player Controls:** Fix chapter title overlapping the bottom buttons ([#5673](https://github.com/ReVanced/revanced-patches/issues/5673)) ([150bee2](150bee2833))
* **YouTube - SponsorBlock:** Do not hide voting or create button when the video ends ([25470ba](25470baeee))
* **YouTube - Video playback:** Disable HDR video does not disable Dolby Vision HDR ([#5661](https://github.com/ReVanced/revanced-patches/issues/5661)) ([4aaa7ca](4aaa7ca895))
* **YouTube - Video quality:** Fix additional incorrect quality resolutions used by YouTube ([6bd9e49](6bd9e49c7a))
* **YouTube - Video quality:** Show FHD+ icon for 1080p 60fps enhanced bitrate ([e579c56](e579c56921))
* **YouTube:** Use correct fade out animation when tapping to dismiss the video overlay ([#5670](https://github.com/ReVanced/revanced-patches/issues/5670)) ([01a04c3](01a04c338c))

### Features

* **Instagram:** Support latest app version ([#5611](https://github.com/ReVanced/revanced-patches/issues/5611)) ([562e005](562e005772))
* **NU.nl:** Support latest app version ([#5643](https://github.com/ReVanced/revanced-patches/issues/5643)) ([1bb8c53](1bb8c53ed3))
* **YouTube - Hide player flyout menu items:** Add option to hide quality flyout menu ([809e013](809e013c4e))
* **YouTube - Hide video action buttons:** Add "Hide Hype button" setting ([fe66bae](fe66baedb7))
* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([40ac8e1](40ac8e1142))
* **YouTube - Playback speed:** Show current playback speed on player speed dialog button ([#5607](https://github.com/ReVanced/revanced-patches/issues/5607)) ([30176a3](30176a3318))
* **YouTube:** Add `Disable sign in to TV popup` patch ([#5639](https://github.com/ReVanced/revanced-patches/issues/5639)) ([56fbd8c](56fbd8cce0))
2025-08-19 15:12:22 +00:00
LisoUseInAIKyrios
43597dab21 chore: Merge branch dev to main (#5617) 2025-08-19 11:08:46 -04:00
semantic-release-bot
c0824db142 chore: Release v5.34.0-dev.13 [skip ci]
# [5.34.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.12...v5.34.0-dev.13) (2025-08-19)

### Bug Fixes

* **YouTube - Player Controls:** Fix chapter title overlapping the bottom buttons ([#5673](https://github.com/ReVanced/revanced-patches/issues/5673)) ([150bee2](150bee2833))
2025-08-19 14:55:36 +00:00
github-actions[bot]
1b7f84b7fa chore: Sync translations (#5677) 2025-08-19 10:52:35 -04:00
semantic-release-bot
6d87c848d6 chore: Release v5.34.0-dev.13 [skip ci]
# [5.34.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.12...v5.34.0-dev.13) (2025-08-18)

### Bug Fixes

* **YouTube - Player Controls:** Fix chapter title overlapping the bottom buttons ([#5673](https://github.com/ReVanced/revanced-patches/issues/5673)) ([150bee2](150bee2833))
2025-08-18 22:29:41 +00:00
MarcaD
150bee2833 fix(YouTube - Player Controls): Fix chapter title overlapping the bottom buttons (#5673)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2025-08-18 18:27:14 -04:00
semantic-release-bot
c3ee6eca44 chore: Release v5.34.0-dev.12 [skip ci]
# [5.34.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.11...v5.34.0-dev.12) (2025-08-18)

### Bug Fixes

* **YouTube:** Use correct fade out animation when tapping to dismiss the video overlay ([#5670](https://github.com/ReVanced/revanced-patches/issues/5670)) ([01a04c3](01a04c338c))
2025-08-18 00:17:30 +00:00
LisoUseInAIKyrios
01a04c338c fix(YouTube): Use correct fade out animation when tapping to dismiss the video overlay (#5670) 2025-08-17 20:14:44 -04:00
github-actions[bot]
3130225d9d chore: Sync translations (#5671) 2025-08-17 20:13:55 -04:00
LisoUseInAIKyrios
16b27fb872 chore: Fix typo 2025-08-17 11:17:54 -04:00
LisoUseInAIKyrios
bedabd3fa3 refactor: Show SB buttons with other overlay buttons when the video has ended 2025-08-16 16:24:24 -04:00
semantic-release-bot
84f3c6f02d chore: Release v5.34.0-dev.11 [skip ci]
# [5.34.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.10...v5.34.0-dev.11) (2025-08-16)

### Bug Fixes

* **YouTube - SponsorBlock:** Do not hide voting or create button when the video ends ([25470ba](25470baeee))
2025-08-16 20:21:35 +00:00
LisoUseInAIKyrios
25470baeee fix(YouTube - SponsorBlock): Do not hide voting or create button when the video ends
This logic is no longer needed, since YouTube no longer hides the overlay buttons when the video ends
2025-08-16 16:17:43 -04:00
semantic-release-bot
b86da73a87 chore: Release v5.34.0-dev.10 [skip ci]
# [5.34.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.9...v5.34.0-dev.10) (2025-08-16)

### Bug Fixes

* **YouTube - Video playback:** Disable HDR video does not disable Dolby Vision HDR ([#5661](https://github.com/ReVanced/revanced-patches/issues/5661)) ([4aaa7ca](4aaa7ca895))

### Features

* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([40ac8e1](40ac8e1142))
2025-08-16 19:14:17 +00:00
LisoUseInAIKyrios
4aaa7ca895 fix(YouTube - Video playback): Disable HDR video does not disable Dolby Vision HDR (#5661) 2025-08-16 15:10:31 -04:00
semantic-release-bot
d3f63461e7 chore: Release v5.34.0-dev.10 [skip ci]
# [5.34.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.9...v5.34.0-dev.10) (2025-08-16)

### Features

* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([40ac8e1](40ac8e1142))
2025-08-16 17:53:26 +00:00
github-actions[bot]
7a3ace2231 chore: Sync translations (#5664) 2025-08-16 13:50:35 -04:00
semantic-release-bot
c89668a540 chore: Release v5.34.0-dev.10 [skip ci]
# [5.34.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.9...v5.34.0-dev.10) (2025-08-16)

### Features

* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([40ac8e1](40ac8e1142))
2025-08-16 17:26:01 +00:00
LisoUseInAIKyrios
40ac8e1142 feat(YouTube - Hide video action buttons): Add "Hide Promote button" setting 2025-08-16 13:21:00 -04:00
github-actions[bot]
26c6420de5 chore: Sync translations (#5663) 2025-08-16 13:20:25 -04:00
github-actions[bot]
bfd3989995 chore: Sync translations (#5662) 2025-08-16 13:15:10 -04:00
LisoUseInAIKyrios
7e812ae1a8 chore: Fix typo 2025-08-16 12:23:09 -04:00
semantic-release-bot
c23a926b07 chore: Release v5.34.0-dev.9 [skip ci]
# [5.34.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.8...v5.34.0-dev.9) (2025-08-16)

### Features

* **YouTube - Hide video action buttons:** Add "Hide Hype button" setting ([fe66bae](fe66baedb7))
2025-08-16 15:48:20 +00:00
LisoUseInAIKyrios
fe66baedb7 feat(YouTube - Hide video action buttons): Add "Hide Hype button" setting 2025-08-16 11:45:36 -04:00
171 changed files with 3352 additions and 1394 deletions

View File

@@ -1,3 +1,257 @@
# [5.37.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0-dev.1) (2025-09-14)
### Features
* **Viber:** Add `Hide ads` patch ([#5826](https://github.com/ReVanced/revanced-patches/issues/5826)) ([0abfab7](https://github.com/ReVanced/revanced-patches/commit/0abfab79d7cda15bf17c53679fbfffb021662649))
# [5.36.0](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0) (2025-09-14)
### Bug Fixes
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](https://github.com/ReVanced/revanced-patches/commit/a53b00dd514dbe2b3406f3c1013a4f58a7f481c5))
### Features
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)
### Bug Fixes
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](https://github.com/ReVanced/revanced-patches/commit/a53b00dd514dbe2b3406f3c1013a4f58a7f481c5))
### Features
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)
### Bug Fixes
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](https://github.com/ReVanced/revanced-patches/commit/a53b00dd514dbe2b3406f3c1013a4f58a7f481c5))
### Features
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)
### Bug Fixes
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
### Features
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-12)
### Bug Fixes
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
### Features
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.1-dev.1...v5.36.0-dev.1) (2025-09-12)
### Features
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([2e042c4](https://github.com/ReVanced/revanced-patches/commit/2e042c4b3366fa3daf991d5560fcae991d00ad12))
## [5.35.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.35.1-dev.1) (2025-09-11)
### Bug Fixes
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([8491516](https://github.com/ReVanced/revanced-patches/commit/849151637389b8f399356d0d331bb74482f3f05d))
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([3af4126](https://github.com/ReVanced/revanced-patches/commit/3af41265338ddaab52d009f53370c57abddd4599))
# [5.35.0](https://github.com/ReVanced/revanced-patches/compare/v5.34.0...v5.35.0) (2025-09-09)
### Bug Fixes
* **Instagram - Hide navigation buttons:** Fix Manager patching error ([0d10e94](https://github.com/ReVanced/revanced-patches/commit/0d10e94663283fac09f3efc57c9b9805c38c4e13))
* **Proton mail:** Constrain patches to last working app target ([21c34b9](https://github.com/ReVanced/revanced-patches/commit/21c34b908e07a97de8c31c7c828b44a8cc4739b6))
* Revert dependency updates to fix Manager pre-release patching ([4c7a1a8](https://github.com/ReVanced/revanced-patches/commit/4c7a1a8554c67797bf663e5230f566c5a9b229af))
* **Spotify - Unlock Premium:** Make compatible with latest versions again by fixing fingerprint ([#5684](https://github.com/ReVanced/revanced-patches/issues/5684)) ([30dcff1](https://github.com/ReVanced/revanced-patches/commit/30dcff13a56883efc499b71faadb403877cd1c67))
* **YouTube - Hide layout components:** Hide Playable shelf header ([fbb5046](https://github.com/ReVanced/revanced-patches/commit/fbb50463f0e3f533a278c5251cfbce59f09ce641))
### Features
* **BaconReader:** Add `Fix Redgifs API` patch ([#5761](https://github.com/ReVanced/revanced-patches/issues/5761)) ([08868c0](https://github.com/ReVanced/revanced-patches/commit/08868c00d3c4f1f37f4a77f333a03ca5a3259b59))
* **Boost/Sync for Reddit:** Add `Fix Redgifs` patch ([#5725](https://github.com/ReVanced/revanced-patches/issues/5725)) ([c5e8079](https://github.com/ReVanced/revanced-patches/commit/c5e8079eab08075a72078cd0fa79f3beb1f75d98))
* **Instagram:** Add `Hide navigation buttons` patch ([#5678](https://github.com/ReVanced/revanced-patches/issues/5678)) ([415cf0f](https://github.com/ReVanced/revanced-patches/commit/415cf0fb5b9b3dcaf4592943a69eea1c10447b07))
* **Instagram:** Add `Hide Stories from Home` patch ([#5756](https://github.com/ReVanced/revanced-patches/issues/5756)) ([3ae3251](https://github.com/ReVanced/revanced-patches/commit/3ae3251dc0317b6ced136fe9aa14be369642f203))
# [5.35.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.4...v5.35.0-dev.5) (2025-09-06)
### Features
* **BaconReader:** Add `Fix Redgifs API` patch ([#5761](https://github.com/ReVanced/revanced-patches/issues/5761)) ([08868c0](https://github.com/ReVanced/revanced-patches/commit/08868c00d3c4f1f37f4a77f333a03ca5a3259b59))
* **Instagram:** Add `Hide Stories from Home` patch ([#5756](https://github.com/ReVanced/revanced-patches/issues/5756)) ([3ae3251](https://github.com/ReVanced/revanced-patches/commit/3ae3251dc0317b6ced136fe9aa14be369642f203))
# [5.35.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.3...v5.35.0-dev.4) (2025-09-04)
### Features
* **Boost/Sync for Reddit:** Add `Fix Redgifs` patch ([#5725](https://github.com/ReVanced/revanced-patches/issues/5725)) ([c5e8079](https://github.com/ReVanced/revanced-patches/commit/c5e8079eab08075a72078cd0fa79f3beb1f75d98))
# [5.35.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.2...v5.35.0-dev.3) (2025-09-04)
### Bug Fixes
* **Instagram - Hide navigation buttons:** Fix Manager patching error ([0d10e94](https://github.com/ReVanced/revanced-patches/commit/0d10e94663283fac09f3efc57c9b9805c38c4e13))
# [5.35.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.1...v5.35.0-dev.2) (2025-09-04)
### Bug Fixes
* Revert dependency updates to fix Manager pre-release patching ([4c7a1a8](https://github.com/ReVanced/revanced-patches/commit/4c7a1a8554c67797bf663e5230f566c5a9b229af))
# [5.35.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.3...v5.35.0-dev.1) (2025-09-03)
### Features
* **Instagram:** Add `Hide navigation buttons` patch ([#5678](https://github.com/ReVanced/revanced-patches/issues/5678)) ([415cf0f](https://github.com/ReVanced/revanced-patches/commit/415cf0fb5b9b3dcaf4592943a69eea1c10447b07))
## [5.34.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.2...v5.34.1-dev.3) (2025-08-24)
### Bug Fixes
* **YouTube - Hide layout components:** Hide Playable shelf header ([fbb5046](https://github.com/ReVanced/revanced-patches/commit/fbb50463f0e3f533a278c5251cfbce59f09ce641))
## [5.34.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.1...v5.34.1-dev.2) (2025-08-22)
### Bug Fixes
* **Proton mail:** Constrain patches to last working app target ([21c34b9](https://github.com/ReVanced/revanced-patches/commit/21c34b908e07a97de8c31c7c828b44a8cc4739b6))
## [5.34.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.34.0...v5.34.1-dev.1) (2025-08-21)
### Bug Fixes
* **Spotify - Unlock Premium:** Make compatible with latest versions again by fixing fingerprint ([#5684](https://github.com/ReVanced/revanced-patches/issues/5684)) ([30dcff1](https://github.com/ReVanced/revanced-patches/commit/30dcff13a56883efc499b71faadb403877cd1c67))
# [5.34.0](https://github.com/ReVanced/revanced-patches/compare/v5.33.0...v5.34.0) (2025-08-19)
### Bug Fixes
* **Backdrops:** Remove broken patch that is no longer supported ([#5627](https://github.com/ReVanced/revanced-patches/issues/5627)) ([ebb8332](https://github.com/ReVanced/revanced-patches/commit/ebb83320838aa99dd4417d45a50333dd42c1218a))
* **pixiv - Hide ads:** Constrain patch to last working app target ([d8ea56c](https://github.com/ReVanced/revanced-patches/commit/d8ea56ca4be47df1c43f96ec41b91c800f1d9daf))
* **Twitch:** Constrain patches to last working app targets ([#5373](https://github.com/ReVanced/revanced-patches/issues/5373)) ([29a4748](https://github.com/ReVanced/revanced-patches/commit/29a47481c4efa209a3a53df60613b59a73adbe07))
* **YouTube - Hide layout components:** Do not hide community posts on channel profiles ([#5634](https://github.com/ReVanced/revanced-patches/issues/5634)) ([9e3d5a2](https://github.com/ReVanced/revanced-patches/commit/9e3d5a2b36106479470f3f69920518b57e8c4dca))
* **YouTube - Player Controls:** Fix chapter title overlapping the bottom buttons ([#5673](https://github.com/ReVanced/revanced-patches/issues/5673)) ([09ccee7](https://github.com/ReVanced/revanced-patches/commit/09ccee71384df338bbf8acc1097f619a372c4868))
* **YouTube - SponsorBlock:** Do not hide voting or create button when the video ends ([6aba4e2](https://github.com/ReVanced/revanced-patches/commit/6aba4e284de9bb94b49eea8be2baf2870eecbbcf))
* **YouTube - Video playback:** Disable HDR video does not disable Dolby Vision HDR ([#5661](https://github.com/ReVanced/revanced-patches/issues/5661)) ([6dab988](https://github.com/ReVanced/revanced-patches/commit/6dab98810645b96bd0387ba7d607e5d8ffb1b5bb))
* **YouTube - Video quality:** Fix additional incorrect quality resolutions used by YouTube ([a2a1fbe](https://github.com/ReVanced/revanced-patches/commit/a2a1fbe2959be8334c54cfc3426c24a960c55c8f))
* **YouTube - Video quality:** Show FHD+ icon for 1080p 60fps enhanced bitrate ([76bed37](https://github.com/ReVanced/revanced-patches/commit/76bed3734093713af24ef065d5ffc5b1cd83f29a))
* **YouTube:** Use correct fade out animation when tapping to dismiss the video overlay ([#5670](https://github.com/ReVanced/revanced-patches/issues/5670)) ([cce6737](https://github.com/ReVanced/revanced-patches/commit/cce6737f627fc7621bbde50a5653b6af14c6f31a))
### Features
* **Instagram:** Support latest app version ([#5611](https://github.com/ReVanced/revanced-patches/issues/5611)) ([26fe690](https://github.com/ReVanced/revanced-patches/commit/26fe690dfbefe6c412c5f81f208a3b1d2fbd7a0a))
* **NU.nl:** Support latest app version ([#5643](https://github.com/ReVanced/revanced-patches/issues/5643)) ([7338e4a](https://github.com/ReVanced/revanced-patches/commit/7338e4a5a99f913256120d0d58fede3aa4ee8922))
* **YouTube - Hide player flyout menu items:** Add option to hide quality flyout menu ([eb55068](https://github.com/ReVanced/revanced-patches/commit/eb5506856a2eaf2a8585e598868ddba3e1429159))
* **YouTube - Hide video action buttons:** Add "Hide Hype button" setting ([f13f377](https://github.com/ReVanced/revanced-patches/commit/f13f3770e7c4fd5bff8f3e224fb1b1ead50a3c18))
* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([1959396](https://github.com/ReVanced/revanced-patches/commit/1959396a53f4c07b94acddc5c0ee6cdf7ade7c7b))
* **YouTube - Playback speed:** Show current playback speed on player speed dialog button ([#5607](https://github.com/ReVanced/revanced-patches/issues/5607)) ([279436a](https://github.com/ReVanced/revanced-patches/commit/279436a3657b50f98bb4cc64dc88dc14e422f204))
* **YouTube:** Add `Disable sign in to TV popup` patch ([#5639](https://github.com/ReVanced/revanced-patches/issues/5639)) ([d0e5bd0](https://github.com/ReVanced/revanced-patches/commit/d0e5bd0479a8910b081c483ed2a6ab4d7134e3c3))
# [5.34.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.12...v5.34.0-dev.13) (2025-08-19)
### Bug Fixes
* **YouTube - Player Controls:** Fix chapter title overlapping the bottom buttons ([#5673](https://github.com/ReVanced/revanced-patches/issues/5673)) ([09ccee7](https://github.com/ReVanced/revanced-patches/commit/09ccee71384df338bbf8acc1097f619a372c4868))
# [5.34.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.12...v5.34.0-dev.13) (2025-08-18)
### Bug Fixes
* **YouTube - Player Controls:** Fix chapter title overlapping the bottom buttons ([#5673](https://github.com/ReVanced/revanced-patches/issues/5673)) ([09ccee7](https://github.com/ReVanced/revanced-patches/commit/09ccee71384df338bbf8acc1097f619a372c4868))
# [5.34.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.11...v5.34.0-dev.12) (2025-08-18)
### Bug Fixes
* **YouTube:** Use correct fade out animation when tapping to dismiss the video overlay ([#5670](https://github.com/ReVanced/revanced-patches/issues/5670)) ([cce6737](https://github.com/ReVanced/revanced-patches/commit/cce6737f627fc7621bbde50a5653b6af14c6f31a))
# [5.34.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.10...v5.34.0-dev.11) (2025-08-16)
### Bug Fixes
* **YouTube - SponsorBlock:** Do not hide voting or create button when the video ends ([6aba4e2](https://github.com/ReVanced/revanced-patches/commit/6aba4e284de9bb94b49eea8be2baf2870eecbbcf))
# [5.34.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.9...v5.34.0-dev.10) (2025-08-16)
### Bug Fixes
* **YouTube - Video playback:** Disable HDR video does not disable Dolby Vision HDR ([#5661](https://github.com/ReVanced/revanced-patches/issues/5661)) ([6dab988](https://github.com/ReVanced/revanced-patches/commit/6dab98810645b96bd0387ba7d607e5d8ffb1b5bb))
### Features
* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([1959396](https://github.com/ReVanced/revanced-patches/commit/1959396a53f4c07b94acddc5c0ee6cdf7ade7c7b))
# [5.34.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.9...v5.34.0-dev.10) (2025-08-16)
### Features
* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([1959396](https://github.com/ReVanced/revanced-patches/commit/1959396a53f4c07b94acddc5c0ee6cdf7ade7c7b))
# [5.34.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.9...v5.34.0-dev.10) (2025-08-16)
### Features
* **YouTube - Hide video action buttons:** Add "Hide Promote button" setting ([1959396](https://github.com/ReVanced/revanced-patches/commit/1959396a53f4c07b94acddc5c0ee6cdf7ade7c7b))
# [5.34.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.8...v5.34.0-dev.9) (2025-08-16)
### Features
* **YouTube - Hide video action buttons:** Add "Hide Hype button" setting ([f13f377](https://github.com/ReVanced/revanced-patches/commit/f13f3770e7c4fd5bff8f3e224fb1b1ead50a3c18))
# [5.34.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.7...v5.34.0-dev.8) (2025-08-15)

8
adsfund.json Normal file
View File

@@ -0,0 +1,8 @@
{
"info": "This is verification file for ads.fund project",
"project": {
"name": "Revanced Patches",
"walletAddress": "0x7ab4091e00363654bf84B34151225742cd92FCE5",
"tokenAddress": "0xadf325f255083a3f3d9a9d01ffb3db52a148d802"
}
}

View File

@@ -0,0 +1,5 @@
dependencies {
compileOnly(project(":extensions:shared:library"))
compileOnly(libs.annotation)
compileOnly(libs.okhttp)
}

View File

@@ -0,0 +1 @@
<manifest/>

View File

@@ -0,0 +1,22 @@
package app.revanced.extension.baconreader;
import app.revanced.extension.shared.fixes.redgifs.BaseFixRedgifsApiPatch;
import okhttp3.OkHttpClient;
/**
* @noinspection unused
*/
public class FixRedgifsApiPatch extends BaseFixRedgifsApiPatch {
static {
INSTANCE = new FixRedgifsApiPatch();
}
public String getDefaultUserAgent() {
// BaconReader uses a static user agent for Redgifs API calls
return "BaconReader";
}
public static OkHttpClient install(OkHttpClient.Builder builder) {
return builder.addInterceptor(INSTANCE).build();
}
}

View File

@@ -1,4 +1,6 @@
dependencies {
compileOnly(project(":extensions:shared:library"))
compileOnly(project(":extensions:boostforreddit:stub"))
compileOnly(libs.annotation)
compileOnly(libs.okhttp)
}

View File

@@ -0,0 +1,22 @@
package app.revanced.extension.boostforreddit;
import app.revanced.extension.shared.fixes.redgifs.BaseFixRedgifsApiPatch;
import okhttp3.OkHttpClient;
/**
* @noinspection unused
*/
public class FixRedgifsApiPatch extends BaseFixRedgifsApiPatch {
static {
INSTANCE = new FixRedgifsApiPatch();
}
public String getDefaultUserAgent() {
// Boost uses a static user agent for Redgifs API calls
return "Boost";
}
public static OkHttpClient createClient() {
return new OkHttpClient.Builder().addInterceptor(INSTANCE).build();
}
}

View File

@@ -1,27 +0,0 @@
package app.revanced.extension.music.spoof;
/**
* @noinspection unused
*/
public class SpoofClientPatch {
private static final int CLIENT_TYPE_ID = 26;
private static final String CLIENT_VERSION = "6.21";
private static final String DEVICE_MODEL = "iPhone16,2";
private static final String OS_VERSION = "17.7.2.21H221";
public static int getClientId() {
return CLIENT_TYPE_ID;
}
public static String getClientVersion() {
return CLIENT_VERSION;
}
public static String getClientModel() {
return DEVICE_MODEL;
}
public static String getOsVersion() {
return OS_VERSION;
}
}

View File

@@ -1,3 +1,4 @@
dependencies {
implementation(project(":extensions:shared:library"))
compileOnly(libs.okhttp)
}

View File

@@ -18,4 +18,5 @@ android {
dependencies {
compileOnly(libs.annotation)
compileOnly(libs.okhttp)
}

View File

@@ -0,0 +1,71 @@
package app.revanced.extension.shared.fixes.redgifs;
import androidx.annotation.NonNull;
import org.json.JSONException;
import java.io.IOException;
import java.net.HttpURLConnection;
import app.revanced.extension.shared.Logger;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public abstract class BaseFixRedgifsApiPatch implements Interceptor {
protected static BaseFixRedgifsApiPatch INSTANCE;
public abstract String getDefaultUserAgent();
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (!request.url().host().equals("api.redgifs.com")) {
return chain.proceed(request);
}
String userAgent = getDefaultUserAgent();
if (request.header("Authorization") != null) {
Response response = chain.proceed(request.newBuilder().header("User-Agent", userAgent).build());
if (response.isSuccessful()) {
return response;
}
// It's possible that the user agent is being overwritten later down in the interceptor
// chain, so make sure we grab the new user agent from the request headers.
userAgent = response.request().header("User-Agent");
response.close();
}
try {
RedgifsTokenManager.RedgifsToken token = RedgifsTokenManager.refreshToken(userAgent);
// Emulate response for old OAuth endpoint
if (request.url().encodedPath().equals("/v2/oauth/client")) {
String responseBody = RedgifsTokenManager.getEmulatedOAuthResponseBody(token);
return new Response.Builder()
.message("OK")
.code(HttpURLConnection.HTTP_OK)
.protocol(Protocol.HTTP_1_1)
.request(request)
.header("Content-Type", "application/json")
.body(ResponseBody.create(
responseBody, MediaType.get("application/json")))
.build();
}
Request modifiedRequest = request.newBuilder()
.header("Authorization", "Bearer " + token.getAccessToken())
.header("User-Agent", userAgent)
.build();
return chain.proceed(modifiedRequest);
} catch (JSONException ex) {
Logger.printException(() -> "Could not parse Redgifs response", ex);
throw new IOException(ex);
}
}
}

View File

@@ -0,0 +1,94 @@
package app.revanced.extension.shared.fixes.redgifs;
import static app.revanced.extension.shared.requests.Route.Method.GET;
import androidx.annotation.GuardedBy;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import app.revanced.extension.shared.requests.Requester;
/**
* Manages Redgifs token lifecycle.
*/
public class RedgifsTokenManager {
public static class RedgifsToken {
// Expire after 23 hours to provide some breathing room
private static final long EXPIRY_SECONDS = 23 * 60 * 60;
private final String accessToken;
private final long refreshTimeInSeconds;
public RedgifsToken(String accessToken, long refreshTime) {
this.accessToken = accessToken;
this.refreshTimeInSeconds = refreshTime;
}
public String getAccessToken() {
return accessToken;
}
public long getExpiryTimeInSeconds() {
return refreshTimeInSeconds + EXPIRY_SECONDS;
}
public boolean isValid() {
if (accessToken == null) return false;
return getExpiryTimeInSeconds() >= System.currentTimeMillis() / 1000;
}
}
public static final String REDGIFS_API_HOST = "https://api.redgifs.com";
private static final String GET_TEMPORARY_TOKEN = REDGIFS_API_HOST + "/v2/auth/temporary";
@GuardedBy("itself")
private static final Map<String, RedgifsToken> tokenMap = new HashMap<>();
private static String getToken(String userAgent) throws IOException, JSONException {
HttpURLConnection connection = (HttpURLConnection) new URL(GET_TEMPORARY_TOKEN).openConnection();
connection.setFixedLengthStreamingMode(0);
connection.setRequestMethod(GET.name());
connection.setRequestProperty("User-Agent", userAgent);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
connection.setUseCaches(false);
JSONObject responseObject = Requester.parseJSONObject(connection);
return responseObject.getString("token");
}
public static RedgifsToken refreshToken(String userAgent) throws IOException, JSONException {
synchronized(tokenMap) {
// Reference: https://github.com/JeffreyCA/Apollo-ImprovedCustomApi/pull/67
RedgifsToken token = tokenMap.get(userAgent);
if (token != null && token.isValid()) {
return token;
}
// Copy user agent from original request if present because Redgifs verifies
// that the user agent in subsequent requests matches the one in the OAuth token.
String accessToken = getToken(userAgent);
long refreshTime = System.currentTimeMillis() / 1000;
token = new RedgifsToken(accessToken, refreshTime);
tokenMap.put(userAgent, token);
return token;
}
}
public static String getEmulatedOAuthResponseBody(RedgifsToken token) throws JSONException {
// Reference: https://github.com/JeffreyCA/Apollo-ImprovedCustomApi/pull/67
JSONObject responseObject = new JSONObject();
responseObject.put("access_token", token.accessToken);
responseObject.put("expiry_time", token.getExpiryTimeInSeconds() - (System.currentTimeMillis() / 1000));
responseObject.put("scope", "read");
responseObject.put("token_type", "Bearer");
return responseObject.toString();
}
}

View File

@@ -34,6 +34,6 @@ public class BaseSettings {
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability());
// Client type must be last spoof setting due to cyclic references.
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_UNPLUGGED, true, parent(SPOOF_VIDEO_STREAMS));
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR_NO_AUTH, true, parent(SPOOF_VIDEO_STREAMS));
}

View File

@@ -96,22 +96,6 @@ public enum ClientType {
forceAVC()
? "iOS TV Force AVC"
: "iOS TV"
),
ANDROID_VR_AUTH(
ANDROID_VR_NO_AUTH.id,
ANDROID_VR_NO_AUTH.clientName,
ANDROID_VR_NO_AUTH.packageName,
ANDROID_VR_NO_AUTH.deviceMake,
ANDROID_VR_NO_AUTH.deviceModel,
ANDROID_VR_NO_AUTH.osName,
ANDROID_VR_NO_AUTH.osVersion,
ANDROID_VR_NO_AUTH.androidSdkVersion,
ANDROID_VR_NO_AUTH.buildId,
ANDROID_VR_NO_AUTH.cronetVersion,
ANDROID_VR_NO_AUTH.clientVersion,
ANDROID_VR_NO_AUTH.requiresAuth,
true,
"Android VR Auth"
);
private static boolean forceAVC() {

View File

@@ -2,4 +2,5 @@ dependencies {
compileOnly(project(":extensions:shared:library"))
compileOnly(project(":extensions:syncforreddit:stub"))
compileOnly(libs.annotation)
compileOnly(libs.okhttp)
}

View File

@@ -0,0 +1,22 @@
package app.revanced.extension.syncforreddit;
import app.revanced.extension.shared.fixes.redgifs.BaseFixRedgifsApiPatch;
import okhttp3.OkHttpClient;
/**
* @noinspection unused
*/
public class FixRedgifsApiPatch extends BaseFixRedgifsApiPatch {
static {
INSTANCE = new FixRedgifsApiPatch();
}
public String getDefaultUserAgent() {
// To be filled in by patch
return "";
}
public static OkHttpClient install(OkHttpClient.Builder builder) {
return builder.addInterceptor(INSTANCE).build();
}
}

View File

@@ -1,5 +1,7 @@
package app.revanced.extension.youtube.patches;
import android.view.Display;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
@@ -8,8 +10,10 @@ public class DisableHdrPatch {
/**
* Injection point.
*/
public static boolean disableHDRVideo() {
return !Settings.DISABLE_HDR_VIDEO.get();
public static int[] disableHdrVideo(Display.HdrCapabilities capabilities) {
return Settings.DISABLE_HDR_VIDEO.get()
? new int[0]
: capabilities.getSupportedHdrTypes();
}
}

View File

@@ -57,11 +57,4 @@ public class PlayerControlsPatch {
private static void fullscreenButtonVisibilityChanged(boolean isVisible) {
// Code added during patching.
}
/**
* Injection point.
*/
public static String getPlayerTopControlsLayoutResourceName(String original) {
return "default";
}
}

View File

@@ -0,0 +1,18 @@
package app.revanced.extension.youtube.patches;
import androidx.annotation.Nullable;
import app.revanced.extension.youtube.shared.PlayerControlsVisibility;
@SuppressWarnings("unused")
public class PlayerControlsVisibilityHookPatch {
/**
* Injection point.
*/
public static void setPlayerControlsVisibility(@Nullable Enum<?> youTubePlayerControlsVisibility) {
if (youTubePlayerControlsVisibility == null) return;
PlayerControlsVisibility.setFromString(youTubePlayerControlsVisibility.name());
}
}

View File

@@ -513,6 +513,9 @@ public final class VideoInformation {
Logger.printDebug(() -> "VideoQualities: " + Arrays.toString(currentQualities));
}
// On extremely slow internet connections the index can initially be -1
originalQualityIndex = Math.max(0, originalQualityIndex);
VideoQuality updatedCurrentQuality = qualities[originalQualityIndex];
if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE
&& (currentQuality == null || currentQuality != updatedCurrentQuality)) {

View File

@@ -83,6 +83,14 @@ final class ButtonsFilter extends Filter {
new ByteArrayFilterGroup(
Settings.HIDE_CLIP_BUTTON,
"yt_outline_scissors"
),
new ByteArrayFilterGroup(
Settings.HIDE_HYPE_BUTTON,
"yt_outline_star_shooting"
),
new ByteArrayFilterGroup(
Settings.HIDE_PROMOTE_BUTTON,
"yt_outline_megaphone"
)
);
}

View File

@@ -45,6 +45,7 @@ public final class LayoutComponentsFilter extends Filter {
private final StringFilterGroup chipBar;
private final StringFilterGroup channelProfile;
private final ByteArrayFilterGroupList channelProfileBuffer;
private final ByteArrayFilterGroup playablesBuffer;
public LayoutComponentsFilter() {
exceptions.addPatterns(
@@ -190,6 +191,12 @@ public final class LayoutComponentsFilter extends Filter {
"mini_game_card.eml"
);
// Playable horizontal shelf header.
playablesBuffer = new ByteArrayFilterGroup(
Settings.HIDE_PLAYABLES,
"FEmini_app_destination"
);
final var quickActions = new StringFilterGroup(
Settings.HIDE_QUICK_ACTIONS,
"quick_actions"
@@ -342,7 +349,9 @@ public final class LayoutComponentsFilter extends Filter {
}
if (matchedGroup == horizontalShelves) {
return contentIndex == 0 && (hideShelves() || ticketShelf.check(buffer).isFiltered());
return contentIndex == 0 && (hideShelves()
|| ticketShelf.check(buffer).isFiltered()
|| playablesBuffer.check(buffer).isFiltered());
}
if (matchedGroup == chipBar) {

View File

@@ -9,7 +9,7 @@ public class SpoofAppVersionPatch {
private static final String SPOOF_APP_VERSION_TARGET = Settings.SPOOF_APP_VERSION_TARGET.get();
/**
* Injection point
* injection point.
*/
public static String getYouTubeVersionOverride(String version) {
if (SPOOF_APP_VERSION_ENABLED) return SPOOF_APP_VERSION_TARGET;

View File

@@ -126,7 +126,7 @@ public final class SeekbarColorPatch {
}
/**
* Injection point
* injection point.
*/
public static boolean useLotteLaunchSplashScreen(boolean original) {
// This method is only used for development purposes to force the old style launch screen.

View File

@@ -223,7 +223,9 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_ASK_BUTTON = new BooleanSetting("revanced_hide_ask_button", FALSE);
public static final BooleanSetting HIDE_CLIP_BUTTON = new BooleanSetting("revanced_hide_clip_button", TRUE);
public static final BooleanSetting HIDE_DOWNLOAD_BUTTON = new BooleanSetting("revanced_hide_download_button", FALSE);
public static final BooleanSetting HIDE_HYPE_BUTTON = new BooleanSetting("revanced_hide_hype_button", FALSE);
public static final BooleanSetting HIDE_LIKE_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_like_dislike_button", FALSE);
public static final BooleanSetting HIDE_PROMOTE_BUTTON = new BooleanSetting("revanced_hide_promote_button", FALSE);
public static final BooleanSetting HIDE_REMIX_BUTTON = new BooleanSetting("revanced_hide_remix_button", TRUE);
public static final BooleanSetting HIDE_REPORT_BUTTON = new BooleanSetting("revanced_hide_report_button", FALSE);
public static final BooleanSetting HIDE_SAVE_BUTTON = new BooleanSetting("revanced_hide_save_button", FALSE);
@@ -434,6 +436,9 @@ public class Settings extends BaseSettings {
public static final StringSetting SB_CATEGORY_HIGHLIGHT = new StringSetting("sb_highlight", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_HIGHLIGHT_COLOR = new StringSetting("sb_highlight_color", "#FF1684");
public static final FloatSetting SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_HOOK = new StringSetting("sb_hook", IGNORE.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_HOOK_COLOR = new StringSetting("sb_hook_color", "#395699");
public static final FloatSetting SB_CATEGORY_HOOK_OPACITY = new FloatSetting("sb_hook_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_INTRO = new StringSetting("sb_intro", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_INTRO_COLOR = new StringSetting("sb_intro_color", "#00FFFF");
public static final FloatSetting SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f);

View File

@@ -86,7 +86,7 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
String summary = str(key + "_summary");
// Android VR supports AV1 but all other clients do not.
if (clientType != ClientType.ANDROID_VR_AUTH && clientType != ClientType.ANDROID_VR_NO_AUTH) {
if (clientType != ClientType.ANDROID_VR_NO_AUTH) {
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
}

View File

@@ -0,0 +1,48 @@
package app.revanced.extension.youtube.shared
import app.revanced.extension.shared.Logger
import app.revanced.extension.youtube.Event
/**
* PlayerControls visibility state.
*/
enum class PlayerControlsVisibility {
PLAYER_CONTROLS_VISIBILITY_UNKNOWN,
PLAYER_CONTROLS_VISIBILITY_WILL_HIDE,
PLAYER_CONTROLS_VISIBILITY_HIDDEN,
PLAYER_CONTROLS_VISIBILITY_WILL_SHOW,
PLAYER_CONTROLS_VISIBILITY_SHOWN;
companion object {
private val nameToPlayerControlsVisibility = PlayerControlsVisibility.entries.associateBy { it.name }
@JvmStatic
fun setFromString(enumName: String) {
val newType = nameToPlayerControlsVisibility[enumName]
if (newType == null) {
Logger.printException { "Unknown PlayerControlsVisibility encountered: $enumName" }
} else {
current = newType
}
}
@JvmStatic
var current
get() = currentPlayerControlsVisibility
private set(type) {
if (currentPlayerControlsVisibility != type) {
Logger.printDebug { "Changed to: $type" }
currentPlayerControlsVisibility = type
onChange(type)
}
}
@Volatile // Read/write from different threads.
private var currentPlayerControlsVisibility = PLAYER_CONTROLS_VISIBILITY_UNKNOWN
@JvmStatic
val onChange = Event<PlayerControlsVisibility>()
}
}

View File

@@ -13,9 +13,9 @@ import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Range;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
@@ -168,6 +168,11 @@ public class SegmentPlaybackController {
*/
private static WeakReference<Dialog> toastDialogRef = new WeakReference<>(null);
/**
* Visibility of the ad progress UI component.
*/
private static volatile int adProgressTextVisibility = -1;
static {
// Dismiss toast if app changes to PiP while undo skip is shown.
PlayerType.getOnChange().addObserver((PlayerType type) -> {
@@ -337,6 +342,7 @@ public class SegmentPlaybackController {
*/
static void executeDownloadSegments(String videoId) {
Objects.requireNonNull(videoId);
Utils.verifyOffMainThread();
SponsorSegment[] segments = SBRequester.getSegments(videoId);
@@ -368,6 +374,35 @@ public class SegmentPlaybackController {
});
}
/**
* Injection point.
*/
@SuppressWarnings("unused")
public static void setAdProgressTextVisibility(int visibility) {
if (adProgressTextVisibility != visibility) {
adProgressTextVisibility = visibility;
Logger.printDebug(() -> {
String visibilityMessage = switch (visibility) {
case View.VISIBLE -> "VISIBLE";
case View.GONE -> "GONE";
case View.INVISIBLE -> "INVISIBLE";
default -> "UNKNOWN";
};
return "AdProgressText visibility changed to: " + visibilityMessage;
});
}
}
/**
* When a video ad is playing in a regular video player, segments or the Skip button should be hidden.
* @return Whether the Ad Progress TextView is visible in the regular video player.
*/
public static boolean isAdProgressTextVisible() {
return adProgressTextVisibility == View.VISIBLE;
}
/**
* Injection point.
* Updates SponsorBlock every 1000ms.
@@ -377,7 +412,8 @@ public class SegmentPlaybackController {
try {
if (!Settings.SB_ENABLED.get()
|| PlayerType.getCurrent().isNoneOrHidden() // Shorts playback.
|| segments == null || segments.length == 0) {
|| segments == null || segments.length == 0
|| isAdProgressTextVisible()) {
return;
}
Logger.printDebug(() -> "setVideoTime: " + millis);
@@ -672,7 +708,14 @@ public class SegmentPlaybackController {
// Check for any smaller embedded segments, and count those as auto-skipped.
final boolean showSkipToast = Settings.SB_TOAST_ON_SKIP.get();
for (SponsorSegment otherSegment : Objects.requireNonNull(segments)) {
if (segmentToSkip.end < otherSegment.start) {
if (otherSegment.end <= segmentToSkip.start) {
// Other segment does not overlap, and is before this skipped segment.
// This situation can only happen if a video is opened and adjusted to
// a later time in the video where earlier auto skip segments
// have not been encountered yet.
continue;
}
if (segmentToSkip.end <= otherSegment.start) {
break; // No other segments can be contained.
}
@@ -877,7 +920,7 @@ public class SegmentPlaybackController {
}
/**
* Injection point
* injection point.
*/
@SuppressWarnings("unused")
public static void setSponsorBarRect(Object self) {
@@ -909,7 +952,7 @@ public class SegmentPlaybackController {
}
/**
* Injection point
* injection point.
*/
@SuppressWarnings("unused")
public static void setSponsorBarThickness(int thickness) {
@@ -923,7 +966,8 @@ public class SegmentPlaybackController {
public static String appendTimeWithoutSegments(String totalTime) {
try {
if (Settings.SB_ENABLED.get() && Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.get()
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)) {
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)
&& !isAdProgressTextVisible()) {
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages
return "\u202D" + totalTime + timeWithoutSegments; // u202D = left to right override
}
@@ -984,7 +1028,7 @@ public class SegmentPlaybackController {
@SuppressWarnings("unused")
public static void drawSponsorTimeBars(final Canvas canvas, final float posY) {
try {
if (segments == null) return;
if (segments == null || isAdProgressTextVisible()) return;
final long videoLength = VideoInformation.getVideoLength();
if (videoLength <= 0) return;

View File

@@ -52,6 +52,8 @@ public enum SegmentCategory {
sf("revanced_sb_skip_button_preview_beginning"), sf("revanced_sb_skip_button_preview_middle"), sf("revanced_sb_skip_button_preview_end"),
sf("revanced_sb_skipped_preview_beginning"), sf("revanced_sb_skipped_preview_middle"), sf("revanced_sb_skipped_preview_end"),
SB_CATEGORY_PREVIEW, SB_CATEGORY_PREVIEW_COLOR, SB_CATEGORY_PREVIEW_OPACITY),
HOOK("hook", sf("revanced_sb_segments_hook"), sf("revanced_sb_segments_hook_sum"), sf("revanced_sb_skip_button_hook"), sf("revanced_sb_skipped_hook"),
SB_CATEGORY_HOOK, SB_CATEGORY_HOOK_COLOR, SB_CATEGORY_HOOK_OPACITY),
FILLER("filler", sf("revanced_sb_segments_filler"), sf("revanced_sb_segments_filler_sum"), sf("revanced_sb_skip_button_filler"), sf("revanced_sb_skipped_filler"),
SB_CATEGORY_FILLER, SB_CATEGORY_FILLER_COLOR, SB_CATEGORY_FILLER_OPACITY),
MUSIC_OFFTOPIC("music_offtopic", sf("revanced_sb_segments_nomusic"), sf("revanced_sb_segments_nomusic_sum"), sf("revanced_sb_skip_button_nomusic"), sf("revanced_sb_skipped_nomusic"),
@@ -69,6 +71,7 @@ public enum SegmentCategory {
INTRO,
OUTRO,
PREVIEW,
HOOK,
FILLER,
MUSIC_OFFTOPIC,
};
@@ -81,6 +84,7 @@ public enum SegmentCategory {
INTRO,
OUTRO,
PREVIEW,
HOOK,
FILLER,
MUSIC_OFFTOPIC,
};

View File

@@ -5,10 +5,11 @@ import android.view.View;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
@SuppressWarnings("unused")
public class CreateSegmentButton {
@Nullable
private static PlayerControlButton instance;
@@ -18,7 +19,7 @@ public class CreateSegmentButton {
}
/**
* injection point
* injection point.
*/
public static void initialize(View controlsView) {
try {
@@ -26,8 +27,7 @@ public class CreateSegmentButton {
controlsView,
"revanced_sb_create_segment_button",
null,
null,
CreateSegmentButton::shouldBeShown,
CreateSegmentButton::isButtonEnabled,
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
null
);
@@ -37,21 +37,28 @@ public class CreateSegmentButton {
}
/**
* Injection point
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* injection point.
*/
public static void setVisibilityImmediate(boolean visible) {
if (instance != null) instance.setVisibilityImmediate(visible);
}
/**
* Injection point
* injection point.
*/
public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) instance.setVisibility(visible, animated);
}
private static boolean shouldBeShown() {
private static boolean isButtonEnabled() {
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get()
&& !VideoInformation.isAtEndOfVideo();
&& !SegmentPlaybackController.isAdProgressTextVisible();
}
}

View File

@@ -16,7 +16,6 @@ import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
import kotlin.Unit;
@@ -227,22 +226,4 @@ public class SponsorBlockViewController {
params.bottomMargin = fullScreen ? ctaBottomMargin : defaultBottomMargin;
view.setLayoutParams(params);
}
/**
* Injection point.
*/
public static void endOfVideoReached() {
try {
Logger.printDebug(() -> "endOfVideoReached");
// the buttons automatically set themselves to visible when appropriate,
// but if buttons are showing when the end of the video is reached then they need
// to be forcefully hidden
if (!Settings.AUTO_REPEAT.get()) {
CreateSegmentButton.hideControls();
VotingButton.hideControls();
}
} catch (Exception ex) {
Logger.printException(() -> "endOfVideoReached failure", ex);
}
}
}

View File

@@ -5,12 +5,12 @@ import android.view.View;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockUtils;
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
@SuppressWarnings("unused")
public class VotingButton {
@Nullable
private static PlayerControlButton instance;
@@ -20,7 +20,7 @@ public class VotingButton {
}
/**
* injection point
* injection point.
*/
public static void initialize(View controlsView) {
try {
@@ -28,8 +28,7 @@ public class VotingButton {
controlsView,
"revanced_sb_voting_button",
null,
null,
VotingButton::shouldBeShown,
VotingButton::isButtonEnabled,
v -> SponsorBlockUtils.onVotingClicked(v.getContext()),
null
);
@@ -39,21 +38,29 @@ public class VotingButton {
}
/**
* Injection point
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* injection point.
*/
public static void setVisibilityImmediate(boolean visible) {
if (instance != null) instance.setVisibilityImmediate(visible);
}
/**
* Injection point
* injection point.
*/
public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) instance.setVisibility(visible, animated);
}
private static boolean shouldBeShown() {
private static boolean isButtonEnabled() {
return Settings.SB_ENABLED.get() && Settings.SB_VOTING_BUTTON.get()
&& SegmentPlaybackController.videoHasSegments() && !VideoInformation.isAtEndOfVideo();
&& SegmentPlaybackController.videoHasSegments()
&& !SegmentPlaybackController.isAdProgressTextVisible();
}
}

View File

@@ -21,7 +21,6 @@ public class CopyVideoUrlButton {
instance = new PlayerControlButton(
controlsView,
"revanced_copy_video_url_button",
"revanced_copy_video_url_button_placeholder",
null,
Settings.COPY_VIDEO_URL::get,
view -> CopyVideoUrlPatch.copyUrl(false),
@@ -35,15 +34,22 @@ public class CopyVideoUrlButton {
}
}
/**`
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* injection point
* injection point.
*/
public static void setVisibilityImmediate(boolean visible) {
if (instance != null) instance.setVisibilityImmediate(visible);
}
/**
* injection point
* injection point.
*/
public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) instance.setVisibility(visible, animated);

View File

@@ -21,7 +21,6 @@ public class CopyVideoUrlTimestampButton {
instance = new PlayerControlButton(
controlsView,
"revanced_copy_video_url_timestamp_button",
"revanced_copy_video_url_timestamp_button_placeholder",
null,
Settings.COPY_VIDEO_URL_TIMESTAMP::get,
view -> CopyVideoUrlPatch.copyUrl(true),
@@ -36,14 +35,21 @@ public class CopyVideoUrlTimestampButton {
}
/**
* injection point
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* injection point.
*/
public static void setVisibilityImmediate(boolean visible) {
if (instance != null) instance.setVisibilityImmediate(visible);
}
/**
* injection point
* injection point.
*/
public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) instance.setVisibility(visible, animated);

View File

@@ -22,7 +22,6 @@ public class ExternalDownloadButton {
instance = new PlayerControlButton(
controlsView,
"revanced_external_download_button",
"revanced_external_download_button_placeholder",
null,
Settings.EXTERNAL_DOWNLOADER::get,
ExternalDownloadButton::onDownloadClick,
@@ -34,14 +33,21 @@ public class ExternalDownloadButton {
}
/**
* injection point
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* injection point.
*/
public static void setVisibilityImmediate(boolean visible) {
if (instance != null) instance.setVisibilityImmediate(visible);
}
/**
* Injection point
* injection point.
*/
public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) instance.setVisibility(visible, animated);

View File

@@ -33,7 +33,6 @@ public class PlaybackSpeedDialogButton {
controlsView,
"revanced_playback_speed_dialog_button_container",
"revanced_playback_speed_dialog_button",
"revanced_playback_speed_dialog_button_placeholder",
"revanced_playback_speed_dialog_button_text",
Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get,
view -> {
@@ -69,6 +68,13 @@ public class PlaybackSpeedDialogButton {
}
}
/**
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* Injection point.
*/

View File

@@ -1,7 +1,7 @@
package app.revanced.extension.youtube.videoplayer;
import android.view.View;
import android.view.animation.Animation;
import android.view.ViewPropertyAnimator;
import android.widget.ImageView;
import android.widget.TextView;
@@ -11,6 +11,7 @@ import java.lang.ref.WeakReference;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.shared.PlayerControlsVisibility;
import app.revanced.extension.youtube.shared.PlayerType;
import kotlin.Unit;
@@ -23,55 +24,29 @@ public class PlayerControlButton {
boolean buttonEnabled();
}
private static final int fadeInDuration;
private static final int fadeOutDuration;
private static final Animation fadeInAnimation;
private static final Animation fadeOutAnimation;
private static final Animation fadeOutImmediate;
static {
fadeInDuration = Utils.getResourceInteger("fade_duration_fast");
fadeOutDuration = Utils.getResourceInteger("fade_duration_scheduled");
fadeInAnimation = Utils.getResourceAnimation("fade_in");
fadeInAnimation.setDuration(fadeInDuration);
fadeOutAnimation = Utils.getResourceAnimation("fade_out");
fadeOutAnimation.setDuration(fadeOutDuration);
// Animation for the fast fade out after tapping the overlay.
// Currently not used but should be.
fadeOutImmediate = Utils.getResourceAnimation("abc_fade_out");
fadeOutImmediate.setDuration(Utils.getResourceInteger("fade_duration_fast"));
}
private static final int fadeInDuration = Utils.getResourceInteger("fade_duration_fast");
private static final int fadeOutDuration = Utils.getResourceInteger("fade_duration_scheduled");
private final WeakReference<View> containerRef;
private final WeakReference<View> buttonRef;
/**
* Empty view with the same layout size as the button. Used to fill empty space while the
* fade out animation runs. Without this the chapter titles overlapping the button when fading out.
*/
private final WeakReference<View> placeHolderRef;
private final WeakReference<TextView> textOverlayRef;
private final PlayerControlButtonStatus enabledStatus;
private boolean isVisible;
private long lastTimeSetVisible;
public PlayerControlButton(View controlsViewGroup,
String buttonId,
@Nullable String placeholderId,
@Nullable String textOverlayId,
PlayerControlButtonStatus enabledStatus,
View.OnClickListener onClickListener,
@Nullable View.OnLongClickListener longClickListener) {
this(controlsViewGroup, buttonId, buttonId, placeholderId, textOverlayId,
this(controlsViewGroup, buttonId, buttonId, textOverlayId,
enabledStatus, onClickListener, longClickListener);
}
public PlayerControlButton(View controlsViewGroup,
String viewToHide,
String buttonId,
@Nullable String placeholderId,
@Nullable String textOverlayId,
PlayerControlButtonStatus enabledStatus,
View.OnClickListener onClickListener,
@@ -87,13 +62,6 @@ public class PlayerControlButton {
}
buttonRef = new WeakReference<>(button);
View tempPlaceholder = null;
if (placeholderId != null) {
tempPlaceholder = Utils.getChildViewByResourceName(controlsViewGroup, placeholderId);
tempPlaceholder.setVisibility(View.GONE);
}
placeHolderRef = new WeakReference<>(tempPlaceholder);
TextView tempTextOverlay = null;
if (textOverlayId != null) {
tempTextOverlay = Utils.getChildViewByResourceName(controlsViewGroup, textOverlayId);
@@ -114,13 +82,55 @@ public class PlayerControlButton {
});
}
public void setVisibilityNegatedImmediate() {
try {
Utils.verifyOnMainThread();
if (PlayerControlsVisibility.getCurrent() != PlayerControlsVisibility.PLAYER_CONTROLS_VISIBILITY_HIDDEN) {
return;
}
final boolean buttonEnabled = enabledStatus.buttonEnabled();
if (!buttonEnabled) {
return;
}
View container = containerRef.get();
if (container == null) {
return;
}
isVisible = false;
ViewPropertyAnimator animate = container.animate();
animate.cancel();
// If the overlay is tapped to display then immediately tapped to dismiss
// before the fade in animation finishes, then the fade out animation is
// the time between when the fade in started and now.
final long animationDuration = Math.min(fadeInDuration,
System.currentTimeMillis() - lastTimeSetVisible);
if (animationDuration <= 0) {
// Should never happen, but handle just in case.
container.setVisibility(View.GONE);
return;
}
animate.alpha(0)
.setDuration(animationDuration)
.withEndAction(() -> container.setVisibility(View.GONE))
.start();
} catch (Exception ex) {
Logger.printException(() -> "setVisibilityNegatedImmediate failure", ex);
}
}
public void setVisibilityImmediate(boolean visible) {
if (visible) {
// Fix button flickering, by pushing this call to the back of
// the main thread and letting other layout code run first.
Utils.runOnMainThread(() -> private_setVisibility(true, false));
Utils.runOnMainThread(() -> privateSetVisibility(true, false));
} else {
private_setVisibility(false, false);
privateSetVisibility(false, false);
}
}
@@ -128,47 +138,53 @@ public class PlayerControlButton {
// Ignore this call, otherwise with full screen thumbnails the buttons are visible while seeking.
if (visible && !animated) return;
private_setVisibility(visible, animated);
privateSetVisibility(visible, animated);
}
private void private_setVisibility(boolean visible, boolean animated) {
private void privateSetVisibility(boolean visible, boolean animated) {
try {
Utils.verifyOnMainThread();
if (isVisible == visible) return;
isVisible = visible;
if (visible) {
lastTimeSetVisible = System.currentTimeMillis();
}
View container = containerRef.get();
if (container == null) return;
if (container == null) {
return;
}
View placeholder = placeHolderRef.get();
final boolean buttonEnabled = enabledStatus.buttonEnabled();
if (visible && buttonEnabled) {
container.clearAnimation();
if (animated) {
container.startAnimation(fadeInAnimation);
}
if (visible && enabledStatus.buttonEnabled()) {
ViewPropertyAnimator animate = container.animate();
animate.cancel();
container.setVisibility(View.VISIBLE);
if (placeholder != null) {
placeholder.setVisibility(View.GONE);
}
} else {
if (container.getVisibility() == View.VISIBLE) {
container.clearAnimation();
if (animated) {
container.startAnimation(fadeOutAnimation);
}
container.setVisibility(View.GONE);
if (animated) {
container.setAlpha(0);
animate.alpha(1)
.setDuration(fadeInDuration)
.start();
} else {
container.setAlpha(1);
}
} else if (container.getVisibility() == View.VISIBLE) {
ViewPropertyAnimator animate = container.animate();
animate.cancel();
if (placeholder != null) {
placeholder.setVisibility(buttonEnabled
? View.VISIBLE
: View.GONE);
if (animated) {
animate.alpha(0)
.setDuration(fadeOutDuration)
.withEndAction(() -> container.setVisibility(View.GONE))
.start();
} else {
container.setVisibility(View.GONE);
}
}
} catch (Exception ex) {
Logger.printException(() -> "private_setVisibility failure", ex);
Logger.printException(() -> "privateSetVisibility failure", ex);
}
}
@@ -176,42 +192,36 @@ public class PlayerControlButton {
* Synchronizes the button state after the player state changes.
*/
private void playerTypeChanged(PlayerType newType) {
Utils.verifyOnMainThread();
if (newType != PlayerType.WATCH_WHILE_MINIMIZED && !newType.isMaximizedOrFullscreen()) {
return;
}
View container = containerRef.get();
if (container == null) return;
if (container == null) {
return;
}
container.clearAnimation();
View placeholder = placeHolderRef.get();
container.animate().cancel();
if (enabledStatus.buttonEnabled()) {
if (isVisible) {
container.setVisibility(View.VISIBLE);
if (placeholder != null) placeholder.setVisibility(View.GONE);
} else {
container.setVisibility(View.GONE);
if (placeholder != null) placeholder.setVisibility(View.VISIBLE);
}
if (isVisible && enabledStatus.buttonEnabled()) {
container.setVisibility(View.VISIBLE);
container.setAlpha(1);
} else {
container.setVisibility(View.GONE);
if (placeholder != null) placeholder.setVisibility(View.GONE);
}
}
public void hide() {
Utils.verifyOnMainThread();
if (!isVisible) return;
if (!isVisible) {
return;
}
isVisible = false;
View view = containerRef.get();
if (view == null) return;
view.setVisibility(View.GONE);
View placeHolder = placeHolderRef.get();
if (placeHolder != null) view.setVisibility(View.GONE);
isVisible = false;
}
/**
@@ -219,6 +229,8 @@ public class PlayerControlButton {
* @param resourceId Drawable identifier, or zero to hide the icon.
*/
public void setIcon(int resourceId) {
Utils.verifyOnMainThread();
View button = buttonRef.get();
if (button instanceof ImageView imageButton) {
imageButton.setImageResource(resourceId);
@@ -230,6 +242,8 @@ public class PlayerControlButton {
* @param text The text to set on the overlay, or null to clear the text.
*/
public void setTextOverlay(CharSequence text) {
Utils.verifyOnMainThread();
TextView textOverlay = textOverlayRef.get();
if (textOverlay != null) {
textOverlay.setText(text);

View File

@@ -69,7 +69,6 @@ public class VideoQualityDialogButton {
controlsView,
"revanced_video_quality_dialog_button_container",
"revanced_video_quality_dialog_button",
"revanced_video_quality_dialog_button_placeholder",
"revanced_video_quality_dialog_button_text",
Settings.VIDEO_QUALITY_DIALOG_BUTTON::get,
view -> {
@@ -116,6 +115,13 @@ public class VideoQualityDialogButton {
}
}
/**
* injection point.
*/
public static void setVisibilityNegatedImmediate() {
if (instance != null) instance.setVisibilityNegatedImmediate();
}
/**
* Injection point.
*/

View File

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

View File

@@ -11,8 +11,8 @@ appcompat = "1.7.0"
okhttp = "5.0.0-alpha.14"
retrofit = "2.11.0"
guava = "33.4.0-jre"
protobuf-javalite = "4.31.1"
protoc = "4.31.1"
protobuf-javalite = "4.32.0"
protoc = "4.32.0"
protobuf = "0.9.5"
antlr4 = "4.13.2"
nanohttpd = "2.3.1"

View File

@@ -264,6 +264,14 @@ public final class app/revanced/patches/instagram/ads/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/hide/navigation/HideNavigationButtonsKt {
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/hide/stories/HideStoriesKt {
public static final fun getHideStoriesPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -384,14 +392,21 @@ public final class app/revanced/patches/music/misc/gms/GmsCoreSupportPatchKt {
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/misc/spoof/SpoofClientPatchKt {
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public final class app/revanced/patches/music/misc/spoof/SpoofVideoStreamsKt {
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/misc/spoof/UserAgentClientSpoofPatchKt {
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/playservice/VersionCheckPatchKt {
public static final fun getVersionCheckPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
public static final fun is_7_33_or_greater ()Z
public static final fun is_8_11_or_greater ()Z
public static final fun is_8_15_or_greater ()Z
}
public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -508,6 +523,13 @@ public final class app/revanced/patches/reddit/ad/general/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/FixRedgifsApiPatchKt {
public static final field CREATE_NEW_CLIENT_METHOD Ljava/lang/String;
public static final field INSTALL_NEW_CLIENT_METHOD Ljava/lang/String;
public static final fun fixRedgifsApiPatch (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun fixRedgifsApiPatch$default (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/FixSLinksPatchKt {
public static final field RESOLVE_S_LINK_METHOD Ljava/lang/String;
public static final field SET_ACCESS_TOKEN_METHOD Ljava/lang/String;
@@ -524,6 +546,14 @@ public final class app/revanced/patches/reddit/customclients/baconreader/api/Spo
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/baconreader/fix/redgifs/FixRedgifsApiPatchKt {
public static final fun getFixRedgifsApi ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/baconreader/misc/extension/SharedExtensionPatchKt {
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/boostforreddit/ads/DisableAdsPatchKt {
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -536,6 +566,10 @@ public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/
public static final fun getFixAudioMissingInDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/redgifs/FixRedgifsApiPatchKt {
public static final fun getFixRedgifsApi ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/FixSLinksPatchKt {
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
public static final fun getFixSlinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
@@ -606,6 +640,10 @@ public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/redgifs/FixRedgifsApiPatchKt {
public static final fun getFixRedgifsApi ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/slink/FixSLinksPatchKt {
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
public static final fun getFixSLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
@@ -952,10 +990,6 @@ public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt {
public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/UnlockPremiumPatchKt {
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/extension/ExtensionPatchKt {
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1208,6 +1242,10 @@ public final class app/revanced/patches/twitter/misc/links/SanitizeSharingLinksP
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/viber/ads/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1536,6 +1574,10 @@ public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHoo
public static final fun setHookNavigationButtonCreated (Lkotlin/jvm/functions/Function1;)V
}
public final class app/revanced/patches/youtube/misc/playercontrols/PlayerControlsOverlayVisibilityPatchKt {
public static final fun getPlayerControlsOverlayVisibilityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatchKt {
public static final fun getAddBottomControl ()Lkotlin/jvm/functions/Function1;
public static final fun getPlayerControlsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;

View File

@@ -19,14 +19,16 @@ val disableAdsPatch = bytecodePatch(
// SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS".
//
// MonetizationDebugSettings seems to be the most general setting to work fine.
initializeMonetizationDebugSettingsFingerprint.method.apply {
val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
initializeMonetizationDebugSettingsFingerprint
.match(monetizationDebugSettingsToStringFingerprint.classDef)
.method.apply {
val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex,
"const/4 v$register, 0x1",
)
}
addInstructions(
insertIndex,
"const/4 v$register, 0x1",
)
}
}
}

View File

@@ -7,13 +7,11 @@ import com.android.tools.smali.dexlib2.Opcode
internal val initializeMonetizationDebugSettingsFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
returns("V")
parameters(
"Z", // disableAds
"Z", // useDebugBilling
"Z", // showManageSubscriptions
"Z", // alwaysShowSuperAds
// matches "Lcom/duolingo/debug/FamilyQuestOverride;" or "Lcom/duolingo/data/debug/monetization/FamilyQuestOverride;"
"Lcom/duolingo/",
)
// Parameters have not been reliable for fingerprinting between versions.
opcodes(Opcode.IPUT_BOOLEAN)
}
internal val monetizationDebugSettingsToStringFingerprint = fingerprint {
strings("MonetizationDebugSettings(") // Partial string match.
custom { method, _ -> method.name == "toString" }
}

View File

@@ -0,0 +1,29 @@
package app.revanced.patches.instagram.hide.navigation
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.Opcode
internal val tabCreateButtonsLoopStartFingerprint = fingerprint {
returns("V")
strings("InstagramMainActivity.createTabButtons")
opcodes(
//Loop Start
Opcode.IF_GE, // Check if index is finished (index, size)
//Injection
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT
)
}
internal val tabCreateButtonsLoopEndFingerprint = fingerprint {
returns("V")
strings("InstagramMainActivity.createTabButtons")
opcodes(
Opcode.IPUT_OBJECT,
// Injection Jump
Opcode.ADD_INT_LIT8, //Increase Index
Opcode.GOTO_16 // Jump to loopStart
// LoopEnd
)
}

View File

@@ -0,0 +1,80 @@
package app.revanced.patches.instagram.hide.navigation
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.booleanOption
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.util.findFreeRegister
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import java.util.logging.Logger
@Suppress("unused")
val hideNavigationButtonsPatch = bytecodePatch(
name = "Hide navigation buttons",
description = "Hides navigation bar buttons, such as the Reels and Create button.",
use = false
) {
compatibleWith("com.instagram.android")
val hideReels by booleanOption(
key = "hideReels",
default = true,
title = "Hide Reels",
description = "Permanently hides the Reels button."
)
val hideCreate by booleanOption(
key = "hideCreate",
default = true,
title = "Hide Create",
description = "Permanently hides the Create button."
)
execute {
if (!hideReels!! && !hideCreate!!) {
return@execute Logger.getLogger(this::class.java.name).warning(
"No hide navigation buttons options are enabled. No changes made."
)
}
tabCreateButtonsLoopStartFingerprint.method.apply {
// Check the current loop index, and skip over adding the
// navigation button view if the index matches a given button.
val startIndex = tabCreateButtonsLoopStartFingerprint.patternMatch!!.startIndex
val endIndex = tabCreateButtonsLoopEndFingerprint.patternMatch!!.endIndex
val insertIndex = startIndex + 1
val loopIndexRegister = getInstruction<TwoRegisterInstruction>(startIndex).registerA
val freeRegister = findFreeRegister(insertIndex, loopIndexRegister)
val instruction = getInstruction(endIndex - 1)
var instructions = buildString {
if (hideCreate!!) {
appendLine(
"""
const v$freeRegister, 0x2
if-eq v$freeRegister, v$loopIndexRegister, :skipAddView
"""
)
}
if (hideReels!!) {
appendLine(
"""
const v$freeRegister, 0x3
if-eq v$freeRegister, v$loopIndexRegister, :skipAddView
"""
)
}
}
addInstructionsWithLabels(
insertIndex,
instructions,
ExternalLabel("skipAddView", instruction)
)
}
}
}

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.instagram.hide.stories
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.Opcode
internal val getOrCreateAvatarViewFingerprint = fingerprint {
parameters()
returns("L")
custom { method, classDef ->
classDef.type == "Lcom/instagram/reels/ui/views/reelavatar/RecyclerReelAvatarView;"
}
opcodes(
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_VIRTUAL // Add View (Story)
)
}

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.instagram.hide.stories
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused")
val hideStoriesPatch = bytecodePatch(
name = "Hide Stories from Home",
description = "Hides Stories from the main page, by removing the buttons.",
use = false
) {
compatibleWith("com.instagram.android")
execute {
val addStoryMethod = getOrCreateAvatarViewFingerprint.method // Creates Story
val addStoryEndIndex = getOrCreateAvatarViewFingerprint.patternMatch!!.endIndex
// Remove addView of Story.
addStoryMethod.removeInstruction(addStoryEndIndex)
}
}

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,11 @@ val permanentShufflePatch = bytecodePatch(
description = "Permanently remember your shuffle preference " +
"even if the playlist ends or another track is played."
) {
compatibleWith("com.google.android.apps.youtube.music")
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
)
)
execute {
disableShuffleFingerprint.method.addInstruction(0, "return-void")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ import app.revanced.patcher.patch.Option
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.spoof.spoofClientPatch
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch
import app.revanced.patches.shared.castContextFetchFingerprint
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
import app.revanced.patches.shared.primeMethodFingerprint
@@ -21,7 +21,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
extensionPatch = sharedExtensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) {
dependsOn(spoofClientPatch)
dependsOn(spoofVideoStreamsPatch)
compatibleWith(MUSIC_PACKAGE_NAME)
}

View File

@@ -1,39 +0,0 @@
package app.revanced.patches.music.misc.spoof
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val playerRequestConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
strings("player")
}
/**
* Matches using the class found in [playerRequestConstructorFingerprint].
*/
internal val createPlayerRequestBodyFingerprint = fingerprint {
parameters("L")
returns("V")
opcodes(
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.AND_INT_LIT16,
)
strings("ms")
}
/**
* Used to get a reference to other clientInfo fields.
*/
internal val setClientInfoFieldsFingerprint = fingerprint {
returns("L")
strings("Google Inc.")
}
/**
* Used to get a reference to the clientInfo and clientInfo.clientVersion field.
*/
internal val setClientInfoClientVersionFingerprint = fingerprint {
strings("10.29")
}

View File

@@ -1,105 +0,0 @@
package app.revanced.patches.music.misc.spoof
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/music/spoof/SpoofClientPatch;"
// TODO: Replace this patch with spoofVideoStreamsPatch once possible.
val spoofClientPatch = bytecodePatch(
name = "Spoof client",
description = "Spoofs the client to fix playback.",
) {
compatibleWith("com.google.android.apps.youtube.music")
dependsOn(
sharedExtensionPatch,
// TODO: Add settingsPatch
userAgentClientSpoofPatch,
)
execute {
val playerRequestClass = playerRequestConstructorFingerprint.classDef
val createPlayerRequestBodyMatch = createPlayerRequestBodyFingerprint.match(playerRequestClass)
val clientInfoContainerClass = createPlayerRequestBodyMatch.method
.getInstruction(createPlayerRequestBodyMatch.patternMatch!!.startIndex)
.getReference<TypeReference>()!!.type
val clientInfoField = setClientInfoClientVersionFingerprint.method.instructions.first {
it.opcode == Opcode.IPUT_OBJECT && it.getReference<FieldReference>()!!.definingClass == clientInfoContainerClass
}.getReference<FieldReference>()!!
val setClientInfoFieldInstructions = setClientInfoFieldsFingerprint.method.instructions.filter {
(it.opcode == Opcode.IPUT_OBJECT || it.opcode == Opcode.IPUT) &&
it.getReference<FieldReference>()!!.definingClass == clientInfoField.type
}.map { it.getReference<FieldReference>()!! }
// Offsets are known for the fields in the clientInfo object.
val clientIdField = setClientInfoFieldInstructions[0]
val clientModelField = setClientInfoFieldInstructions[5]
val osVersionField = setClientInfoFieldInstructions[7]
val clientVersionField = setClientInfoClientVersionFingerprint.method
.getInstruction(setClientInfoClientVersionFingerprint.stringMatches!!.first().index + 1)
.getReference<FieldReference>()
// Helper method to spoof the client info.
val spoofClientInfoMethod = ImmutableMethod(
playerRequestClass.type,
"spoofClientInfo",
listOf(ImmutableMethodParameter(clientInfoContainerClass, null, null)),
"V",
AccessFlags.PRIVATE.value or AccessFlags.STATIC.value,
null,
null,
MutableMethodImplementation(3),
).toMutable().also(playerRequestClass.methods::add).apply {
addInstructions(
"""
iget-object v0, p0, $clientInfoField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientId()I
move-result v1
iput v1, v0, $clientIdField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientModel()Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientModelField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientVersion()Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientVersionField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getOsVersion()Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $osVersionField
return-void
""",
)
}
createPlayerRequestBodyMatch.method.apply {
val checkCastIndex = createPlayerRequestBodyMatch.patternMatch!!.startIndex
val clientInfoContainerRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
addInstruction(checkCastIndex + 1, "invoke-static {v$clientInfoContainerRegister}, $spoofClientInfoMethod")
}
}
}

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.music.misc.spoof
import app.revanced.patches.music.playservice.is_7_33_or_greater
import app.revanced.patches.music.playservice.is_8_11_or_greater
import app.revanced.patches.music.playservice.is_8_15_or_greater
import app.revanced.patches.music.playservice.versionCheckPatch
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
block = {
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
)
)
dependsOn(versionCheckPatch, userAgentClientSpoofPatch)
},
fixMediaFetchHotConfigChanges = { true },
fixMediaFetchHotConfigAlternativeChanges = { is_8_11_or_greater && !is_8_15_or_greater },
fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater }
)

View File

@@ -0,0 +1,28 @@
@file:Suppress("ktlint:standard:property-naming")
package app.revanced.patches.music.playservice
import app.revanced.patcher.patch.resourcePatch
import app.revanced.util.findPlayStoreServicesVersion
var is_7_33_or_greater = false
private set
var is_8_11_or_greater = false
private set
var is_8_15_or_greater = false
private set
val versionCheckPatch = resourcePatch(
description = "Uses the Play Store service version to find the major/minor version of the YouTube Music target app.",
) {
execute {
// The app version is missing from the decompiled manifest,
// so instead use the Google Play services version and compare against specific releases.
val playStoreServicesVersion = findPlayStoreServicesVersion()
// All bug fix releases always seem to use the same play store version as the minor version.
is_7_33_or_greater = 245199000 <= playStoreServicesVersion
is_8_11_or_greater = 251199000 <= playStoreServicesVersion
is_8_15_or_greater = 251530000 <= playStoreServicesVersion
}
}

View File

@@ -8,7 +8,7 @@ val removeFreeAccountsLimitPatch = resourcePatch(
name = "Remove free accounts limit",
description = "Removes the limit for maximum free accounts logged in.",
) {
compatibleWith("ch.protonmail.android")
compatibleWith("ch.protonmail.android"("4.15.0"))
execute {
document("res/values/integers.xml").use { document ->

View File

@@ -10,7 +10,7 @@ val removeSentFromSignaturePatch = resourcePatch(
name = "Remove 'Sent from' signature",
description = "Removes the 'Sent from Proton Mail mobile' signature from emails.",
) {
compatibleWith("ch.protonmail.android")
compatibleWith("ch.protonmail.android"("4.15.0"))
execute {
val stringResourceFiles = mutableListOf<File>()

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.reddit.customclients
import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.bytecodePatch
const val INSTALL_NEW_CLIENT_METHOD = "install(Lokhttp3/OkHttpClient${'$'}Builder;)Lokhttp3/OkHttpClient;"
const val CREATE_NEW_CLIENT_METHOD = "createClient()Lokhttp3/OkHttpClient;"
fun fixRedgifsApiPatch(
extensionPatch: Patch<*>,
block: BytecodePatchBuilder.() -> Unit = {},
) = bytecodePatch(name = "Fix Redgifs API") {
dependsOn(extensionPatch)
block()
}

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.reddit.customclients.baconreader.fix.redgifs
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal val getOkHttpClientFingerprint = fingerprint {
returns("Lokhttp3/OkHttpClient;")
parameters()
custom { method, classDef ->
classDef.type == "Lcom/onelouder/baconreader/media/gfycat/RedGifsManager;" && method.name == "getOkhttpClient"
}
}

View File

@@ -0,0 +1,53 @@
package app.revanced.patches.reddit.customclients.baconreader.fix.redgifs
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.reddit.customclients.INSTALL_NEW_CLIENT_METHOD
import app.revanced.patches.reddit.customclients.baconreader.misc.extension.sharedExtensionPatch
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
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.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/baconreader/FixRedgifsApiPatch;"
@Suppress("unused")
val fixRedgifsApi = fixRedgifsApiPatch(
extensionPatch = sharedExtensionPatch
) {
compatibleWith(
"com.onelouder.baconreader",
"com.onelouder.baconreader.premium",
)
execute {
// region Patch Redgifs OkHttp3 client.
getOkHttpClientFingerprint.method.apply {
// Remove conflicting OkHttp interceptors.
val originalInterceptorInstallIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.NEW_INSTANCE && getReference<TypeReference>()?.type == "Lcom/onelouder/baconreader/media/gfycat/RedGifsManager\$HeaderInterceptor;"
}
removeInstructions(originalInterceptorInstallIndex, 5)
val index = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
}
val register = getInstruction<FiveRegisterInstruction>(index).registerC
replaceInstruction(
index,
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$INSTALL_NEW_CLIENT_METHOD
"""
)
}
// endregion
}
}

View File

@@ -0,0 +1,6 @@
package app.revanced.patches.reddit.customclients.baconreader.misc.extension
import app.revanced.patches.reddit.customclients.baconreader.misc.extension.hooks.initHook
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
val sharedExtensionPatch = sharedExtensionPatch("baconreader", initHook)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.reddit.customclients.baconreader.misc.extension.hooks
import app.revanced.patches.shared.misc.extension.extensionHook
internal val initHook = extensionHook {
custom { method, _ ->
method.definingClass == "Lcom/onelouder/baconreader/BaconReader;" && method.name == "onCreate"
}
}

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.reddit.customclients.boostforreddit.fix.redgifs
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val createOkHttpClientFingerprint = fingerprint {
accessFlags(AccessFlags.PRIVATE)
opcodes(
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
)
custom { _, classDef -> classDef.sourceFile == "RedGifsAPIv2.java" }
}

View File

@@ -0,0 +1,38 @@
package app.revanced.patches.reddit.customclients.boostforreddit.fix.redgifs
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.reddit.customclients.CREATE_NEW_CLIENT_METHOD
import app.revanced.patches.reddit.customclients.boostforreddit.misc.extension.sharedExtensionPatch
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/boostforreddit/FixRedgifsApiPatch;"
@Suppress("unused")
val fixRedgifsApi = fixRedgifsApiPatch(
extensionPatch = sharedExtensionPatch
) {
compatibleWith("com.rubenmayayo.reddit")
execute {
// region Patch Redgifs OkHttp3 client.
createOkHttpClientFingerprint.method.apply {
val index = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
}
replaceInstruction(
index,
"""
invoke-static { }, ${EXTENSION_CLASS_DESCRIPTOR}->$CREATE_NEW_CLIENT_METHOD
"""
)
}
// endregion
}
}

View File

@@ -0,0 +1,39 @@
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.redgifs
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.fingerprint
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.writeRegister
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11n
internal val createOkHttpClientFingerprint = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
returns("V")
parameters()
custom { method, classDef ->
// There are four functions (each creating a client) defined in this file with very similar fingerprints.
// We're looking for the one that only creates one object (the builder) and sets client options true
// (thus never reloading the register with a 0).
classDef.sourceFile == "OkHttpHelper.java" &&
method.instructions.count { it.opcode == Opcode.NEW_INSTANCE } == 1 &&
method.indexOfFirstInstruction {
opcode == Opcode.CONST_4 && writeRegister == 1 && (this as Instruction11n).narrowLiteral == 0
} == -1
}
}
internal val getDefaultUserAgentFingerprint = fingerprint {
custom { method, classDef ->
method.name == "getDefaultUserAgent" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
}
}
internal val getOriginalUserAgentFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Ljava/lang/String;")
parameters()
custom { _, classDef -> classDef.sourceFile == "AccountSingleton.java" }
}

View File

@@ -0,0 +1,56 @@
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.redgifs
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.reddit.customclients.INSTALL_NEW_CLIENT_METHOD
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
import app.revanced.patches.reddit.customclients.sync.syncforreddit.extension.sharedExtensionPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/syncforreddit/FixRedgifsApiPatch;"
@Suppress("unused")
val fixRedgifsApi = fixRedgifsApiPatch(
extensionPatch = sharedExtensionPatch
) {
compatibleWith(
"com.laurencedawson.reddit_sync",
"com.laurencedawson.reddit_sync.pro",
"com.laurencedawson.reddit_sync.dev",
)
execute {
// region Patch Redgifs OkHttp3 client.
createOkHttpClientFingerprint.method.apply {
val index = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
}
val register = getInstruction<FiveRegisterInstruction>(index).registerC
replaceInstruction(
index,
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$INSTALL_NEW_CLIENT_METHOD
"""
)
}
getDefaultUserAgentFingerprint.method.apply {
addInstructions(
0,
"""
invoke-static { }, ${getOriginalUserAgentFingerprint.method}
move-result-object v0
return-object v0
"""
)
}
// endregion
}
}

View File

@@ -1,9 +1,12 @@
package app.revanced.patches.shared.misc.spoof
import app.revanced.patcher.fingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val buildInitPlaybackRequestFingerprint = fingerprint {
returns("Lorg/chromium/net/UrlRequest\$Builder;")
@@ -35,8 +38,15 @@ internal val buildPlayerRequestURIFingerprint = fingerprint {
internal val buildRequestFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Lorg/chromium/net/UrlRequest;")
returns("Lorg/chromium/net/UrlRequest") // UrlRequest; or UrlRequest$Builder;
custom { methodDef, _ ->
if (methodDef.indexOfFirstInstruction {
val reference = getReference<MethodReference>()
reference?.name == "newUrlRequestBuilder"
} < 0) {
return@custom false
}
// Different targets have slightly different parameters
// Earlier targets have parameters:
@@ -58,12 +68,22 @@ internal val buildRequestFingerprint = fingerprint {
// Lorg/chromium/net/UrlRequest\$Callback;
// L
// 20.16+ uses a refactored and extracted method:
// L
// Ljava/util/Map;
// [B
// L
// Lorg/chromium/net/UrlRequest$Callback;
// L
val parameterTypes = methodDef.parameterTypes
(parameterTypes.size == 7 || parameterTypes.size == 8) &&
parameterTypes[1] == "Ljava/util/Map;" // URL headers.
val parameterTypesSize = parameterTypes.size
(parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) &&
parameterTypes[1] == "Ljava/util/Map;" // URL headers.
}
}
internal val protobufClassParseByteBufferFingerprint = fingerprint {
accessFlags(AccessFlags.PROTECTED, AccessFlags.STATIC)
returns("L")
@@ -148,7 +168,8 @@ internal val mediaFetchHotConfigFingerprint = fingerprint {
literal { MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG }
}
// 20.10+
// YT 20.10+, YT Music 8.11 - 8.14.
// Flag is missing in YT Music 8.15+, and it is not known if a replacement flag/feature exists.
internal const val MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG = 45683169L
internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint {
@@ -162,7 +183,6 @@ internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint {
internal const val PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG = 45665455L
internal val playbackStartDescriptorFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters()
returns("Z")
literal { PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG }

View File

@@ -10,6 +10,7 @@ import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.util.findFreeRegister
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
@@ -42,7 +43,7 @@ fun spoofVideoStreamsPatch(
) {
block()
dependsOn(addResourcesPatch)
dependsOn(sharedExtensionPatch, addResourcesPatch)
execute {
// region Enable extension helper method used by other patches
@@ -53,9 +54,8 @@ fun spoofVideoStreamsPatch(
// region Block /initplayback requests to fall back to /get_watch requests.
val moveUriStringIndex = buildInitPlaybackRequestFingerprint.patternMatch!!.startIndex
buildInitPlaybackRequestFingerprint.method.apply {
val moveUriStringIndex = buildInitPlaybackRequestFingerprint.patternMatch!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
addInstructions(
@@ -63,7 +63,7 @@ fun spoofVideoStreamsPatch(
"""
invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
""",
"""
)
}
@@ -71,9 +71,8 @@ fun spoofVideoStreamsPatch(
// region Block /get_watch requests to fall back to /player requests.
val invokeToStringIndex = buildPlayerRequestURIFingerprint.patternMatch!!.startIndex
buildPlayerRequestURIFingerprint.method.apply {
val invokeToStringIndex = buildPlayerRequestURIFingerprint.patternMatch!!.startIndex
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
addInstructions(
@@ -81,7 +80,7 @@ fun spoofVideoStreamsPatch(
"""
invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
move-result-object v$uriRegister
""",
"""
)
}
@@ -178,9 +177,9 @@ fun spoofVideoStreamsPatch(
:disabled
return-void
""",
"""
)
},
}
)
}
@@ -199,17 +198,17 @@ fun spoofVideoStreamsPatch(
addInstructions(
targetIndex,
"""
# Field a: Stream uri.
# Field c: Http method.
# Field d: Post data.
move-object v0, p0 # method has over 15 registers and must copy p0 to a lower register.
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
iget v2, v0, $definingClass->c:I
iget-object v3, v0, $definingClass->d:[B
invoke-static { v1, v2, v3 }, $EXTENSION_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
move-result-object v1
iput-object v1, v0, $definingClass->d:[B
""",
# Field a: Stream uri.
# Field c: Http method.
# Field d: Post data.
move-object v0, p0 # method has over 15 registers and must copy p0 to a lower register.
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
iget v2, v0, $definingClass->c:I
iget-object v3, v0, $definingClass->d:[B
invoke-static { v1, v2, v3 }, $EXTENSION_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
move-result-object v1
iput-object v1, v0, $definingClass->d:[B
"""
)
}

View File

@@ -1,145 +0,0 @@
package app.revanced.patches.spotify.misc
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
context(BytecodePatchContext)
internal val accountAttributeFingerprint get() = fingerprint {
custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/AccountAttribute;" }
}
context(BytecodePatchContext)
internal val productStateProtoGetMapFingerprint get() = fingerprint {
returns("Ljava/util/Map;")
custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/ProductStateProto;" }
}
internal val buildQueryParametersFingerprint = fingerprint {
strings("trackRows", "device_type:tablet")
}
internal val contextMenuViewModelClassFingerprint = fingerprint {
strings("ContextMenuViewModel(header=")
}
/**
* Used in versions older than "9.0.60.128".
*/
internal val oldContextMenuViewModelAddItemFingerprint = fingerprint {
parameters("L")
returns("V")
custom { method, _ ->
method.indexOfFirstInstruction {
getReference<MethodReference>()?.name == "add"
} >= 0
}
}
internal val contextMenuViewModelConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
}
/**
* Used to find the interface name of a context menu item.
*/
internal val removeAdsContextMenuItemClassFingerprint = fingerprint {
strings("remove_ads_item", "ui_navigate")
}
internal const val CONTEXT_MENU_ITEM_CLASS_DESCRIPTOR_PLACEHOLDER = "Lapp/revanced/ContextMenuItemPlaceholder;"
internal val extensionFilterContextMenuItemsFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Ljava/util/List;")
parameters("Ljava/util/List;")
custom { method, classDef ->
method.name == "filterContextMenuItems" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
}
}
internal val getViewModelFingerprint = fingerprint {
custom { method, _ -> method.name == "getViewModel" }
}
internal val contextFromJsonFingerprint = fingerprint {
opcodes(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC
)
custom { method, classDef ->
method.name == "fromJson" &&
classDef.type.endsWith("voiceassistants/playermodels/ContextJsonAdapter;")
}
}
internal val readPlayerOptionOverridesFingerprint = fingerprint {
custom { method, classDef ->
method.name == "readPlayerOptionOverrides" &&
classDef.type.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;")
}
}
internal val protobufListsFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
custom { method, _ -> method.name == "emptyProtobufList" }
}
internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters()
returns("V")
custom { method, _ ->
method.indexOfFirstInstruction {
getReference<TypeReference>()?.type == "Ljava/lang/UnsupportedOperationException;"
} >= 0
}
}
internal fun structureGetSectionsFingerprint(className: String) = fingerprint {
custom { method, classDef ->
classDef.type.endsWith(className) && method.indexOfFirstInstruction {
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.name == "sections_"
} >= 0
}
}
internal val homeSectionFingerprint = fingerprint {
custom { _, classDef -> classDef.type.endsWith("homeapi/proto/Section;") }
}
internal val homeStructureGetSectionsFingerprint =
structureGetSectionsFingerprint("homeapi/proto/HomeStructure;")
internal val browseSectionFingerprint = fingerprint {
custom { _, classDef-> classDef.type.endsWith("browsita/v1/resolved/Section;") }
}
internal val browseStructureGetSectionsFingerprint =
structureGetSectionsFingerprint("browsita/v1/resolved/BrowseStructure;")
internal fun reactivexFunctionApplyWithClassInitFingerprint(className: String) = fingerprint {
returns("Ljava/lang/Object;")
parameters("Ljava/lang/Object;")
custom { method, _ ->
method.name == "apply" && method.indexOfFirstInstruction {
opcode == Opcode.NEW_INSTANCE && getReference<TypeReference>()?.type?.endsWith(className) == true
} >= 0
}
}
internal const val PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME = "FetchMessageRequest;"
internal val pendragonJsonFetchMessageRequestFingerprint =
reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME)
internal const val PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME = "FetchMessageListRequest;"
internal val pendragonProtoFetchMessageListRequestFingerprint =
reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME)

View File

@@ -1,12 +1,9 @@
package app.revanced.patches.spotify.navbar
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.spotify.misc.unlockPremiumPatch
@Deprecated("Superseded by unlockPremiumPatch", ReplaceWith("unlockPremiumPatch"))
@Deprecated("Obsolete and will be deleted soon")
@Suppress("unused")
val premiumNavbarTabPatch = bytecodePatch(
description = "Hides the premium tab from the navigation bar.",
) {
dependsOn(unlockPremiumPatch)
}
)

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.viber.ads
import app.revanced.patcher.fingerprint
internal val adsFreeFingerprint = fingerprint {
returns("I")
parameters()
custom { method, classDef ->
classDef.type.contains("com/viber/voip/feature/viberplus") &&
classDef.superclass?.contains("com/viber/voip/core/feature") == true && // Must extend com.viber.voip.core.feature.?
classDef.methods.count() == 1
}
}

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.viber.ads
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.returnEarly
@Suppress("unused")
val hideAdsPatch = bytecodePatch(
name = "Hide Ads",
description = "Hides ad banners between chats.",
) {
compatibleWith("com.viber.voip")
execute {
// Return 1 (true) indicating ads should be disabled.
adsFreeFingerprint.method.returnEarly(1)
}
}

View File

@@ -42,7 +42,9 @@ val hideButtonsPatch = resourcePatch(
SwitchPreference("revanced_hide_ask_button"),
SwitchPreference("revanced_hide_clip_button"),
SwitchPreference("revanced_hide_download_button"),
SwitchPreference("revanced_hide_hype_button"),
SwitchPreference("revanced_hide_like_dislike_button"),
SwitchPreference("revanced_hide_promote_button"),
SwitchPreference("revanced_hide_remix_button"),
SwitchPreference("revanced_hide_report_button"),
SwitchPreference("revanced_hide_save_button"),

View File

@@ -1,8 +1,11 @@
package app.revanced.patches.youtube.layout.sponsorblock
import app.revanced.patcher.fingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionReversed
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -56,3 +59,20 @@ internal val rectangleFieldInvalidatorFingerprint = fingerprint {
reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method
}
}
internal val adProgressTextViewVisibilityFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
parameters("Z")
custom { method, _ ->
indexOfAdProgressTextViewVisibilityInstruction(method) >= 0
}
}
internal fun indexOfAdProgressTextViewVisibilityInstruction(method: Method) =
method.indexOfFirstInstructionReversed {
val reference = getReference<MethodReference>()
reference?.definingClass ==
"Lcom/google/android/libraries/youtube/ads/player/ui/AdProgressTextView;"
&& reference.name =="setVisibility"
}

View File

@@ -202,7 +202,7 @@ val sponsorBlockPatch = bytecodePatch(
"""
invoke-static { v$register }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$register
""",
"""
)
}
@@ -253,14 +253,15 @@ val sponsorBlockPatch = bytecodePatch(
} ?: throw PatchException("Could not find the method which contains the replaceMeWith* strings")
}
// The vote and create segment buttons automatically change their visibility when appropriate,
// but if buttons are showing when the end of the video is reached then they will not automatically hide.
// Add a hook to forcefully hide when the end of the video is reached.
autoRepeatFingerprint.match(autoRepeatParentFingerprint.originalClassDef).method.addInstruction(
0,
"invoke-static {}, $EXTENSION_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->endOfVideoReached()V",
)
adProgressTextViewVisibilityFingerprint.method.apply {
val index = indexOfAdProgressTextViewVisibilityInstruction(this)
val register = getInstruction<FiveRegisterInstruction>(index).registerD
addInstructionsAtControlFlowLabel(
index,
"invoke-static { v$register }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setAdProgressTextVisibility(I)V"
)
}
// TODO: Channel whitelisting.
}
}

View File

@@ -2,14 +2,63 @@ package app.revanced.patches.youtube.misc.playercontrols
import app.revanced.patcher.fingerprint
import app.revanced.util.containsLiteralInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionReversed
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal fun indexOfFocusableInTouchModeInstruction(method: Method) =
method.indexOfFirstInstruction {
getReference<MethodReference>()?.name == "setFocusableInTouchMode"
}
internal fun indexOfTranslationInstruction(method: Method) =
method.indexOfFirstInstructionReversed {
getReference<MethodReference>()?.name == "setTranslationY"
}
internal val playerControlsVisibilityEntityModelFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC)
returns("L")
parameters()
opcodes(
Opcode.IGET,
Opcode.INVOKE_STATIC
)
custom { method, _ ->
method.name == "getPlayerControlsVisibility"
}
}
internal val youtubeControlsOverlayFingerprint = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
returns("V")
parameters()
custom { method, _ ->
indexOfFocusableInTouchModeInstruction(method) >= 0 &&
method.containsLiteralInstruction(inset_overlay_view_layout_id) &&
method.containsLiteralInstruction(scrim_overlay_id)
}
}
internal val motionEventFingerprint = fingerprint {
returns("V")
parameters("Landroid/view/MotionEvent;")
custom { method, _ ->
indexOfTranslationInstruction(method) >= 0
}
}
internal val playerTopControlsInflateFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
parameters()
literal { controlsLayoutStub }
literal { controls_layout_stub_id }
}
internal val playerControlsExtensionHookListenersExistFingerprint = fingerprint {
@@ -35,7 +84,7 @@ internal val playerControlsExtensionHookFingerprint = fingerprint {
internal val playerBottomControlsInflateFingerprint = fingerprint {
returns("Ljava/lang/Object;")
parameters()
literal { bottomUiContainerResourceId }
literal { bottom_ui_container_stub_id }
}
internal val overlayViewInflateFingerprint = fingerprint {
@@ -43,8 +92,8 @@ internal val overlayViewInflateFingerprint = fingerprint {
returns("V")
parameters("Landroid/view/View;")
custom { methodDef, _ ->
methodDef.containsLiteralInstruction(fullscreenButton) &&
methodDef.containsLiteralInstruction(heatseekerViewstub)
methodDef.containsLiteralInstruction(fullscreen_button_id) &&
methodDef.containsLiteralInstruction(heatseeker_viewstub_id)
}
}

View File

@@ -0,0 +1,42 @@
package app.revanced.patches.youtube.misc.playercontrols
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
private const val EXTENSION_PLAYER_CONTROLS_VISIBILITY_HOOK_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/PlayerControlsVisibilityHookPatch;"
val PlayerControlsOverlayVisibilityPatch = bytecodePatch {
dependsOn(sharedExtensionPatch)
execute {
playerControlsVisibilityEntityModelFingerprint.let {
it.method.apply {
val startIndex = it.patternMatch!!.startIndex
val iGetReference = getInstruction<ReferenceInstruction>(startIndex).reference
val staticReference = getInstruction<ReferenceInstruction>(startIndex + 1).reference
it.classDef.methods.find { method -> method.name == "<init>" }?.apply {
val targetIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT)
val targetRegister = getInstruction<TwoRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1,
"""
iget v$targetRegister, v$targetRegister, $iGetReference
invoke-static { v$targetRegister }, $staticReference
move-result-object v$targetRegister
invoke-static { v$targetRegister }, $EXTENSION_PLAYER_CONTROLS_VISIBILITY_HOOK_CLASS_DESCRIPTOR->setPlayerControlsVisibility(Ljava/lang/Enum;)V
"""
)
}
}
}
}
}

View File

@@ -1,7 +1,6 @@
package app.revanced.patches.youtube.misc.playercontrols
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
@@ -40,13 +39,17 @@ internal lateinit var addTopControl: (String) -> Unit
lateinit var addBottomControl: (String) -> Unit
private set
internal var bottomUiContainerResourceId = -1L
internal var bottom_ui_container_stub_id = -1L
private set
internal var controlsLayoutStub = -1L
internal var controls_layout_stub_id = -1L
private set
internal var heatseekerViewstub = -1L
internal var heatseeker_viewstub_id = -1L
private set
internal var fullscreenButton = -1L
internal var fullscreen_button_id = -1L
private set
internal var inset_overlay_view_layout_id = -1L
private set
internal var scrim_overlay_id = -1L
private set
val playerControlsResourcePatch = resourcePatch {
@@ -65,10 +68,12 @@ val playerControlsResourcePatch = resourcePatch {
execute {
val targetResourceName = "youtube_controls_bottom_ui_container.xml"
bottomUiContainerResourceId = resourceMappings["id", "bottom_ui_container_stub"]
controlsLayoutStub = resourceMappings["id", "controls_layout_stub"]
heatseekerViewstub = resourceMappings["id", "heatseeker_viewstub"]
fullscreenButton = resourceMappings["id", "fullscreen_button"]
bottom_ui_container_stub_id = resourceMappings["id", "bottom_ui_container_stub"]
controls_layout_stub_id = resourceMappings["id", "controls_layout_stub"]
heatseeker_viewstub_id = resourceMappings["id", "heatseeker_viewstub"]
fullscreen_button_id = resourceMappings["id", "fullscreen_button"]
inset_overlay_view_layout_id = resourceMappings["id", "inset_overlay_view_layout"]
scrim_overlay_id = resourceMappings["id", "scrim_overlay"]
bottomTargetDocument = document("res/layout/$targetResourceName")
@@ -198,6 +203,13 @@ fun injectVisibilityCheckCall(descriptor: String) {
visibilityImmediateInsertIndex++,
"invoke-static { p0 }, $descriptor->setVisibilityImmediate(Z)V",
)
// Patch works without this hook, but it is needed to use the correct fade out animation
// duration when tapping the overlay to dismiss.
visibilityNegatedImmediateMethod.addInstruction(
visibilityNegatedImmediateInsertIndex++,
"invoke-static { }, $descriptor->setVisibilityNegatedImmediate()V",
)
}
internal const val EXTENSION_CLASS_DESCRIPTOR =
@@ -220,12 +232,16 @@ private lateinit var visibilityImmediateCallbacksExistMethod : MutableMethod
private lateinit var visibilityImmediateMethod: MutableMethod
private var visibilityImmediateInsertIndex: Int = 0
private lateinit var visibilityNegatedImmediateMethod: MutableMethod
private var visibilityNegatedImmediateInsertIndex: Int = 0
val playerControlsPatch = bytecodePatch(
description = "Manages the code for the player controls of the YouTube player.",
) {
dependsOn(
playerControlsResourcePatch,
sharedExtensionPatch,
PlayerControlsOverlayVisibilityPatch
)
execute {
@@ -258,7 +274,7 @@ val playerControlsPatch = bytecodePatch(
// Hook the fullscreen close button. Used to fix visibility
// when seeking and other situations.
overlayViewInflateFingerprint.method.apply {
val resourceIndex = indexOfFirstLiteralInstructionReversedOrThrow(fullscreenButton)
val resourceIndex = indexOfFirstLiteralInstructionReversedOrThrow(fullscreen_button_id)
val index = indexOfFirstInstructionOrThrow(resourceIndex) {
opcode == Opcode.CHECK_CAST &&
@@ -277,6 +293,11 @@ val playerControlsPatch = bytecodePatch(
visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistFingerprint.method
visibilityImmediateMethod = playerControlsExtensionHookFingerprint.method
motionEventFingerprint.match(youtubeControlsOverlayFingerprint.originalClassDef).method.apply {
visibilityNegatedImmediateMethod = this
visibilityNegatedImmediateInsertIndex = indexOfTranslationInstruction(this) + 1
}
// A/B test for a slightly different bottom overlay controls,
// that uses layout file youtube_video_exploder_controls_bottom_ui_container.xml
// The change to support this is simple and only requires adding buttons to both layout files,
@@ -299,12 +320,9 @@ val playerControlsPatch = bytecodePatch(
val index = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_OBJECT)
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
addInstruction(
index + 1,
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerTopControlsLayoutResourceName(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$register
""",
"const-string v$register, \"default\""
)
}
}

View File

@@ -3,7 +3,7 @@
package app.revanced.patches.youtube.misc.playservice
import app.revanced.patcher.patch.resourcePatch
import app.revanced.util.findElementByAttributeValueOrThrow
import app.revanced.util.findPlayStoreServicesVersion
@Deprecated("19.34.42 is the lowest supported version")
var is_19_03_or_greater = false
@@ -77,12 +77,7 @@ val versionCheckPatch = resourcePatch(
execute {
// The app version is missing from the decompiled manifest,
// so instead use the Google Play services version and compare against specific releases.
val playStoreServicesVersion = document("res/values/integers.xml").use { document ->
document.documentElement.childNodes.findElementByAttributeValueOrThrow(
"name",
"google_play_services_version",
).textContent.toInt()
}
val playStoreServicesVersion = findPlayStoreServicesVersion()
// All bug fix releases always seem to use the same play store version as the minor version.
is_19_03_or_greater = 240402000 <= playStoreServicesVersion

View File

@@ -1,15 +1,16 @@
package app.revanced.patches.youtube.video.hdr
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR =
@@ -24,6 +25,31 @@ val disableHdrPatch = bytecodePatch(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
// Override all calls of `getSupportedHdrTypes`.
transformInstructionsPatch(
filterMap = filterMap@{ classDef, _, instruction, instructionIndex ->
if (classDef.type.startsWith("Lapp/revanced/")) {
return@filterMap null
}
val reference = instruction.getReference<MethodReference>()
if (reference?.definingClass =="Landroid/view/Display\$HdrCapabilities;"
&& reference.name == "getSupportedHdrTypes") {
return@filterMap instruction to instructionIndex
}
return@filterMap null
},
transform = { method, entry ->
val (instruction, index) = entry
val register = (instruction as FiveRegisterInstruction).registerC
method.replaceInstruction(
index,
"invoke-static/range { v$register .. v$register }, $EXTENSION_CLASS_DESCRIPTOR->" +
"disableHdrVideo(Landroid/view/Display\$HdrCapabilities;)[I",
)
}
)
)
compatibleWith(
@@ -43,29 +69,5 @@ val disableHdrPatch = bytecodePatch(
PreferenceScreen.VIDEO.addPreferences(
SwitchPreference("revanced_disable_hdr_video")
)
hdrCapabilityFingerprint.let {
it.originalMethod.apply {
val stringIndex = it.stringMatches!!.first().index
val navigateIndex = indexOfFirstInstructionOrThrow(stringIndex) {
val reference = getReference<MethodReference>()
reference?.parameterTypes == listOf("I", "Landroid/view/Display;") &&
reference.returnType == "Z"
}
// Modify the HDR lookup method (Method is in the same class as the fingerprint).
navigate(this).to(navigateIndex).stop().addInstructionsWithLabels(
0,
"""
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableHDRVideo()Z
move-result v0
if-nez v0, :useHdr
return v0
:useHdr
nop
"""
)
}
}
}
}

View File

@@ -1,12 +0,0 @@
package app.revanced.patches.youtube.video.hdr
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal val hdrCapabilityFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
strings(
"av1_profile_main_10_hdr_10_plus_supported",
"video/av01"
)
}

View File

@@ -132,6 +132,7 @@ internal val Instruction.registersUsed: List<Int>
get() = when (this) {
is FiveRegisterInstruction -> {
when (registerCount) {
0 -> listOf()
1 -> listOf(registerC)
2 -> listOf(registerC, registerD)
3 -> listOf(registerC, registerD, registerE)

View File

@@ -178,3 +178,15 @@ internal fun Element.copyAttributesFrom(oldContainer: Element) {
setAttribute(attr.name, attr.value)
}
}
/**
* @return The play store services version.
*/
internal fun ResourcePatchContext.findPlayStoreServicesVersion(): Int =
document("res/values/integers.xml").use { document ->
document.documentElement.childNodes.findElementByAttributeValueOrThrow(
"name",
"google_play_services_version",
).textContent.toInt()
}

View File

@@ -67,6 +67,8 @@ Second \"item\" text"</string>
</patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch>
<patch id="interaction.downloads.downloadsResourcePatch">
@@ -84,12 +86,15 @@ Second \"item\" text"</string>
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Download' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>

View File

@@ -67,6 +67,8 @@ Second \"item\" text"</string>
</patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch>
<patch id="interaction.downloads.downloadsResourcePatch">
@@ -84,12 +86,15 @@ Second \"item\" text"</string>
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Download' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>

View File

@@ -452,6 +452,11 @@ Second \"item\" text"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">سيتم عرض مربع الحوار</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">وهذا لا يتجاوز قيود السن. بل يقبلها تلقائيًا.</string>
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
<string name="revanced_disable_signin_to_tv_popup_title">تعطيل النافذة المنبثقة لتسجيل الدخول إلى التلفزيون</string>
<string name="revanced_disable_signin_to_tv_popup_summary_on">النافذة المنبثقة لتسجيل الدخول إلى التلفزيون معطلة</string>
<string name="revanced_disable_signin_to_tv_popup_summary_off">النافذة المنبثقة لتسجيل الدخول إلى التلفزيون مفعلة</string>
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">تعطيل تخطي الفصل بالنقر المزدوج</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">لا يمكن للنقر المزدوج مطلقًا أن يؤدي إلى تخطي الفصل التالي/السابق</string>
@@ -563,7 +568,7 @@ Second \"item\" text"</string>
<string name="revanced_hide_stop_ads_button_summary_on">زر إيقاف الإعلانات مخفي</string>
<string name="revanced_hide_stop_ads_button_summary_off">زر إيقاف الإعلانات معروض</string>
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<string name="revanced_hide_report_button_title">إخفاء الإبلاغ</string>
<string name="revanced_hide_report_button_summary_on">تم إخفاء زر الإبلاغ</string>
<string name="revanced_hide_report_button_summary_off">يتم عرض زر الإبلاغ</string>
@@ -575,12 +580,21 @@ Second \"item\" text"</string>
<string name="revanced_hide_download_button_title">إخفاء التنزيل</string>
<string name="revanced_hide_download_button_summary_on">تم إخفاء زر التنزيل</string>
<string name="revanced_hide_download_button_summary_off">يتم عرض زر التنزيل</string>
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">إخفاء الضجة</string>
<string name="revanced_hide_hype_button_summary_on">زر الضجة مخفي</string>
<string name="revanced_hide_hype_button_summary_off">يظهر زر الحماس</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">إخفاء الترويج</string>
<string name="revanced_hide_promote_button_summary_on">زر الترويج مخفي</string>
<string name="revanced_hide_promote_button_summary_off">زر الترويج ظاهر</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">إخفاء شكرًا</string>
<string name="revanced_hide_thanks_button_summary_on">تم إخفاء زر شكرًا</string>
<string name="revanced_hide_thanks_button_summary_off">يتم عرض زر شكرًا</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<string name="revanced_hide_ask_button_title">إخفاء \"Ask\"</string>
<string name="revanced_hide_ask_button_summary_on">تم إخفاء زر \"Ask\"</string>
<string name="revanced_hide_ask_button_summary_off">يتم عرض زر \"Ask\"</string>
@@ -1061,10 +1075,12 @@ Second \"item\" text"</string>
<string name="revanced_sb_segments_intro_sum">فاصل زمني بدون محتوى فعلي. قد يكون توقفًا مؤقتًا، أو إطارًا ثابتًا، أو رسومًا متحركة متكررة. لا يتضمن انتقالات تحتوي على معلومات</string>
<string name="revanced_sb_segments_outro">الخاتمة / تترات النهاية</string>
<string name="revanced_sb_segments_outro_sum">تتر النهاية أو عندما تظهر بطاقات نهاية YouTube، نهايات غير منطوقة. ليس للاستنتاجات مع المعلومات</string>
<string name="revanced_sb_segments_preview">معاينة/موجز/ربط</string>
<string name="revanced_sb_segments_hook">مقدمة / تحيات</string>
<string name="revanced_sb_segments_hook_sum">مقاطع دعائية مروية للفيديو القادم، تحيات ووداعات. لا تشمل الأقسام التي تضيف محتوى إضافيًا</string>
<string name="revanced_sb_segments_preview">معاينة / ملخص</string>
<string name="revanced_sb_segments_preview_sum">مجموعة من المقاطع التي توضح ما هو قادم أو ما حدث في الفيديو أو في مقاطع فيديو أخرى من السلسلة، حيث تتكرر جميع المعلومات في مكان آخر</string>
<string name="revanced_sb_segments_filler">خارج الموضوع/النكات</string>
<string name="revanced_sb_segments_filler_sum">تم إضافة مشاهد ملتقطة خارج الموضوع أو الفكاهة التي ليست مطلوبة لفهم المحتوى الرئيسي للفيديو. لا تتضمن مقاطع توفر تَعبِير أو تفاصيل الخلفية</string>
<string name="revanced_sb_segments_filler">استطراد / نكات</string>
<string name="revanced_sb_segments_filler_sum">مشاهد أو نكات جانبية غير ضرورية لفهم المحتوى الرئيسي للفيديو. لا تشمل الأقسام التي توفر سياقًا أو تفاصيل خلفية</string>
<string name="revanced_sb_segments_nomusic">الموسيقى: مقطع غير موسيقي</string>
<string name="revanced_sb_segments_nomusic_sum">فقط للاستخدام في المقاطع الموسيقية. أقسام المقاطع الموسيقية بدون موسيقى، والتي لم يتم تغطيتها بالفعل من قبل فئة أخرى</string>
<string name="revanced_sb_skip_button_compact">تخطي</string>
@@ -1077,10 +1093,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skip_button_intro_middle">تخطي الفاصل</string>
<string name="revanced_sb_skip_button_intro_end">تخطي الفاصل</string>
<string name="revanced_sb_skip_button_outro">تخطي الخاتمة</string>
<string name="revanced_sb_skip_button_hook">تخطي المقدمة</string>
<string name="revanced_sb_skip_button_preview_beginning">تخطي النظرة العامة</string>
<string name="revanced_sb_skip_button_preview_middle">تخطي النظرة العامة</string>
<string name="revanced_sb_skip_button_preview_end">تخطي الملخص</string>
<string name="revanced_sb_skip_button_filler">تخطي مقطع غير ذي صلة</string>
<string name="revanced_sb_skip_button_filler">تخطي الجزء الجانبي</string>
<string name="revanced_sb_skip_button_nomusic">تخطي غير الموسيقى</string>
<string name="revanced_sb_skip_button_unsubmitted">تخطي المقطع</string>
<string name="revanced_sb_skipped_sponsor">تم تخطي الراعي</string>
@@ -1091,10 +1108,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skipped_intro_middle">تم تخطي الفاصل</string>
<string name="revanced_sb_skipped_intro_end">تم تخطي الفاصل</string>
<string name="revanced_sb_skipped_outro">تم تخطي الخاتمة</string>
<string name="revanced_sb_skipped_hook">تم تخطي المقدمة</string>
<string name="revanced_sb_skipped_preview_beginning">تم تخطي النظرة العامة</string>
<string name="revanced_sb_skipped_preview_middle">تم تخطي النظرة العامة</string>
<string name="revanced_sb_skipped_preview_end">تم تخطي الملخص</string>
<string name="revanced_sb_skipped_filler">تم تخطي مقطع غير ذي صلة</string>
<string name="revanced_sb_skipped_filler">تم تخطي الجزء الجانبي</string>
<string name="revanced_sb_skipped_nomusic">تم تخطي جزء غير موسيقي</string>
<string name="revanced_sb_skipped_unsubmitted">تم تخطي المقطع الغير المرسل</string>
<string name="revanced_sb_skipped_multiple_segments">تم تخطي عدة مقاطع</string>

View File

@@ -67,6 +67,8 @@ Second \"item\" text"</string>
</patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch>
<patch id="interaction.downloads.downloadsResourcePatch">
@@ -84,12 +86,15 @@ Second \"item\" text"</string>
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Download' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>

View File

@@ -452,6 +452,11 @@ 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_user_dialog_message">Bu, yaş məhdudiyyətini ötürmür. Sadəcə birbaşa qəbul edir.</string>
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
<string name="revanced_disable_signin_to_tv_popup_title">TV ani görüntüsü girişin qapat</string>
<string name="revanced_disable_signin_to_tv_popup_summary_on">TV ani görüntüyə giriş qapadılıb</string>
<string name="revanced_disable_signin_to_tv_popup_summary_off">TV ani görüntüyə giriş işləkdir</string>
</patch>
<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_summary_on">Cüt toxunma heç vaxt növbəti/əvvəlki fəsilə keçidi zorlaya bilməz</string>
@@ -563,7 +568,7 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz
<string name="revanced_hide_stop_ads_button_summary_on">Reklamları dayandır düyməsi gizlidir</string>
<string name="revanced_hide_stop_ads_button_summary_off">Reklamları dayandır düyməsi görünür</string>
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<string name="revanced_hide_report_button_title">\"Xəbər verin\"i gizlət</string>
<string name="revanced_hide_report_button_summary_on">Xəbər ver/düyməsi gizlidir</string>
<string name="revanced_hide_report_button_summary_off">Xəbər ver/düyməsi göstərilir</string>
@@ -575,12 +580,21 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz
<string name="revanced_hide_download_button_title">\"Endirin\"i gizlət</string>
<string name="revanced_hide_download_button_summary_on">Yükləmə düyməsi gizlidir</string>
<string name="revanced_hide_download_button_summary_off">Yükləmə düyməsi göstərilir</string>
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">Coşqu Gizlət</string>
<string name="revanced_hide_hype_button_summary_on">Coşqu düyməsi gizlidir</string>
<string name="revanced_hide_hype_button_summary_off">Coşqu düyməsi görünür</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">Sponsor-u Gizlət</string>
<string name="revanced_hide_promote_button_summary_on">Sponsor düyməsi gizlidir</string>
<string name="revanced_hide_promote_button_summary_off"> Sponsor düyməsi görünür</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">\"Təşəkkürlər\"i gizlət</string>
<string name="revanced_hide_thanks_button_summary_on">Təşəkkür düyməsi gizlidir</string>
<string name="revanced_hide_thanks_button_summary_off">Təşəkkür düyməsi göstərilir</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<string name="revanced_hide_ask_button_title">Soruş\'u Gizlət</string>
<string name="revanced_hide_ask_button_summary_on">Soruş düyməsi gizlidir</string>
<string name="revanced_hide_ask_button_summary_off">\"Soruş\" düyməsi göstərilir</string>
@@ -1060,10 +1074,12 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
<string name="revanced_sb_segments_intro_sum">Həqiqi məzmunu olmayan aralıq. Fasilə, statik kadr və ya təkrarlanan animasiya ola bilər. Məlumat ehtiva edən keçidlər daxil deyil</string>
<string name="revanced_sb_segments_outro">Son kartlar / Zaminlər</string>
<string name="revanced_sb_segments_outro_sum">Zaminlər və ya YouTube bitiş kartları görünəndə. Məlumat daxil olan nəticələr üçün deyil</string>
<string name="revanced_sb_segments_preview">Önizləmə/Anons/Qısa</string>
<string name="revanced_sb_segments_hook">Giriş / Salamlar</string>
<string name="revanced_sb_segments_hook_sum">Yaxınlaşan video üçün danışılan kadrlar, salamlama və sağollaşma. Əlavə məzmun əlavə edən bölmələr daxil deyil</string>
<string name="revanced_sb_segments_preview">Önizləmə / Anons</string>
<string name="revanced_sb_segments_preview_sum">Videoda və ya seriyanın digər videolarında nə gözlənildiyini və ya baş verdiyini göstərən, bütün məlumatların başqa yerdə təkrarlandığı bölüm toplusu</string>
<string name="revanced_sb_segments_filler">Əlaqəsiz/Zarafatlar</string>
<string name="revanced_sb_segments_filler_sum">Videonun əsas məzmununu başa düşmək tələb olunmayan yalnız əlaqəsiz və ya yumor üçün əlavə edilmiş təsiredici səhnələr. Məzmun və ya arxa plan detallarınıqdim edən bölümlər daxil deyil</string>
<string name="revanced_sb_segments_filler">Əlaqəsiz / Zarafatlar</string>
<string name="revanced_sb_segments_filler_sum">Videonun əsas məzmunun başa düşmək tələb olunmayan əlaqəsiz səhnələr və ya zarafatlar. Məzmun və ya arxa plan təfərrüatlarınımin edən bölmələr daxil deyil</string>
<string name="revanced_sb_segments_nomusic">Musiqi: Musiqi olmayan bölmə</string>
<string name="revanced_sb_segments_nomusic_sum">Yalnız musiqi videolarında istifadə üçün. Artıq başqa kateqoriyaya aid edilməyən musiqisiz musiqi videoları bölmələri</string>
<string name="revanced_sb_skip_button_compact">Ötür</string>
@@ -1076,10 +1092,11 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
<string name="revanced_sb_skip_button_intro_middle">Fasiləni ötür</string>
<string name="revanced_sb_skip_button_intro_end">Fasiləni ötür</string>
<string name="revanced_sb_skip_button_outro">Bitişi ötür</string>
<string name="revanced_sb_skip_button_hook">Girişi ötür</string>
<string name="revanced_sb_skip_button_preview_beginning">Önizləməni ötür</string>
<string name="revanced_sb_skip_button_preview_middle">Önizləməni ötür</string>
<string name="revanced_sb_skip_button_preview_end">Anonsu ötür</string>
<string name="revanced_sb_skip_button_filler">Əlaqəsiz hissəni ötür</string>
<string name="revanced_sb_skip_button_filler">Əlaqəsiz olanı ötür</string>
<string name="revanced_sb_skip_button_nomusic">Musiqisiz hissəni ötür</string>
<string name="revanced_sb_skip_button_unsubmitted">Bölümü ötür</string>
<string name="revanced_sb_skipped_sponsor">Sponsorlu hissə ötürüldü</string>
@@ -1090,10 +1107,11 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
<string name="revanced_sb_skipped_intro_middle">Fasilə ötürüldü</string>
<string name="revanced_sb_skipped_intro_end">Fasilə ötürüldü</string>
<string name="revanced_sb_skipped_outro">Bitiş ötürüldü</string>
<string name="revanced_sb_skipped_hook">Giriş ötürüldü</string>
<string name="revanced_sb_skipped_preview_beginning">Önbaxış ötürüldü</string>
<string name="revanced_sb_skipped_preview_middle">Önbaxış ötürüldü</string>
<string name="revanced_sb_skipped_preview_end">Anons ötürüldü</string>
<string name="revanced_sb_skipped_filler">Əlaqəsiz hissə ötürüldü</string>
<string name="revanced_sb_skipped_filler">Əlaqəsiz ötürüldü</string>
<string name="revanced_sb_skipped_nomusic">Musiqi olmayan bölmə ötürüldü</string>
<string name="revanced_sb_skipped_unsubmitted">Göndərilməmiş bölüm ötürüldü</string>
<string name="revanced_sb_skipped_multiple_segments">Çoxlu bölümlər ötürüldü</string>

View File

@@ -452,6 +452,11 @@ Second \"item\" text"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Будзе паказана дыялогавае акно</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Гэта не абыходзіць узроставае абмежаванне. Ён проста прымае гэта аўтаматычна.</string>
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
<string name="revanced_disable_signin_to_tv_popup_title">Адключыць усплывальнае акно «Уваход у ТБ»</string>
<string name="revanced_disable_signin_to_tv_popup_summary_on">Усплывальнае акно «Уваход у ТБ» адключана</string>
<string name="revanced_disable_signin_to_tv_popup_summary_off">Усплывальнае акно «Уваход у ТБ» уключана</string>
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">Адключыць прапуск раздзела па двайным націску</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Двайны націск ніколі не можа выклікаць прапуск да наступнага/папярэдняга раздзела</string>
@@ -563,7 +568,7 @@ Second \"item\" text"</string>
<string name="revanced_hide_stop_ads_button_summary_on">Кнопка \"Спыніць рэкламу\" схавана</string>
<string name="revanced_hide_stop_ads_button_summary_off">Кнопка \"Спыніць рэкламу\" паказана</string>
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<string name="revanced_hide_report_button_title">Схаваць справаздачу</string>
<string name="revanced_hide_report_button_summary_on">Кнопка \"Паведаміць\" схавана</string>
<string name="revanced_hide_report_button_summary_off">Паказана кнопка \"Паведаміць\"</string>
@@ -575,12 +580,21 @@ Second \"item\" text"</string>
<string name="revanced_hide_download_button_title">Схаваць загрузку</string>
<string name="revanced_hide_download_button_summary_on">Кнопка загрузкі схавана</string>
<string name="revanced_hide_download_button_summary_off">Паказана кнопка загрузкі</string>
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">Схаваць хайп</string>
<string name="revanced_hide_hype_button_summary_on">Кнопка Hype схаваная</string>
<string name="revanced_hide_hype_button_summary_off">Кнопка хайпу паказана</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">Схаваць Рэкламу</string>
<string name="revanced_hide_promote_button_summary_on">Кнопка \"Прасоўваць\" схавана</string>
<string name="revanced_hide_promote_button_summary_off">Кнопка \"Прасоўваць\" паказана</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">Схаваць Дзякуй</string>
<string name="revanced_hide_thanks_button_summary_on">Кнопка падзякі схавана</string>
<string name="revanced_hide_thanks_button_summary_off">Паказана кнопка падзякі</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<string name="revanced_hide_ask_button_title">Схаваць кнопку «Запытацца»</string>
<string name="revanced_hide_ask_button_summary_on">Кнопка «Запытацца» схаваная</string>
<string name="revanced_hide_ask_button_summary_off">Кнопка «Запытацца» паказаная</string>
@@ -1062,10 +1076,12 @@ Second \"item\" text"</string>
<string name="revanced_sb_segments_intro_sum">Інтэрвал без фактычнага зместу. Гэта можа быць паўза, статычны кадр або паўтаральная анімацыя. Не ўключае пераходы, якія змяшчаюць інфармацыю</string>
<string name="revanced_sb_segments_outro">Канцоўкі / Цітры</string>
<string name="revanced_sb_segments_outro_sum">Крэдыты або калі з\"яўляюцца канцавыя карткі YouTube. Не для высноў з інфармацыяй</string>
<string name="revanced_sb_segments_preview">Папярэдні прагляд/Паўзвядзенне/Хук</string>
<string name="revanced_sb_segments_hook">Уступ / Прывітанні</string>
<string name="revanced_sb_segments_hook_sum">Агучаныя трэйлеры для будучага відэа, прывітанні і развітанні. Не ўключае раздзелы, якія дадаюць дадатковы змест</string>
<string name="revanced_sb_segments_preview">Прадпрагляд / Паўтарэнне</string>
<string name="revanced_sb_segments_preview_sum">Калекцыя кліпаў, якія паказваюць, што адбываецца або што адбылося ў відэа ці ў іншых відэа серыі, дзе ўся інфармацыя паўтараецца ў іншым месцы</string>
<string name="revanced_sb_segments_filler">Філер Тангенс / Жарты</string>
<string name="revanced_sb_segments_filler_sum">Датычныя сцэны дададзены толькі для напаўнення або гумару, якія не патрэбныя для разумення асноўнага зместу відэа. Не ўключае сегменты, якія прадстаўляюць кантэкст або даведку</string>
<string name="revanced_sb_segments_filler">Лірычнае адступленне / Жарты</string>
<string name="revanced_sb_segments_filler_sum">Тангенцыяльныя сцэны або жарты, якія не патрабуюцца для разумення асноўнага зместу відэа. Не ўключае раздзелы, якія прадастаўляюць кантэкст або фонавыя дэталі</string>
<string name="revanced_sb_segments_nomusic">Музыка: немузычны раздзел</string>
<string name="revanced_sb_segments_nomusic_sum">Толькі для выкарыстання ў музычных відэа. Раздзелы музычных відэа без музыкі, якія яшчэ не ахоплены іншай катэгорыяй</string>
<string name="revanced_sb_skip_button_compact">Прапусціць</string>
@@ -1078,10 +1094,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skip_button_intro_middle">Прапусціць антракт</string>
<string name="revanced_sb_skip_button_intro_end">Прапусціць антракт</string>
<string name="revanced_sb_skip_button_outro">Прапусціць іншы</string>
<string name="revanced_sb_skip_button_hook">Прапусціць уступ</string>
<string name="revanced_sb_skip_button_preview_beginning">Прапусціць папярэдні прагляд</string>
<string name="revanced_sb_skip_button_preview_middle">Прапусціць папярэдні прагляд</string>
<string name="revanced_sb_skip_button_preview_end">Прапусціць рэзюмэ</string>
<string name="revanced_sb_skip_button_filler">Скіп напаўняльнік</string>
<string name="revanced_sb_skip_button_filler">Прапусціць тангенс</string>
<string name="revanced_sb_skip_button_nomusic">Прапусціць не музыку</string>
<string name="revanced_sb_skip_button_unsubmitted">Прапусціць сегмент</string>
<string name="revanced_sb_skipped_sponsor">Прапусціў спонсара</string>
@@ -1092,10 +1109,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skipped_intro_middle">Прапушчаны антракт</string>
<string name="revanced_sb_skipped_intro_end">Прапушчаны антракт</string>
<string name="revanced_sb_skipped_outro">Прапушчаны выхад</string>
<string name="revanced_sb_skipped_hook">Уступ прапушчаны</string>
<string name="revanced_sb_skipped_preview_beginning">Прапушчаны папярэдні прагляд</string>
<string name="revanced_sb_skipped_preview_middle">Прапушчаны папярэдні прагляд</string>
<string name="revanced_sb_skipped_preview_end">Прапушчаны рэзюмэ</string>
<string name="revanced_sb_skipped_filler">Прапушчаны напаўняльнік</string>
<string name="revanced_sb_skipped_filler">Тангенс прапушчаны</string>
<string name="revanced_sb_skipped_nomusic">Прапусціў немузычны раздзел</string>
<string name="revanced_sb_skipped_unsubmitted">Прапушчаны неадпраўлены сегмент</string>
<string name="revanced_sb_skipped_multiple_segments">Прапушчаны некалькі сегментаў</string>

View File

@@ -452,6 +452,11 @@ Second \"item\" text"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Диалоговият прозорец ще бъде показан</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Тази функция не заобикаля възрастовото ограничение. Тя просто приема възрастовата граница автоматично.</string>
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
<string name="revanced_disable_signin_to_tv_popup_title">Деактивиране на изскачащия прозорец „Влизане в телевизора“</string>
<string name="revanced_disable_signin_to_tv_popup_summary_on">Изскачащият прозорец „Влизане в телевизора“ е деактивиран</string>
<string name="revanced_disable_signin_to_tv_popup_summary_off">Изскачащият прозорец „Влизане в телевизора“ е активиран</string>
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">Деактивиране на пропускане на глава с двойно докосване</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Двойното докосване никога не може да предизвика пропускане до следваща/предишна глава</string>
@@ -563,7 +568,7 @@ Second \"item\" text"</string>
<string name="revanced_hide_stop_ads_button_summary_on">Бутонът за спиране на реклами е скрит</string>
<string name="revanced_hide_stop_ads_button_summary_off">Бутонът за спиране на реклами е показан</string>
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<string name="revanced_hide_report_button_title">Бутон за доклади</string>
<string name="revanced_hide_report_button_summary_on">Бутона за докладване е скрит</string>
<string name="revanced_hide_report_button_summary_off">Бутона за докладване се показва</string>
@@ -575,12 +580,21 @@ Second \"item\" text"</string>
<string name="revanced_hide_download_button_title">Бутон за изтегляне</string>
<string name="revanced_hide_download_button_summary_on">Бутона за изтегляне е скрит</string>
<string name="revanced_hide_download_button_summary_off">Бутона за изтегляне се показва</string>
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">Скрий хайпа</string>
<string name="revanced_hide_hype_button_summary_on">Бутонът за хайп е скрит</string>
<string name="revanced_hide_hype_button_summary_off">Бутонът за хайп е показан</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">Скриване на промоция</string>
<string name="revanced_hide_promote_button_summary_on">Бутонът за популяризиране е скрит</string>
<string name="revanced_hide_promote_button_summary_off">Бутонът за популяризиране е показан</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">Бутон за благодарност</string>
<string name="revanced_hide_thanks_button_summary_on">Бутона за благодарност е скрит</string>
<string name="revanced_hide_thanks_button_summary_off">Бутона за благодарност се показва</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<string name="revanced_hide_ask_button_title">Скриване на \"Попитай\"</string>
<string name="revanced_hide_ask_button_summary_on">Бутонът \"Попитай\" е скрит</string>
<string name="revanced_hide_ask_button_summary_off">Бутонът \"Попитай\" е показан</string>
@@ -1061,10 +1075,12 @@ Second \"item\" text"</string>
<string name="revanced_sb_segments_intro_sum">Интервал без реално съдържание. Може да бъде пауза, статичен кадър, повтаряща се анимация. Това не трябва да се използва за преходи, съдържащи информация</string>
<string name="revanced_sb_segments_outro">Край на клипа / Надписи</string>
<string name="revanced_sb_segments_outro_sum">Информация или когато се показват крайните карти на YouTube. Не за заключения с информация</string>
<string name="revanced_sb_segments_preview">Кратък преглед/Обобщение</string>
<string name="revanced_sb_segments_hook">Начало / Поздрави</string>
<string name="revanced_sb_segments_hook_sum">Озвучени трейлъри за предстоящото видео, поздрави и сбогувания. Не включва секции, които добавят допълнително съдържание</string>
<string name="revanced_sb_segments_preview">Предварителен преглед / Резюме</string>
<string name="revanced_sb_segments_preview_sum">Колекция от клипове, които показват какво предстои в този видеоклип или в други видеоклипове от поредицата, където цялата информация се повтаря по-късно във видеоклипа</string>
<string name="revanced_sb_segments_filler">Пълнеж/Шеги</string>
<string name="revanced_sb_segments_filler_sum">Сцени извън темата, добавени само за пълнеж или хумор, които не са необходими за разбирането на основното съдържание на видеоклипа. Това не трябва да включва сегменти, предоставящи контекст или справочни данни</string>
<string name="revanced_sb_segments_filler">Отклонение / Шеги</string>
<string name="revanced_sb_segments_filler_sum">Странични сцени или шеги, които не са необходими за разбиране на основното съдържание на видеоклипа. Не включва секции, предоставящи контекст или фонови детайли</string>
<string name="revanced_sb_segments_nomusic">Музика: Част без музика</string>
<string name="revanced_sb_segments_nomusic_sum">За използване само в музикални видеоклипове. Това трябва да се използва само за части от музикални видеоклипове, които вече не са обхванати от друга категория</string>
<string name="revanced_sb_skip_button_compact">Пропусни</string>
@@ -1077,10 +1093,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skip_button_intro_middle">Пропусни пауза</string>
<string name="revanced_sb_skip_button_intro_end">Пропусни пауза</string>
<string name="revanced_sb_skip_button_outro">Пропусни заключение</string>
<string name="revanced_sb_skip_button_hook">Пропускане на увод</string>
<string name="revanced_sb_skip_button_preview_beginning">Пропусни преглед</string>
<string name="revanced_sb_skip_button_preview_middle">Пропусни преглед</string>
<string name="revanced_sb_skip_button_preview_end">Пропуснете обобщението</string>
<string name="revanced_sb_skip_button_filler">Пропусни пълнеж</string>
<string name="revanced_sb_skip_button_filler">Пропускане на отклонение</string>
<string name="revanced_sb_skip_button_nomusic">Пропусни част без музика</string>
<string name="revanced_sb_skip_button_unsubmitted">Пропускане на сегмент</string>
<string name="revanced_sb_skipped_sponsor">Пропуснат спонсор</string>
@@ -1091,10 +1108,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skipped_intro_middle">Пропусни паузи</string>
<string name="revanced_sb_skipped_intro_end">Пропусни паузи</string>
<string name="revanced_sb_skipped_outro">Пропуснато заключение</string>
<string name="revanced_sb_skipped_hook">Пропуснато увод</string>
<string name="revanced_sb_skipped_preview_beginning">Пропуснат преглед</string>
<string name="revanced_sb_skipped_preview_middle">Пропуснат преглед</string>
<string name="revanced_sb_skipped_preview_end">Пропуснато повторение</string>
<string name="revanced_sb_skipped_filler">Пропуснат пълнеж</string>
<string name="revanced_sb_skipped_filler">Пропуснато отклонение</string>
<string name="revanced_sb_skipped_nomusic">Пропусната част без музика</string>
<string name="revanced_sb_skipped_unsubmitted">Пропуснат неизпратен сегмент</string>
<string name="revanced_sb_skipped_multiple_segments">Пропуснати множество части</string>

View File

@@ -448,6 +448,11 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_remove_viewer_discretion_dialog_summary_off">ডায়ালগ প্রদর্শিত হবে</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">এটি বয়সের সীমাবদ্ধতাকে বাইপাস করে না। এটা শুধু স্বয়ংক্রিয়ভাবে গ্রহণ করে।</string>
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
<string name="revanced_disable_signin_to_tv_popup_title">টিভিতে সাইন ইন পপআপ অক্ষম করুন</string>
<string name="revanced_disable_signin_to_tv_popup_summary_on">টিভিতে সাইন ইন পপআপ অক্ষম করা হয়েছে</string>
<string name="revanced_disable_signin_to_tv_popup_summary_off">টিভিতে সাইন ইন পপআপ সক্ষম করা হয়েছে</string>
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">ডাবল ট্যাপ অধ্যায় স্কিপ অক্ষম করুন</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">ডাবল ট্যাপ কখনও পরবর্তী/পূর্ববর্তী অধ্যায়ে স্কিপ ট্রিগার করতে পারে না</string>
@@ -559,7 +564,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_stop_ads_button_summary_on">বিজ্ঞাপন বন্ধ করুন বোতামটি লুকানো আছে</string>
<string name="revanced_hide_stop_ads_button_summary_off">বিজ্ঞাপন বন্ধ করুন বোতামটি দেখানো হচ্ছে</string>
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<string name="revanced_hide_report_button_title">Report লুকান</string>
<string name="revanced_hide_report_button_summary_on">রিপোর্ট বাটন লুকিয়ে রয়েছে</string>
<string name="revanced_hide_report_button_summary_off">রিপোর্ট বাটন প্রদর্শিত</string>
@@ -571,12 +576,21 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_download_button_title">ডাউনলোডগুলো হাইড করাও</string>
<string name="revanced_hide_download_button_summary_on">ডাউনলোড বোতাম লুকানো আছে</string>
<string name="revanced_hide_download_button_summary_off">ডাউনলোড বোতাম দেখানো হয়েছে</string>
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">হাইপ লুকান</string>
<string name="revanced_hide_hype_button_summary_on">হাইপ বোতাম লুকানো আছে</string>
<string name="revanced_hide_hype_button_summary_off">হাইপ বাটন দেখানো হয়েছে</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">প্রমোট লুকান</string>
<string name="revanced_hide_promote_button_summary_on">প্রোমোশন বাটন লুকানো আছে</string>
<string name="revanced_hide_promote_button_summary_off">প্রোমোশন বাটন দেখানো আছে</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">ধন্যবাদ লুকান</string>
<string name="revanced_hide_thanks_button_summary_on">ধন্যবাদ বোতাম লুকানো আছে</string>
<string name="revanced_hide_thanks_button_summary_off">ধন্যবাদ বোতাম দেখানো হয়</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<string name="revanced_hide_ask_button_title">জিজ্ঞাসা লুকান</string>
<string name="revanced_hide_ask_button_summary_on">জিজ্ঞাসা বোতাম লুকানো আছে</string>
<string name="revanced_hide_ask_button_summary_off">জিজ্ঞাসা বোতাম দেখানো হয়েছে</string>
@@ -1056,10 +1070,12 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
<string name="revanced_sb_segments_intro_sum">প্রকৃত বিষয়বস্তু ছাড়াই একটি বিরতি। বিরতি, স্থির ফ্রেম, অ্যানিমেশন পুনরাবৃত্তি হতে পারে। এটি তথ্যযুক্ত ট্রানজিশনের জন্য ব্যবহার করা উচিত নয়</string>
<string name="revanced_sb_segments_outro">এন্ডকার্ডস / কৃতজ্ঞতা স্বীকার</string>
<string name="revanced_sb_segments_outro_sum">ক্রেডিট বা যখন ইউটিউব এন্ডকার্ডগুলি উপস্থিত হয়। তথ্য সহ সিদ্ধান্তের জন্য নয়</string>
<string name="revanced_sb_segments_preview">পূর্বরূপ/সংক্ষিপ্তবৃত্তি/হুক</string>
<string name="revanced_sb_segments_hook">হুক / শুভেচ্ছা</string>
<string name="revanced_sb_segments_hook_sum">আসন্ন ভিডিওর জন্য বর্ণিত ট্রেলার, শুভেচ্ছা এবং বিদায়। এমন অংশগুলি অন্তর্ভুক্ত নয় যা অতিরিক্ত সামগ্রী যোগ করে।</string>
<string name="revanced_sb_segments_preview">পূর্বরূপ / সারসংক্ষেপ</string>
<string name="revanced_sb_segments_preview_sum">একটি সমষ্টি ক্লিপ সমূহ যা ভিডিওতে এসে যা হচ্ছে বা অন্য ভিডিও সিরিজে ঘটেছে সেগুলি দেখায় যেখানে সমস্ত তথ্য অন্যত্র পুনরাবৃত্তি করা হয়</string>
<string name="revanced_sb_segments_filler">স্পর্শক/কৌতুক ফিল্টার করুন</string>
<string name="revanced_sb_segments_filler_sum">স্পর্শকাতর দৃশ্যগুলি শুধুমাত্র ফিলার বা হাস্যরসের জন্য যোগ করা হয়েছে যা ভিডিওর মূল বিষয়বস্তু বোঝার প্রয়োজন নেই। প্রসঙ্গ বা পটভূমি বিশদ প্রদানকারী বিভাগগুলি এতে অন্তর্ভুক্ত করা উচিত নয়</string>
<string name="revanced_sb_segments_filler">অপ্রাসঙ্গিক / কৌতুক</string>
<string name="revanced_sb_segments_filler_sum">পার্শ্বীয় দৃশ্য বা কৌতুক যা ভিডিওর মূল বিষবস্তু বোঝার জন্য অপরিহার্য নয়। প্রসঙ্গ বা পটভূমি বিশদ প্রদানকারী অংশগুলি অন্তর্ভুক্ত নয়।</string>
<string name="revanced_sb_segments_nomusic">সঙ্গীত: সঙ্গীতবিহীন অংশ</string>
<string name="revanced_sb_segments_nomusic_sum">শুধুমাত্র সঙ্গীত ভিডিওতে ব্যবহারের জন্য। এটি কেবলমাত্র সংগীত ভিডিওর সেসব বিভাগের জন্য ব্যবহার করা উচিত যা ইতিমধ্যে অন্য কোনও বিভাগ দ্বারা আচ্ছাদিত নয়।</string>
<string name="revanced_sb_skip_button_compact">এড়িয়ে যান</string>
@@ -1072,10 +1088,11 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
<string name="revanced_sb_skip_button_intro_middle">উপসংহার এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_intro_end">উপসংহার এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_outro">শেষ অংশ এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_hook">হুক এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_preview_beginning">প্রিভিউ এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_preview_middle">প্রিভিউ এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_preview_end">সংক্ষিপ্তবৃত্তি এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_filler">ফিল্টার এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_filler">প্রাসঙ্গিকতা এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_nomusic">সঙ্গীত-বিহীন অংশ এড়িয়ে যান</string>
<string name="revanced_sb_skip_button_unsubmitted">সেগমেন্ট এড়িয়ে যান</string>
<string name="revanced_sb_skipped_sponsor">স্পন্সর এড়িয়ে গেছে</string>
@@ -1086,10 +1103,11 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
<string name="revanced_sb_skipped_intro_middle">উপসংহার এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_intro_end">উপসংহার এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_outro">শেষ অংশ এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_hook">হুক এড়িয়ে যাওয়া হয়েছে</string>
<string name="revanced_sb_skipped_preview_beginning">প্রাকদর্শন এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_preview_middle">প্রাকদর্শন এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_preview_end">সংক্ষিপ্তবৃত্তি এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_filler">ফিল্টার এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_filler">প্রাসঙ্গিকতা এড়িয়ে যাওয়া হয়েছে</string>
<string name="revanced_sb_skipped_nomusic">একটি সঙ্গীতবিহীন অংশ এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_unsubmitted">জমা না হওয়া সেগমেন্ট এড়িয়ে গেছে</string>
<string name="revanced_sb_skipped_multiple_segments">একটানা একাধিক সেগমেন্ট এড়িয়ে গেছে</string>

View File

@@ -67,6 +67,8 @@ Second \"item\" text"</string>
</patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch>
<patch id="interaction.downloads.downloadsResourcePatch">
@@ -84,12 +86,15 @@ Second \"item\" text"</string>
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Download' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>

View File

@@ -67,6 +67,8 @@ Second \"item\" text"</string>
</patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
</patch>
<patch id="interaction.downloads.downloadsResourcePatch">
@@ -84,12 +86,15 @@ Second \"item\" text"</string>
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Download' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>

View File

@@ -452,6 +452,11 @@ Tato funkce je dostupná pouze pro starší zařízení"</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialog bude zobrazen</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Tímto krokem neobcházíte věkové omezení. Pouze jej automaticky akceptujete.</string>
</patch>
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
<string name="revanced_disable_signin_to_tv_popup_title">Zakázat vyskakovací okno Přihlásit se k televizi</string>
<string name="revanced_disable_signin_to_tv_popup_summary_on">Vyskakovací okno Přihlásit se k televizi je zakázáno</string>
<string name="revanced_disable_signin_to_tv_popup_summary_off">Vyskakovací okno Přihlásit se k televizi je povoleno</string>
</patch>
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
<string name="revanced_disable_chapter_skip_double_tap_title">Zakázat přeskočení kapitoly dvojitým klepnutím</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Dvojité klepnutí nikdy nespustí přeskočení na další/předchozí kapitolu</string>
@@ -563,7 +568,7 @@ Hlasitost se upravuje svislým přejetím po pravé straně obrazovky"</string>
<string name="revanced_hide_stop_ads_button_summary_on">Tlačítko pro zastavení reklam je skryté</string>
<string name="revanced_hide_stop_ads_button_summary_off">Tlačítko pro zastavení reklam je zobrazeno</string>
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
This button usually appears only on live streams. -->
This button usually only shows on live streams. -->
<string name="revanced_hide_report_button_title">Skrýt Nahlásit</string>
<string name="revanced_hide_report_button_summary_on">Tlačítko Nahlásit je skryto</string>
<string name="revanced_hide_report_button_summary_off">Tlačítko Nahlásit je zobrazeno</string>
@@ -575,12 +580,21 @@ Hlasitost se upravuje svislým přejetím po pravé straně obrazovky"</string>
<string name="revanced_hide_download_button_title">Skrýt Stáhnout</string>
<string name="revanced_hide_download_button_summary_on">Tlačítko Stáhnout je skryto</string>
<string name="revanced_hide_download_button_summary_off">Tlačítko Stáhnout je zobrazeno</string>
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">Skrýt Hype</string>
<string name="revanced_hide_hype_button_summary_on">Tlačítko Hype je skryto</string>
<string name="revanced_hide_hype_button_summary_off">Tlačítko Hype je zobrazeno</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">Skrýt propagaci</string>
<string name="revanced_hide_promote_button_summary_on">Tlačítko Propagovat je skryto</string>
<string name="revanced_hide_promote_button_summary_off">Tlačítko Propagovat je zobrazeno</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">Skrýt Poděkování</string>
<string name="revanced_hide_thanks_button_summary_on">Tlačítko Poděkování je skryto</string>
<string name="revanced_hide_thanks_button_summary_off">Tlačítko Poděkování je zobrazeno</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows up if the user ip is from specific region such as the USA or EU. -->
This button only shows if the user ip is from specific region such as the USA or EU. -->
<string name="revanced_hide_ask_button_title">Skrýt Zeptat se</string>
<string name="revanced_hide_ask_button_summary_on">Tlačítko Zeptat se je skryté</string>
<string name="revanced_hide_ask_button_summary_off">Tlačítko Zeptat se je zobrazeno</string>
@@ -1061,10 +1075,12 @@ Vaše ID uživatele je jako heslo a nikdy by nemělo být sdíleno."</string>
<string name="revanced_sb_segments_intro_sum">Interval bez skutečného obsahu. Může to být pauza, statický snímek nebo opakující se animace. Neobsahuje přechody s informacemi</string>
<string name="revanced_sb_segments_outro">Outro / Závěrečné titulky</string>
<string name="revanced_sb_segments_outro_sum">Titulky nebo když se objeví závěrečné karty YouTube. Ne pro závěry s informacemi</string>
<string name="revanced_sb_segments_preview">Náhled/Shrnutí/Háček</string>
<string name="revanced_sb_segments_hook">Úvod / Pozdravy</string>
<string name="revanced_sb_segments_hook_sum">Komentované upoutávky na nadcházející video, pozdravy a rozloučení. Neobsahuje sekce, které přidávají další obsah</string>
<string name="revanced_sb_segments_preview">Náhled / Shrnutí</string>
<string name="revanced_sb_segments_preview_sum">Sbírka klipů, které ukazují, co se chystá nebo co se stalo ve videu nebo v jiných videích série, kde jsou všechny informace opakované jinde</string>
<string name="revanced_sb_segments_filler">Výplň / vtipy</string>
<string name="revanced_sb_segments_filler_sum">Vedlejší scény přidány pouze pro výplň nebo humor, které nejsou nutné pro pochopení hlavního obsahu videa. Neobsahuje segmenty poskytující kontext nebo podrobnosti o pozadí</string>
<string name="revanced_sb_segments_filler">Odbočka / Vtipy</string>
<string name="revanced_sb_segments_filler_sum">Vedlejší scény nebo vtipy, které nejsou nutné k pochopení hlavního obsahu videa. Neobsahuje sekce poskytující kontext nebo podrobnosti na pozadí</string>
<string name="revanced_sb_segments_nomusic">Hudba: nehudební sekce</string>
<string name="revanced_sb_segments_nomusic_sum">Pouze pro použití v hudebních videích. Sekce hudebních videí bez hudby, které nejsou již pokryty jinou kategorií</string>
<string name="revanced_sb_skip_button_compact">Přeskočit</string>
@@ -1077,10 +1093,11 @@ Vaše ID uživatele je jako heslo a nikdy by nemělo být sdíleno."</string>
<string name="revanced_sb_skip_button_intro_middle">Přeskočit přestávku</string>
<string name="revanced_sb_skip_button_intro_end">Přeskočit přestávku</string>
<string name="revanced_sb_skip_button_outro">Přeskočit závěr</string>
<string name="revanced_sb_skip_button_hook">Přeskočit úvod</string>
<string name="revanced_sb_skip_button_preview_beginning">Přeskočit náhled</string>
<string name="revanced_sb_skip_button_preview_middle">Přeskočit náhled</string>
<string name="revanced_sb_skip_button_preview_end">Přeskočit shrnutí</string>
<string name="revanced_sb_skip_button_filler">Přeskočit výplň</string>
<string name="revanced_sb_skip_button_filler">Přeskočit vedlejší část</string>
<string name="revanced_sb_skip_button_nomusic">Přeskočit bez hudby</string>
<string name="revanced_sb_skip_button_unsubmitted">Přeskočit segment</string>
<string name="revanced_sb_skipped_sponsor">Sponzor přeskočen</string>
@@ -1091,10 +1108,11 @@ Vaše ID uživatele je jako heslo a nikdy by nemělo být sdíleno."</string>
<string name="revanced_sb_skipped_intro_middle">Přeskočena přestávka</string>
<string name="revanced_sb_skipped_intro_end">Přeskočena přestávka</string>
<string name="revanced_sb_skipped_outro">Outro přeskočeno</string>
<string name="revanced_sb_skipped_hook">Úvod přeskočen</string>
<string name="revanced_sb_skipped_preview_beginning">Přeskočena ukázka/rekapitulace</string>
<string name="revanced_sb_skipped_preview_middle">Přeskočena ukázka/rekapitulace</string>
<string name="revanced_sb_skipped_preview_end">Přeskočeno shrnutí</string>
<string name="revanced_sb_skipped_filler">Přeskočená nepodstatná výplň videa</string>
<string name="revanced_sb_skipped_filler">Vedlejší část přeskočena</string>
<string name="revanced_sb_skipped_nomusic">Přeskočena nehudební sekce</string>
<string name="revanced_sb_skipped_unsubmitted">Přeskočen neodeslaný segment</string>
<string name="revanced_sb_skipped_multiple_segments">Přeskočeno více segmentů</string>

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