1
mirror of https://github.com/revanced/revanced-integrations synced 2025-11-19 03:23:27 +01:00

Compare commits

...

72 Commits

Author SHA1 Message Date
semantic-release-bot
45dd26c397 chore(release): 1.0.1-dev.2 [skip ci]
## [1.0.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.0.1-dev.1...v1.0.1-dev.2) (2023-12-17)

### Bug Fixes

* **YouTube - Return YouTube Dislike:** Do not prefetch Shorts shelf items on app startup ([697c2aa](697c2aaac6))
2023-12-17 09:16:45 +00:00
LisoUseInAIKyrios
697c2aaac6 fix(YouTube - Return YouTube Dislike): Do not prefetch Shorts shelf items on app startup 2023-12-17 13:14:05 +04:00
semantic-release-bot
869b209c4b chore(release): 1.0.1-dev.1 [skip ci]
## [1.0.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0...v1.0.1-dev.1) (2023-12-16)

### Bug Fixes

* **YouTube - SponsorBlock:** Export local statistics with saved settings ([#542](https://github.com/ReVanced/revanced-integrations/issues/542)) ([0ed8e5a](0ed8e5a298))
2023-12-16 11:25:35 +00:00
LisoUseInAIKyrios
0ed8e5a298 fix(YouTube - SponsorBlock): Export local statistics with saved settings (#542) 2023-12-16 15:22:59 +04:00
LisoUseInAIKyrios
aedb3eddd6 refactor(YouTube - Litho filter): Simplify filtering callbacks (#539) 2023-12-13 02:40:28 +04:00
semantic-release-bot
56cf001964 chore(release): 1.0.0 [skip ci]
# [1.0.0](https://github.com/ReVanced/revanced-integrations/compare/v0.125.0...v1.0.0) (2023-12-12)

### Bug Fixes

* **YouTube - Announcements:** Don't show error toast if there is no internet connection ([#537](https://github.com/ReVanced/revanced-integrations/issues/537)) ([0ce92c2](0ce92c284d))
* **YouTube - Client spoof:** Do not break clips ([f9102fa](f9102fa83b))
* **YouTube - Minimized playback:** Fix PIP incorrectly shown for some Shorts playback ([#533](https://github.com/ReVanced/revanced-integrations/issues/533)) ([fb433da](fb433da6ad))
* **YouTube - Return YouTube Dislike:** Fix dislikes sometimes not showing for non English language ([5d4c8b0](5d4c8b0a1b))
* **YouTube - Return YouTube Dislike:** Prevent the first Short opened from freezing the UI ([#532](https://github.com/ReVanced/revanced-integrations/issues/532)) ([0bb8669](0bb86694e2))
* **YouTube - Return YouTube Dislike:** Wait until fetch is complete before allowing the first Short to start playback ([#538](https://github.com/ReVanced/revanced-integrations/issues/538)) ([1c9c51c](1c9c51ca5f))
* **YouTube - SponsorBlock:** Allow autoplay when skipping to the end of the video ([3d660e1](3d660e1b5e))
* **YouTube - SponsorBlock:** Prevent autoplay from stopping to work ([f4e2d56](f4e2d56b18))
* **YouTube - Spoof signature:** Wait until storyboard fetch is done ([#535](https://github.com/ReVanced/revanced-integrations/issues/535)) ([92e8619](92e8619cd7))

### Features

* Allow choosing the vendor of GmsCore via patch options ([#529](https://github.com/ReVanced/revanced-integrations/issues/529)) ([fba7181](fba7181e70))
* **Tiktok:** Bump compatibility to `32.5.3` ([#536](https://github.com/ReVanced/revanced-integrations/issues/536)) ([10a1e16](10a1e168d0))
* **YouTube - Alternative Thumbnails:** Add option to use DeArrow ([#534](https://github.com/ReVanced/revanced-integrations/issues/534)) ([c4ee6ca](c4ee6ca4dd))
* **YouTube:** Add `Change start page` patch ([792dc0c](792dc0c522))

### BREAKING CHANGES

* The class `MicroGSupport` has been renamed to `GmsCoreSupport`
2023-12-12 00:13:59 +00:00
oSumAtrIX
69c5028661 chore: Merge branch dev to main (#530) 2023-12-12 01:11:30 +01:00
semantic-release-bot
30f2c4f4c9 chore(release): 1.0.0-dev.12 [skip ci]
# [1.0.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.11...v1.0.0-dev.12) (2023-12-12)

### Features

* **Tiktok:** Bump compatibility to `32.5.3` ([#536](https://github.com/ReVanced/revanced-integrations/issues/536)) ([10a1e16](10a1e168d0))
2023-12-12 00:09:33 +00:00
d4rkk3y
10a1e168d0 feat(Tiktok): Bump compatibility to 32.5.3 (#536)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-12-12 01:07:08 +01:00
semantic-release-bot
e79ebb26ec chore(release): 1.0.0-dev.11 [skip ci]
# [1.0.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2023-12-11)

### Features

* **YouTube:** Add `Change start page` patch ([792dc0c](792dc0c522))
2023-12-11 23:44:14 +00:00
oSumAtrIX
792dc0c522 feat(YouTube): Add Change start page patch 2023-12-12 00:38:04 +01:00
semantic-release-bot
8870f7ab0c chore(release): 1.0.0-dev.10 [skip ci]
# [1.0.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.9...v1.0.0-dev.10) (2023-12-11)

### Bug Fixes

* **YouTube - Return YouTube Dislike:** Wait until fetch is complete before allowing the first Short to start playback ([#538](https://github.com/ReVanced/revanced-integrations/issues/538)) ([1c9c51c](1c9c51ca5f))
2023-12-11 18:33:07 +00:00
LisoUseInAIKyrios
1c9c51ca5f fix(YouTube - Return YouTube Dislike): Wait until fetch is complete before allowing the first Short to start playback (#538) 2023-12-11 22:30:36 +04:00
semantic-release-bot
6f7a7b825e chore(release): 1.0.0-dev.9 [skip ci]
# [1.0.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.8...v1.0.0-dev.9) (2023-12-11)

### Features

* **YouTube - Alternative Thumbnails:** Add option to use DeArrow ([#534](https://github.com/ReVanced/revanced-integrations/issues/534)) ([c4ee6ca](c4ee6ca4dd))
2023-12-11 01:09:29 +00:00
Chris
c4ee6ca4dd feat(YouTube - Alternative Thumbnails): Add option to use DeArrow (#534)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2023-12-11 05:06:55 +04:00
semantic-release-bot
46dbbf5f86 chore(release): 1.0.0-dev.8 [skip ci]
# [1.0.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.7...v1.0.0-dev.8) (2023-12-10)

### Bug Fixes

* **YouTube - Announcements:** Don't show error toast if there is no internet connection ([#537](https://github.com/ReVanced/revanced-integrations/issues/537)) ([0ce92c2](0ce92c284d))
2023-12-10 22:46:37 +00:00
nullptr
0ce92c284d fix(YouTube - Announcements): Don't show error toast if there is no internet connection (#537) 2023-12-10 23:44:10 +01:00
oSumAtrIX
fb56e9a362 build: Simplify enabling local build cache 2023-12-10 22:21:40 +01:00
semantic-release-bot
fa5713b4a0 chore(release): 1.0.0-dev.7 [skip ci]
# [1.0.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2023-12-09)

### Bug Fixes

* **YouTube - Spoof signature:** Wait until storyboard fetch is done ([#535](https://github.com/ReVanced/revanced-integrations/issues/535)) ([92e8619](92e8619cd7))
2023-12-09 10:33:48 +00:00
LisoUseInAIKyrios
92e8619cd7 fix(YouTube - Spoof signature): Wait until storyboard fetch is done (#535) 2023-12-09 14:31:20 +04:00
semantic-release-bot
9c635e5f91 chore(release): 1.0.0-dev.6 [skip ci]
# [1.0.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2023-12-07)

### Bug Fixes

* **YouTube - Client spoof:** Do not break clips ([f9102fa](f9102fa83b))
2023-12-07 19:03:21 +00:00
oSumAtrIX
f9102fa83b fix(YouTube - Client spoof): Do not break clips 2023-12-07 23:00:36 +04:00
semantic-release-bot
e7758a7ac4 chore(release): 1.0.0-dev.5 [skip ci]
# [1.0.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2023-12-04)

### Bug Fixes

* **YouTube - Minimized playback:** Fix PIP incorrectly shown for some Shorts playback ([#533](https://github.com/ReVanced/revanced-integrations/issues/533)) ([fb433da](fb433da6ad))
2023-12-04 23:50:11 +00:00
LisoUseInAIKyrios
fb433da6ad fix(YouTube - Minimized playback): Fix PIP incorrectly shown for some Shorts playback (#533) 2023-12-05 03:47:31 +04:00
semantic-release-bot
aa6f591141 chore(release): 1.0.0-dev.4 [skip ci]
# [1.0.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.3...v1.0.0-dev.4) (2023-12-04)

### Bug Fixes

* **YouTube - Return YouTube Dislike:** Prevent the first Short opened from freezing the UI ([#532](https://github.com/ReVanced/revanced-integrations/issues/532)) ([0bb8669](0bb86694e2))
2023-12-04 08:49:53 +00:00
LisoUseInAIKyrios
0bb86694e2 fix(YouTube - Return YouTube Dislike): Prevent the first Short opened from freezing the UI (#532) 2023-12-04 10:47:29 +02:00
semantic-release-bot
d484f35127 chore(release): 1.0.0-dev.3 [skip ci]
# [1.0.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.2...v1.0.0-dev.3) (2023-12-03)

### Bug Fixes

* **YouTube - SponsorBlock:** Prevent autoplay from stopping to work ([f4e2d56](f4e2d56b18))
2023-12-03 18:33:33 +00:00
oSumAtrIX
f4e2d56b18 fix(YouTube - SponsorBlock): Prevent autoplay from stopping to work 2023-12-03 19:30:56 +01:00
semantic-release-bot
9394c512ba chore(release): 1.0.0-dev.2 [skip ci]
# [1.0.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.1...v1.0.0-dev.2) (2023-12-03)

### Bug Fixes

* **YouTube - Return YouTube Dislike:** Fix dislikes sometimes not showing for non English language ([5d4c8b0](5d4c8b0a1b))
2023-12-03 18:27:44 +00:00
LisoUseInAIKyrios
5d4c8b0a1b fix(YouTube - Return YouTube Dislike): Fix dislikes sometimes not showing for non English language 2023-12-03 20:24:37 +02:00
semantic-release-bot
3a56431a28 chore(release): 1.0.0-dev.1 [skip ci]
# [1.0.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.125.1-dev.1...v1.0.0-dev.1) (2023-12-02)

### Features

* Allow choosing the vendor of GmsCore via patch options ([#529](https://github.com/ReVanced/revanced-integrations/issues/529)) ([fba7181](fba7181e70))

### BREAKING CHANGES

* The class `MicroGSupport` has been renamed to `GmsCoreSupport`
2023-12-02 21:54:20 +00:00
oSumAtrIX
fba7181e70 feat: Allow choosing the vendor of GmsCore via patch options (#529)
BREAKING CHANGE: The class `MicroGSupport` has been renamed to `GmsCoreSupport`
2023-12-02 22:51:39 +01:00
semantic-release-bot
3b4f0206ad chore(release): 0.125.1-dev.1 [skip ci]
## [0.125.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.125.0...v0.125.1-dev.1) (2023-12-02)

### Bug Fixes

* **YouTube - SponsorBlock:** Allow autoplay when skipping to the end of the video ([3d660e1](3d660e1b5e))
2023-12-02 21:31:15 +00:00
oSumAtrIX
3d660e1b5e fix(YouTube - SponsorBlock): Allow autoplay when skipping to the end of the video 2023-12-02 17:56:08 +01:00
semantic-release-bot
dd045ad985 chore(release): 0.125.0 [skip ci]
# [0.125.0](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1...v0.125.0) (2023-12-02)

### Features

* Modernize restart logic ([#527](https://github.com/ReVanced/revanced-integrations/issues/527)) ([0ea4e72](0ea4e720ed))
2023-12-02 14:27:11 +00:00
oSumAtrIX
0a15245f41 chore: Merge branch dev to main (#528) 2023-12-02 15:24:33 +01:00
semantic-release-bot
a18c134aaa chore(release): 0.125.0-dev.1 [skip ci]
# [0.125.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1...v0.125.0-dev.1) (2023-11-29)

### Features

* Modernize restart logic ([#527](https://github.com/ReVanced/revanced-integrations/issues/527)) ([0ea4e72](0ea4e720ed))
2023-11-29 20:51:03 +00:00
LisoUseInAIKyrios
0ea4e720ed feat: Modernize restart logic (#527) 2023-11-29 22:48:23 +02:00
semantic-release-bot
c6a1b9fc59 chore(release): 0.124.1 [skip ci]
## [0.124.1](https://github.com/ReVanced/revanced-integrations/compare/v0.124.0...v0.124.1) (2023-11-27)

### Bug Fixes

* **YouTube - Hide layout components:** Prevent app from crashing on startup ([c2112e0](c2112e066a))
* **YouTube - Return YouTube dislike:** Fix layout of right to left languages ([11abdf1](11abdf162f))
* **YouTube - Spoof signature:** fix error toast when viewing very old YouTube videos ([#525](https://github.com/ReVanced/revanced-integrations/issues/525)) ([eede028](eede028c96))
2023-11-27 19:09:52 +00:00
oSumAtrIX
d6ed0c061c chore: Merge branch dev to main (#526) 2023-11-27 20:07:15 +01:00
semantic-release-bot
3ba3d5108d chore(release): 0.124.1-dev.3 [skip ci]
## [0.124.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1-dev.2...v0.124.1-dev.3) (2023-11-27)

### Bug Fixes

* **YouTube - Hide layout components:** Prevent app from crashing on startup ([c2112e0](c2112e066a))
2023-11-27 19:06:27 +00:00
oSumAtrIX
c2112e066a fix(YouTube - Hide layout components): Prevent app from crashing on startup
The application crashes sporadically when a field is not initialized yet in a static context.
2023-11-27 20:02:59 +01:00
oSumAtrIX
6520499a27 refactor: Use a newline consistently 2023-11-27 18:40:49 +01:00
semantic-release-bot
b2d9dcd6c0 chore(release): 0.124.1-dev.2 [skip ci]
## [0.124.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1-dev.1...v0.124.1-dev.2) (2023-11-26)

### Bug Fixes

* **YouTube - Return YouTube dislike:** Fix layout of right to left languages ([11abdf1](11abdf162f))
2023-11-26 22:27:00 +00:00
LisoUseInAIKyrios
11abdf162f fix(YouTube - Return YouTube dislike): Fix layout of right to left languages 2023-11-27 00:24:14 +02:00
semantic-release-bot
b514bdd7d0 chore(release): 0.124.1-dev.1 [skip ci]
## [0.124.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.124.0...v0.124.1-dev.1) (2023-11-25)

### Bug Fixes

* **YouTube - Spoof signature:** fix error toast when viewing very old YouTube videos ([#525](https://github.com/ReVanced/revanced-integrations/issues/525)) ([eede028](eede028c96))
2023-11-25 21:32:51 +00:00
LisoUseInAIKyrios
eede028c96 fix(YouTube - Spoof signature): fix error toast when viewing very old YouTube videos (#525) 2023-11-25 23:30:15 +02:00
semantic-release-bot
9eb0471989 chore(release): 0.124.0 [skip ci]
# [0.124.0](https://github.com/ReVanced/revanced-integrations/compare/v0.123.0...v0.124.0) (2023-11-23)

### Bug Fixes

* **YouTube - Custom playback speed:** Fix toast error on opening playback speed menu ([#522](https://github.com/ReVanced/revanced-integrations/issues/522)) ([0124f41](0124f41cd6))
* **YouTube - Enable tablet layout:** Respect the original device layout ([bc56aa5](bc56aa5f07))
* **YouTube - SponsorBlock:** Do not disable autoplay when skipping to the end of the video ([f936f24](f936f240a7))

### Features

* **YouTube - Hide ads:** Hide shopping links in video description ([11e7c04](11e7c04b70))
* **YouTube - Hide layout components:** Hide "For You" shelf in channel page ([2613e10](2613e102cc))
2023-11-23 03:37:12 +00:00
oSumAtrIX
3dbfbf9e6f chore: Merge branch dev to main (#524) 2023-11-23 04:34:47 +01:00
semantic-release-bot
373820eb99 chore(release): 0.124.0-dev.1 [skip ci]
# [0.124.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.123.1-dev.1...v0.124.0-dev.1) (2023-11-23)

### Bug Fixes

* **YouTube - Enable tablet layout:** Respect the original device layout ([bc56aa5](bc56aa5f07))
* **YouTube - SponsorBlock:** Do not disable autoplay when skipping to the end of the video ([f936f24](f936f240a7))

### Features

* **YouTube - Hide ads:** Hide shopping links in video description ([11e7c04](11e7c04b70))
* **YouTube - Hide layout components:** Hide "For You" shelf in channel page ([2613e10](2613e102cc))
2023-11-23 03:25:50 +00:00
oSumAtrIX
f936f240a7 fix(YouTube - SponsorBlock): Do not disable autoplay when skipping to the end of the video 2023-11-23 04:23:02 +01:00
semantic-release-bot
b9d50fd3d8 chore(release): 0.124.0-dev.1 [skip ci]
# [0.124.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.123.1-dev.1...v0.124.0-dev.1) (2023-11-23)

### Bug Fixes

* **YouTube - Enable tablet layout:** Respect the original device layout ([bc56aa5](bc56aa5f07))

### Features

* **YouTube - Hide ads:** Hide shopping links in video description ([11e7c04](11e7c04b70))
* **YouTube - Hide layout components:** Hide "For You" shelf in channel page ([2613e10](2613e102cc))
2023-11-23 03:01:56 +00:00
oSumAtrIX
11e7c04b70 feat(YouTube - Hide ads): Hide shopping links in video description 2023-11-23 03:55:03 +01:00
oSumAtrIX
2613e102cc feat(YouTube - Hide layout components): Hide "For You" shelf in channel page 2023-11-23 03:55:02 +01:00
semantic-release-bot
2a582f9424 chore(release): 0.123.1-dev.2 [skip ci]
## [0.123.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.123.1-dev.1...v0.123.1-dev.2) (2023-11-23)

### Bug Fixes

* **YouTube - Enable tablet layout:** Respect the original device layout ([9e3e747](9e3e747ce6))
2023-11-23 03:55:02 +01:00
oSumAtrIX
bc56aa5f07 fix(YouTube - Enable tablet layout): Respect the original device layout 2023-11-23 03:54:59 +01:00
oSumAtrIX
1ebf8e04a6 chore: Add heading to issue templates 2023-11-23 00:56:50 +01:00
semantic-release-bot
c13504a0b3 chore(release): 0.123.1-dev.1 [skip ci]
## [0.123.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.123.0...v0.123.1-dev.1) (2023-11-22)

### Bug Fixes

* **YouTube - Custom playback speed:** Fix toast error on opening playback speed menu ([#522](https://github.com/ReVanced/revanced-integrations/issues/522)) ([0124f41](0124f41cd6))
2023-11-22 19:20:28 +00:00
LisoUseInAIKyrios
0124f41cd6 fix(YouTube - Custom playback speed): Fix toast error on opening playback speed menu (#522) 2023-11-22 21:18:01 +02:00
oSumAtrIX
31777e027e chore: Merge branch dev to main (#523) 2023-11-22 09:02:44 +01:00
oSumAtrIX
dedd2f658a chore: Suppress deprecated flag 2023-11-22 01:03:30 +01:00
oSumAtrIX
7f0c2c507c build: Bump dependencies 2023-11-22 01:02:28 +01:00
oSumAtrIX
17e78824b7 build: Bump Gradle wrapper 2023-11-22 01:01:56 +01:00
oSumAtrIX
36fe5718cf build: Use dedicated Gradle cache action 2023-11-22 01:01:56 +01:00
oSumAtrIX
355acc7023 build: Use Gradle build cache 2023-11-22 01:01:55 +01:00
oSumAtrIX
dcca2e5e8d ci: Simplify cache paths 2023-11-22 00:11:15 +01:00
oSumAtrIX
c4d01b2334 chore: Reword comment for first PR merge 2023-11-22 00:07:48 +01:00
oSumAtrIX
ce2ad04f60 chore: Add a newline between steps 2023-11-22 00:04:20 +01:00
oSumAtrIX
1230d77f94 chore: Simplify issue templates 2023-11-21 23:57:28 +01:00
oSumAtrIX
2735f99c0a chore: Add folder to gitignore 2023-11-21 23:42:04 +01:00
oSumAtrIX
64463dea5b ci: Update cache key 2023-11-21 23:41:41 +01:00
oSumAtrIX
4932a71088 chore: Update packages 2023-11-21 23:40:57 +01:00
65 changed files with 12884 additions and 4182 deletions

View File

@@ -1,59 +0,0 @@
name: 🐞 Bug report
description: Report a very clearly broken issue.
title: 'bug: <title>'
labels: [bug]
body:
- type: markdown
attributes:
value: |
# ReVanced bug report
Important to note that your issue may have already been reported before. Please check for existing issues [here](https://github.com/revanced/revanced-integrations/labels/bug).
- type: dropdown
attributes:
label: Type
options:
- Cosmetic
- Other
validations:
required: true
- type: textarea
attributes:
label: Bug description
description: How did you find the bug? Any additional details that might help?
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: Add the steps to reproduce this bug including your environment.
placeholder: Step 1. Download some files. Step 2. ...
validations:
required: true
- type: textarea
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: true
- type: textarea
attributes:
label: Screenshots or videos
description: Add screenshots or videos that show the bug here.
placeholder: Drag and drop the screenshots/videos into this box.
validations:
required: false
- type: textarea
attributes:
label: Solution
description: If applicable, add a possible solution.
validations:
required: false
- type: textarea
attributes:
label: Additional context
description: Add additional context here.
validations:
required: false

109
.github/ISSUE_TEMPLATE/bug-report.yml vendored Normal file
View File

@@ -0,0 +1,109 @@
name: 🐞 Bug report
description: Report a bug or an issue.
title: 'bug: '
labels: ['Bug report']
body:
- type: markdown
attributes:
value: |
<p align="center">
<picture>
<source
width="256px"
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-headline/revanced-headline-vertical-dark.svg"
>
<img
width="256px"
src="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-headline/revanced-headline-vertical-light.svg"
>
</picture>
<br>
<a href="https://revanced.app/">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-logo/revanced-logo.svg" />
<img height="24px" src="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-logo/revanced-logo.svg" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://github.com/ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="http://revanced.app/discord">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://reddit.com/r/revancedapp">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://t.me/app_revanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://x.com/revancedapp">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://www.youtube.com/@ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
</picture>
</a>
<br>
<br>
Continuing the legacy of Vanced
</p>
# ReVanced Integrations bug report
Before creating a new bug report, please keep the following in mind:
- **Do not submit a duplicate bug report**: You can review existing bug reports [here](https://github.com/ReVanced/revanced-integrations/labels/Bug%20report).
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
- type: textarea
attributes:
label: Bug description
description: |
- Describe your bug in detail
- Add steps to reproduce the bug if possible (Step 1. ... Step 2. ...)
- Add images and videos if possible
- List used patches if applicable
validations:
required: true
- type: textarea
attributes:
label: Error logs
description: Exceptions can be captured by running `logcat | grep AndroidRuntime` in a shell.
render: shell
- type: textarea
attributes:
label: Solution
description: If applicable, add a possible solution to the bug.
- type: textarea
attributes:
label: Additional context
description: Add additional context here.
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Your bug report will be closed if you don't follow the checklist below.
options:
- label: This issue is not a duplicate of an existing bug report.
required: true
- label: I have chosen an appropriate title.
required: true
- label: All requested information has been provided properly.
required: true

View File

@@ -1,46 +0,0 @@
name: ⭐ Feature request
description: Create a detailed feature request.
title: 'feat: <title>'
labels: [feature-request]
body:
- type: markdown
attributes:
value: |
# ReVanced feature request
Do not submit requests for patches here. Please submit them [here](https://github.com/orgs/revanced/discussions/categories/patches) instead.
Important to note that your feature request may have already been made before. Please check for existing feature requests [here](https://github.com/revanced/revanced-integrations/labels/feature-request).
- type: dropdown
attributes:
label: Type
options:
- Functionality
- Cosmetic
- Other
validations:
required: true
- type: textarea
attributes:
label: Issue
description: What is the current problem. Why does it require a feature request?
validations:
required: true
- type: textarea
attributes:
label: Feature
description: Describe your feature in detail. How does it solve the issue?
validations:
required: true
- type: textarea
attributes:
label: Motivation
description: Why should your feature should be considered?
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Add additional context here.
validations:
required: false

View File

@@ -0,0 +1,105 @@
name: ⭐ Feature request
description: Create a detailed request for a new feature.
title: 'feat: '
labels: ['Feature request']
body:
- type: markdown
attributes:
value: |
<p align="center">
<picture>
<source
width="256px"
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-headline/revanced-headline-vertical-dark.svg"
>
<img
width="256px"
src="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-headline/revanced-headline-vertical-light.svg"
>
</picture>
<br>
<a href="https://revanced.app/">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-logo/revanced-logo.svg" />
<img height="24px" src="https://raw.githubusercontent.com/revanced/revanced-integrations/main/assets/revanced-logo/revanced-logo.svg" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://github.com/ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="http://revanced.app/discord">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://reddit.com/r/revancedapp">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://t.me/app_revanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://x.com/revancedapp">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://www.youtube.com/@ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
</picture>
</a>
<br>
<br>
Continuing the legacy of Vanced
</p>
# ReVanced Integrations feature request
Before creating a new feature request, please keep the following in mind:
- **Do not submit a duplicate feature request**: You can review existing feature requests [here](https://github.com/ReVanced/revanced-integrations/labels/Feature%20request).
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
- type: textarea
attributes:
label: Feature description
description: |
- Describe your feature in detail
- Add images, videos, links, examples, references, etc. if possible
- Add the target application name in case you request a new patch
- type: textarea
attributes:
label: Motivation
description: |
A strong motivation is necessary for a feature request to be considered.
- Why should this feature be implemented?
- What is the explicit use case?
- What are the benefits?
- What makes this feature important?
validations:
required: true
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Your feature request will be closed if you don't follow the checklist below.
options:
- label: This issue is not a duplicate of an existing feature request.
required: true
- label: I have chosen an appropriate title.
required: true
- label: All requested information has been provided properly.
required: true

2
.github/config.yml vendored
View File

@@ -1,2 +1,2 @@
firstPRMergeComment: >
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) if you want to receive a contributor role.
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) to receive a role for your contribution.

View File

@@ -16,6 +16,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Open pull request
uses: repo-sync/pull-request@v2
with:

View File

@@ -23,23 +23,28 @@ jobs:
# https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false
fetch-depth: 0
- name: Cache
- name: Cache Node modules
uses: actions/cache@v3
with:
path: |
${{ runner.home }}/.gradle/caches
${{ runner.home }}/.gradle/wrapper
.gradle
node_modules
key: ${{ runner.os }}-gradle-npm-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'package-lock.json') }}
key: npm-${{ hashFiles('package-lock.json') }}
- name: Cache Gradle
uses: burrunan/gradle-cache-action@v1
- name: Setup Java
run: echo "JAVA_HOME=$JAVA_HOME_17_X64" >> $GITHUB_ENV
- name: Build with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew build clean
- name: Setup semantic-release
run: npm install
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@
/.idea
/.vscode
/*.log
node_modules

View File

@@ -1,3 +1,241 @@
## [1.0.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.0.1-dev.1...v1.0.1-dev.2) (2023-12-17)
### Bug Fixes
* **YouTube - Return YouTube Dislike:** Do not prefetch Shorts shelf items on app startup ([697c2aa](https://github.com/ReVanced/revanced-integrations/commit/697c2aaac68976c985f0d838795b03f284e907e8))
## [1.0.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0...v1.0.1-dev.1) (2023-12-16)
### Bug Fixes
* **YouTube - SponsorBlock:** Export local statistics with saved settings ([#542](https://github.com/ReVanced/revanced-integrations/issues/542)) ([0ed8e5a](https://github.com/ReVanced/revanced-integrations/commit/0ed8e5a2988c07f3dfbd5dd4e9ef8ed53378fbbe))
# [1.0.0](https://github.com/ReVanced/revanced-integrations/compare/v0.125.0...v1.0.0) (2023-12-12)
### Bug Fixes
* **YouTube - Announcements:** Don't show error toast if there is no internet connection ([#537](https://github.com/ReVanced/revanced-integrations/issues/537)) ([0ce92c2](https://github.com/ReVanced/revanced-integrations/commit/0ce92c284d08a1c6bffba976e9cf208e82288ddf))
* **YouTube - Client spoof:** Do not break clips ([f9102fa](https://github.com/ReVanced/revanced-integrations/commit/f9102fa83bdb2b147543882cb8ebb80b5985ad3e))
* **YouTube - Minimized playback:** Fix PIP incorrectly shown for some Shorts playback ([#533](https://github.com/ReVanced/revanced-integrations/issues/533)) ([fb433da](https://github.com/ReVanced/revanced-integrations/commit/fb433da6ad652aee48fc92794de82bb914ab80ca))
* **YouTube - Return YouTube Dislike:** Fix dislikes sometimes not showing for non English language ([5d4c8b0](https://github.com/ReVanced/revanced-integrations/commit/5d4c8b0a1b77e97c7c0c02288927e92f3c9765ce))
* **YouTube - Return YouTube Dislike:** Prevent the first Short opened from freezing the UI ([#532](https://github.com/ReVanced/revanced-integrations/issues/532)) ([0bb8669](https://github.com/ReVanced/revanced-integrations/commit/0bb86694e24a6a41edee62f5ef1bb80fe7bc3f19))
* **YouTube - Return YouTube Dislike:** Wait until fetch is complete before allowing the first Short to start playback ([#538](https://github.com/ReVanced/revanced-integrations/issues/538)) ([1c9c51c](https://github.com/ReVanced/revanced-integrations/commit/1c9c51ca5f7970774d4e0b5aad5ebcd064cac716))
* **YouTube - SponsorBlock:** Allow autoplay when skipping to the end of the video ([3d660e1](https://github.com/ReVanced/revanced-integrations/commit/3d660e1b5eeab9771f96bd2d26a222b835e2485c))
* **YouTube - SponsorBlock:** Prevent autoplay from stopping to work ([f4e2d56](https://github.com/ReVanced/revanced-integrations/commit/f4e2d56b181fee4d693dea1dfe81974237e4eff7))
* **YouTube - Spoof signature:** Wait until storyboard fetch is done ([#535](https://github.com/ReVanced/revanced-integrations/issues/535)) ([92e8619](https://github.com/ReVanced/revanced-integrations/commit/92e8619cd7bbcf82f27e9407e18c30d65214e31c))
### Features
* Allow choosing the vendor of GmsCore via patch options ([#529](https://github.com/ReVanced/revanced-integrations/issues/529)) ([fba7181](https://github.com/ReVanced/revanced-integrations/commit/fba7181e70d695d7fb13c530754dc1db99b87216))
* **Tiktok:** Bump compatibility to `32.5.3` ([#536](https://github.com/ReVanced/revanced-integrations/issues/536)) ([10a1e16](https://github.com/ReVanced/revanced-integrations/commit/10a1e168d062adc3c979de17738d8cf1b8f25d63))
* **YouTube - Alternative Thumbnails:** Add option to use DeArrow ([#534](https://github.com/ReVanced/revanced-integrations/issues/534)) ([c4ee6ca](https://github.com/ReVanced/revanced-integrations/commit/c4ee6ca4dde13ab8ce6f9cf94f1910455f9d9ecc))
* **YouTube:** Add `Change start page` patch ([792dc0c](https://github.com/ReVanced/revanced-integrations/commit/792dc0c52210dc9b1560290b0cc2afad572c584c))
### BREAKING CHANGES
* The class `MicroGSupport` has been renamed to `GmsCoreSupport`
# [1.0.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.11...v1.0.0-dev.12) (2023-12-12)
### Features
* **Tiktok:** Bump compatibility to `32.5.3` ([#536](https://github.com/ReVanced/revanced-integrations/issues/536)) ([10a1e16](https://github.com/ReVanced/revanced-integrations/commit/10a1e168d062adc3c979de17738d8cf1b8f25d63))
# [1.0.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2023-12-11)
### Features
* **YouTube:** Add `Change start page` patch ([792dc0c](https://github.com/ReVanced/revanced-integrations/commit/792dc0c52210dc9b1560290b0cc2afad572c584c))
# [1.0.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.9...v1.0.0-dev.10) (2023-12-11)
### Bug Fixes
* **YouTube - Return YouTube Dislike:** Wait until fetch is complete before allowing the first Short to start playback ([#538](https://github.com/ReVanced/revanced-integrations/issues/538)) ([1c9c51c](https://github.com/ReVanced/revanced-integrations/commit/1c9c51ca5f7970774d4e0b5aad5ebcd064cac716))
# [1.0.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.8...v1.0.0-dev.9) (2023-12-11)
### Features
* **YouTube - Alternative Thumbnails:** Add option to use DeArrow ([#534](https://github.com/ReVanced/revanced-integrations/issues/534)) ([c4ee6ca](https://github.com/ReVanced/revanced-integrations/commit/c4ee6ca4dde13ab8ce6f9cf94f1910455f9d9ecc))
# [1.0.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.7...v1.0.0-dev.8) (2023-12-10)
### Bug Fixes
* **YouTube - Announcements:** Don't show error toast if there is no internet connection ([#537](https://github.com/ReVanced/revanced-integrations/issues/537)) ([0ce92c2](https://github.com/ReVanced/revanced-integrations/commit/0ce92c284d08a1c6bffba976e9cf208e82288ddf))
# [1.0.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2023-12-09)
### Bug Fixes
* **YouTube - Spoof signature:** Wait until storyboard fetch is done ([#535](https://github.com/ReVanced/revanced-integrations/issues/535)) ([92e8619](https://github.com/ReVanced/revanced-integrations/commit/92e8619cd7bbcf82f27e9407e18c30d65214e31c))
# [1.0.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2023-12-07)
### Bug Fixes
* **YouTube - Client spoof:** Do not break clips ([f9102fa](https://github.com/ReVanced/revanced-integrations/commit/f9102fa83bdb2b147543882cb8ebb80b5985ad3e))
# [1.0.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2023-12-04)
### Bug Fixes
* **YouTube - Minimized playback:** Fix PIP incorrectly shown for some Shorts playback ([#533](https://github.com/ReVanced/revanced-integrations/issues/533)) ([fb433da](https://github.com/ReVanced/revanced-integrations/commit/fb433da6ad652aee48fc92794de82bb914ab80ca))
# [1.0.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.3...v1.0.0-dev.4) (2023-12-04)
### Bug Fixes
* **YouTube - Return YouTube Dislike:** Prevent the first Short opened from freezing the UI ([#532](https://github.com/ReVanced/revanced-integrations/issues/532)) ([0bb8669](https://github.com/ReVanced/revanced-integrations/commit/0bb86694e24a6a41edee62f5ef1bb80fe7bc3f19))
# [1.0.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.2...v1.0.0-dev.3) (2023-12-03)
### Bug Fixes
* **YouTube - SponsorBlock:** Prevent autoplay from stopping to work ([f4e2d56](https://github.com/ReVanced/revanced-integrations/commit/f4e2d56b181fee4d693dea1dfe81974237e4eff7))
# [1.0.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.0.0-dev.1...v1.0.0-dev.2) (2023-12-03)
### Bug Fixes
* **YouTube - Return YouTube Dislike:** Fix dislikes sometimes not showing for non English language ([5d4c8b0](https://github.com/ReVanced/revanced-integrations/commit/5d4c8b0a1b77e97c7c0c02288927e92f3c9765ce))
# [1.0.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.125.1-dev.1...v1.0.0-dev.1) (2023-12-02)
### Features
* Allow choosing the vendor of GmsCore via patch options ([#529](https://github.com/ReVanced/revanced-integrations/issues/529)) ([fba7181](https://github.com/ReVanced/revanced-integrations/commit/fba7181e70d695d7fb13c530754dc1db99b87216))
### BREAKING CHANGES
* The class `MicroGSupport` has been renamed to `GmsCoreSupport`
## [0.125.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.125.0...v0.125.1-dev.1) (2023-12-02)
### Bug Fixes
* **YouTube - SponsorBlock:** Allow autoplay when skipping to the end of the video ([3d660e1](https://github.com/ReVanced/revanced-integrations/commit/3d660e1b5eeab9771f96bd2d26a222b835e2485c))
# [0.125.0](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1...v0.125.0) (2023-12-02)
### Features
* Modernize restart logic ([#527](https://github.com/ReVanced/revanced-integrations/issues/527)) ([0ea4e72](https://github.com/ReVanced/revanced-integrations/commit/0ea4e720edab250aac02b32a8014c24b1127d02f))
# [0.125.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1...v0.125.0-dev.1) (2023-11-29)
### Features
* Modernize restart logic ([#527](https://github.com/ReVanced/revanced-integrations/issues/527)) ([0ea4e72](https://github.com/ReVanced/revanced-integrations/commit/0ea4e720edab250aac02b32a8014c24b1127d02f))
## [0.124.1](https://github.com/ReVanced/revanced-integrations/compare/v0.124.0...v0.124.1) (2023-11-27)
### Bug Fixes
* **YouTube - Hide layout components:** Prevent app from crashing on startup ([c2112e0](https://github.com/ReVanced/revanced-integrations/commit/c2112e066af31890c5d441870d24f3582e9b1dd1))
* **YouTube - Return YouTube dislike:** Fix layout of right to left languages ([11abdf1](https://github.com/ReVanced/revanced-integrations/commit/11abdf162f1a4c82a2330b16ca42800d8599c215))
* **YouTube - Spoof signature:** fix error toast when viewing very old YouTube videos ([#525](https://github.com/ReVanced/revanced-integrations/issues/525)) ([eede028](https://github.com/ReVanced/revanced-integrations/commit/eede028c96042e6abc18377bf16a75e4806aba4a))
## [0.124.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1-dev.2...v0.124.1-dev.3) (2023-11-27)
### Bug Fixes
* **YouTube - Hide layout components:** Prevent app from crashing on startup ([c2112e0](https://github.com/ReVanced/revanced-integrations/commit/c2112e066af31890c5d441870d24f3582e9b1dd1))
## [0.124.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.124.1-dev.1...v0.124.1-dev.2) (2023-11-26)
### Bug Fixes
* **YouTube - Return YouTube dislike:** Fix layout of right to left languages ([11abdf1](https://github.com/ReVanced/revanced-integrations/commit/11abdf162f1a4c82a2330b16ca42800d8599c215))
## [0.124.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.124.0...v0.124.1-dev.1) (2023-11-25)
### Bug Fixes
* **YouTube - Spoof signature:** fix error toast when viewing very old YouTube videos ([#525](https://github.com/ReVanced/revanced-integrations/issues/525)) ([eede028](https://github.com/ReVanced/revanced-integrations/commit/eede028c96042e6abc18377bf16a75e4806aba4a))
# [0.124.0](https://github.com/ReVanced/revanced-integrations/compare/v0.123.0...v0.124.0) (2023-11-23)
### Bug Fixes
* **YouTube - Custom playback speed:** Fix toast error on opening playback speed menu ([#522](https://github.com/ReVanced/revanced-integrations/issues/522)) ([0124f41](https://github.com/ReVanced/revanced-integrations/commit/0124f41cd699467e1c973ea42774c89b751f576f))
* **YouTube - Enable tablet layout:** Respect the original device layout ([bc56aa5](https://github.com/ReVanced/revanced-integrations/commit/bc56aa5f07d8fa5c241343ebf43887f360c79e74))
* **YouTube - SponsorBlock:** Do not disable autoplay when skipping to the end of the video ([f936f24](https://github.com/ReVanced/revanced-integrations/commit/f936f240a7ad14bbf6130ef6960c0fa5542f78c5))
### Features
* **YouTube - Hide ads:** Hide shopping links in video description ([11e7c04](https://github.com/ReVanced/revanced-integrations/commit/11e7c04b707d86901809db3b4f427a0155787177))
* **YouTube - Hide layout components:** Hide "For You" shelf in channel page ([2613e10](https://github.com/ReVanced/revanced-integrations/commit/2613e102cc446c910c4a2f750cc034e12995dd39))
# [0.124.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.123.1-dev.1...v0.124.0-dev.1) (2023-11-23)
### Bug Fixes
* **YouTube - Enable tablet layout:** Respect the original device layout ([bc56aa5](https://github.com/ReVanced/revanced-integrations/commit/bc56aa5f07d8fa5c241343ebf43887f360c79e74))
* **YouTube - SponsorBlock:** Do not disable autoplay when skipping to the end of the video ([f936f24](https://github.com/ReVanced/revanced-integrations/commit/f936f240a7ad14bbf6130ef6960c0fa5542f78c5))
### Features
* **YouTube - Hide ads:** Hide shopping links in video description ([11e7c04](https://github.com/ReVanced/revanced-integrations/commit/11e7c04b707d86901809db3b4f427a0155787177))
* **YouTube - Hide layout components:** Hide "For You" shelf in channel page ([2613e10](https://github.com/ReVanced/revanced-integrations/commit/2613e102cc446c910c4a2f750cc034e12995dd39))
# [0.124.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.123.1-dev.1...v0.124.0-dev.1) (2023-11-23)
### Bug Fixes
* **YouTube - Enable tablet layout:** Respect the original device layout ([bc56aa5](https://github.com/ReVanced/revanced-integrations/commit/bc56aa5f07d8fa5c241343ebf43887f360c79e74))
### Features
* **YouTube - Hide ads:** Hide shopping links in video description ([11e7c04](https://github.com/ReVanced/revanced-integrations/commit/11e7c04b707d86901809db3b4f427a0155787177))
* **YouTube - Hide layout components:** Hide "For You" shelf in channel page ([2613e10](https://github.com/ReVanced/revanced-integrations/commit/2613e102cc446c910c4a2f750cc034e12995dd39))
## [0.123.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.123.1-dev.1...v0.123.1-dev.2) (2023-11-23)
### Bug Fixes
* **YouTube - Enable tablet layout:** Respect the original device layout ([9e3e747](https://github.com/ReVanced/revanced-integrations/commit/9e3e747ce66d58b9ee74e812a68e74d1a88288e0))
## [0.123.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.123.0...v0.123.1-dev.1) (2023-11-22)
### Bug Fixes
* **YouTube - Custom playback speed:** Fix toast error on opening playback speed menu ([#522](https://github.com/ReVanced/revanced-integrations/issues/522)) ([0124f41](https://github.com/ReVanced/revanced-integrations/commit/0124f41cd699467e1c973ea42774c89b751f576f))
# [0.123.0](https://github.com/ReVanced/revanced-integrations/compare/v0.122.1...v0.123.0) (2023-11-20)

View File

@@ -42,7 +42,7 @@ android {
dependencies {
compileOnly(project(mapOf("path" to ":dummy")))
compileOnly("androidx.annotation:annotation:1.6.0")
compileOnly("androidx.annotation:annotation:1.7.0")
compileOnly("androidx.appcompat:appcompat:1.7.0-alpha03")
compileOnly("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
compileOnly("com.squareup.retrofit2:retrofit:2.9.0")

View File

@@ -0,0 +1,16 @@
package app.revanced.integrations.patches;
import android.content.Intent;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
@SuppressWarnings("unused")
public final class ChangeStartPagePatch {
public static void changeIntent(Intent intent) {
final var startPage = SettingsEnum.START_PAGE.getString();
if (startPage.isEmpty()) return;
LogHelper.printDebug(() -> "Changing start page to " + startPage);
intent.setAction("com.google.android.youtube.action." + startPage);
}
}

View File

@@ -0,0 +1,74 @@
package app.revanced.integrations.patches;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.RequiresApi;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
import java.util.Objects;
import static app.revanced.integrations.utils.StringRef.str;
/**
* @noinspection unused
*/
public class GmsCoreSupport {
private static final String GMS_CORE_PACKAGE_NAME
= getGmsCoreVendor() + ".android.gms";
private static final String DONT_KILL_MY_APP_LINK
= "https://dontkillmyapp.com";
private static final Uri GMS_CORE_PROVIDER
= Uri.parse("content://" + getGmsCoreVendor() + ".android.gsf.gservices/prefix");
private static void search(Context context, String uriString, String message) {
ReVancedUtils.showToastLong(message);
var intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(SearchManager.QUERY, uriString);
context.startActivity(intent);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public static void checkAvailability() {
var context = Objects.requireNonNull(ReVancedUtils.getContext());
try {
context.getPackageManager().getPackageInfo(GMS_CORE_PACKAGE_NAME, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException exception) {
LogHelper.printInfo(() -> "GmsCore was not found", exception);
search(context, getGmsCoreDownloadLink(), str("gms_core_not_installed_warning"));
// Gracefully exit the app, so it does not crash.
System.exit(0);
}
try (var client = context.getContentResolver().acquireContentProviderClient(GMS_CORE_PROVIDER)) {
if (client != null) return;
LogHelper.printInfo(() -> "GmsCore is not running in the background");
search(context, DONT_KILL_MY_APP_LINK, str("gms_core_not_running_warning"));
}
}
private static String getGmsCoreDownloadLink() {
final var vendor = getGmsCoreVendor();
switch (vendor) {
case "com.mgoogle":
return "https://github.com/TeamVanced/VancedMicroG/releases/latest";
case "app.revanced":
return "https://github.com/revanced/gmscore/releases/latest";
default:
return vendor + ".android.gms";
}
}
// Modified by a patch. Do not touch.
private static String getGmsCoreVendor() {
return "app.revanced";
}
}

View File

@@ -1,53 +0,0 @@
package app.revanced.integrations.patches;
import static app.revanced.integrations.utils.StringRef.str;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import java.util.Objects;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
public class MicroGSupport {
private static final String MICROG_VENDOR = "com.mgoogle";
private static final String MICROG_PACKAGE_NAME = MICROG_VENDOR + ".android.gms";
private static final String VANCED_MICROG_DOWNLOAD_LINK = "https://github.com/TeamVanced/VancedMicroG/releases/latest";
private static final String DONT_KILL_MY_APP_LINK = "https://dontkillmyapp.com";
private static final Uri VANCED_MICROG_PROVIDER = Uri.parse("content://" + MICROG_VENDOR + ".android.gsf.gservices/prefix");
private static void startIntent(Context context, String uriString, String message) {
ReVancedUtils.showToastLong(message);
var intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(uriString));
context.startActivity(intent);
}
@TargetApi(26)
public static void checkAvailability() {
var context = Objects.requireNonNull(ReVancedUtils.getContext());
try {
context.getPackageManager().getPackageInfo(MICROG_PACKAGE_NAME, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException exception) {
LogHelper.printInfo(() -> "Vanced MicroG was not found", exception);
startIntent(context, VANCED_MICROG_DOWNLOAD_LINK, str("microg_not_installed_warning"));
// Gracefully exit the app, so it does not crash.
System.exit(0);
}
try (var client = context.getContentResolver().acquireContentProviderClient(VANCED_MICROG_PROVIDER)) {
if (client != null) return;
LogHelper.printInfo(() -> "Vanced MicroG is not running in the background");
startIntent(context, DONT_KILL_MY_APP_LINK, str("microg_not_running_warning"));
}
}
}

View File

@@ -2,12 +2,39 @@ package app.revanced.integrations.patches;
import app.revanced.integrations.shared.PlayerType;
@SuppressWarnings("unused")
public class MinimizedPlaybackPatch {
public static boolean isPlaybackNotShort() {
return !PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized();
/**
* Injection point.
*/
public static boolean playbackIsNotShort() {
// Steps to verify most edge cases:
// 1. Open a regular video
// 2. Minimize app (PIP should appear)
// 3. Reopen app
// 4. Open a Short (without closing the regular video)
// (try opening both Shorts in the video player suggestions AND Shorts from the home feed)
// 5. Minimize the app (PIP should not appear)
// 6. Reopen app
// 7. Close the Short
// 8. Resume playing the regular video
// 9. Minimize the app (PIP should appear)
if (!VideoInformation.lastVideoIdIsShort()) {
return true; // Definitely is not a Short.
}
// Might be a Short, or might be a prior regular video on screen again after a Short was closed.
// This incorrectly prevents PIP if player is in WATCH_WHILE_MINIMIZED after closing a Short,
// But there's no way around this unless an additional hook is added to definitively detect
// the Shorts player is on screen. This use case is unusual anyways so it's not a huge concern.
return !PlayerType.getCurrent().isNoneHiddenOrMinimized();
}
/**
* Injection point.
*/
public static boolean overrideMinimizedPlaybackAvailable() {
// This could be done entirely in the patch,
// but having a unique method to search for makes manually inspecting the patched apk much easier.

View File

@@ -9,6 +9,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.integrations.patches.components.ReturnYouTubeDislikeFilterPatch;
import app.revanced.integrations.patches.spoof.SpoofAppVersionPatch;
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.shared.PlayerType;
@@ -27,19 +28,25 @@ import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislik
* Handles all interaction of UI patch components.
*
* Known limitation:
* Litho based Shorts player can experience temporarily frozen video playback if the RYD fetch takes too long.
* The implementation of Shorts litho requires blocking the loading the first Short until RYD has completed.
* This is because it modifies the dislikes text synchronously, and if the RYD fetch has
* not completed yet then the UI will be temporarily frozen.
*
* Temporary work around:
* Enable app spoofing to version 18.33.40 or older, as that uses a non litho Shorts player.
*
* Permanent fix (yet to be implemented), either of:
* - Modify patch to hook onto the Shorts Litho TextView, and update the dislikes asynchronously.
* - Find a way to force Litho to rebuild it's component tree
* (and use that hook to force the shorts dislikes to update after the fetch is completed).
* A (yet to be implemented) solution that fixes this problem. Any one of:
* - Modify patch to hook onto the Shorts Litho TextView, and update the dislikes text asynchronously.
* - Find a way to force Litho to rebuild it's component tree,
* and use that hook to force the shorts dislikes to update after the fetch is completed.
* - Hook into the dislikes button image view, and replace the dislikes thumb down image with a
* generated image of the number of dislikes, then update the image asynchronously. This Could
* also be used for the regular video player to give a better UI layout and completely remove
* the need for the Rolling Number patches.
*/
@SuppressWarnings("unused")
public class ReturnYouTubeDislikePatch {
public static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER =
SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("18.33.40");
/**
* RYD data for the current video on screen.
*/
@@ -318,8 +325,12 @@ public class ReturnYouTubeDislikePatch {
try {
if (SettingsEnum.RYD_ENABLED.getBoolean() && !SettingsEnum.RYD_COMPACT_LAYOUT.getBoolean()) {
if (ReturnYouTubeDislike.isPreviouslyCreatedSegmentedSpan(text)) {
// +1 pixel is needed for some foreign languages that measure
// the text different from what is used for layout (Greek in particular).
// Probably a bug in Android, but who knows.
// Single line mode is also used as an additional fix for this issue.
return measuredTextWidth + ReturnYouTubeDislike.leftSeparatorBounds.right
+ ReturnYouTubeDislike.leftSeparatorShapePaddingPixels;
+ ReturnYouTubeDislike.leftSeparatorShapePaddingPixels + 1;
}
}
} catch (Exception ex) {
@@ -335,9 +346,17 @@ public class ReturnYouTubeDislikePatch {
// YouTube Rolling Numbers do not use compound drawables or drawable padding.
if (view.getCompoundDrawablePadding() == 0) {
LogHelper.printDebug(() -> "Adding rolling number TextView changes");
ShapeDrawable leftSeparator = ReturnYouTubeDislike.getLeftSeparatorDrawable();
view.setCompoundDrawables(leftSeparator, null, null, null);
view.setCompoundDrawablePadding(ReturnYouTubeDislike.leftSeparatorShapePaddingPixels);
ShapeDrawable separator = ReturnYouTubeDislike.getLeftSeparatorDrawable();
if (ReVancedUtils.isRightToLeftTextLayout()) {
view.setCompoundDrawables(null, null, separator, null);
} else {
view.setCompoundDrawables(separator, null, null, null);
}
// Single line mode does not clip words if the span is larger than the view bounds.
// The styled span applied to the view should always have the same bounds,
// but use this feature just in case the measurements are somehow off by a few pixels.
view.setSingleLine(true);
}
}
@@ -350,6 +369,7 @@ public class ReturnYouTubeDislikePatch {
LogHelper.printDebug(() -> "Removing rolling number TextView changes");
view.setCompoundDrawablePadding(0);
view.setCompoundDrawables(null, null, null, null);
view.setSingleLine(false);
}
}
@@ -536,26 +556,47 @@ public class ReturnYouTubeDislikePatch {
// Video Id and voting hooks (all players).
//
private static volatile boolean lastPlayerResponseWasShort;
/**
* Injection point. Uses 'playback response' video id hook to preload RYD.
*/
public static void preloadVideoId(@NonNull String videoId, boolean videoIsOpeningOrPlaying) {
public static void preloadVideoId(@NonNull String videoId, boolean isShortAndOpeningOrPlaying) {
try {
// Shorts shelf in home and subscription feed causes player response hook to be called,
// and the 'is opening/playing' parameter will be false.
// This hook will be called again when the Short is actually opened.
if (!videoIsOpeningOrPlaying || !SettingsEnum.RYD_ENABLED.getBoolean()) {
return;
}
if (!SettingsEnum.RYD_SHORTS.getBoolean() && PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized()) {
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
return;
}
if (videoId.equals(lastPrefetchedVideoId)) {
return;
}
lastPrefetchedVideoId = videoId;
final boolean videoIdIsShort = VideoInformation.lastPlayerResponseIsShort();
// Shorts shelf in home and subscription feed causes player response hook to be called,
// and the 'is opening/playing' parameter will be false.
// This hook will be called again when the Short is actually opened.
if (videoIdIsShort && (!isShortAndOpeningOrPlaying || !SettingsEnum.RYD_SHORTS.getBoolean())) {
return;
}
final boolean waitForFetchToComplete = !IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER
&& videoIdIsShort && !lastPlayerResponseWasShort;
LogHelper.printDebug(() -> "Prefetching RYD for video: " + videoId);
ReturnYouTubeDislike.getFetchForVideoId(videoId);
ReturnYouTubeDislike fetch = ReturnYouTubeDislike.getFetchForVideoId(videoId);
if (waitForFetchToComplete && !fetch.fetchCompleted()) {
// This call is off the main thread, so wait until the RYD fetch completely finishes,
// otherwise if this returns before the fetch completes then the UI can
// become frozen when the main thread tries to modify the litho Shorts dislikes and
// it must wait for the fetch.
// Only need to do this for the first Short opened, as the next Short to swipe to
// are preloaded in the background.
//
// If an asynchronous litho Shorts solution is found, then this blocking call should be removed.
LogHelper.printDebug(() -> "Waiting for prefetch to complete: " + videoId);
fetch.getFetchData(20000); // Any arbitrarily large max wait time.
}
// Set the fields after the fetch completes, so any concurrent calls will also wait.
lastPlayerResponseWasShort = videoIdIsShort;
lastPrefetchedVideoId = videoId;
} catch (Exception ex) {
LogHelper.printException(() -> "preloadVideoId failure", ex);
}

View File

@@ -12,10 +12,15 @@ import java.util.Objects;
/**
* Hooking class for the current playing video.
* @noinspection unused
*/
public final class VideoInformation {
private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f;
private static final String SEEK_METHOD_NAME = "seekTo";
/**
* Prefix present in all Short player parameters signature.
*/
private static final String SHORTS_PLAYER_PARAMETERS = "8AEB";
private static WeakReference<Object> playerControllerRef;
private static Method seekMethod;
@@ -27,6 +32,8 @@ public final class VideoInformation {
@NonNull
private static volatile String playerResponseVideoId = "";
private static volatile boolean playerResponseVideoIdIsShort;
private static volatile boolean videoIdIsShort;
/**
* The current playback speed
@@ -64,12 +71,34 @@ public final class VideoInformation {
}
}
/**
* @return If the player parameters are for a Short.
*/
public static boolean playerParametersAreShort(@NonNull String parameters) {
return parameters.startsWith(SHORTS_PLAYER_PARAMETERS);
}
/**
* Injection point.
*/
public static String newPlayerResponseSignature(@NonNull String signature, boolean isShortAndOpeningOrPlaying) {
final boolean isShort = playerParametersAreShort(signature);
playerResponseVideoIdIsShort = isShort;
if (!isShort || isShortAndOpeningOrPlaying) {
if (videoIdIsShort != isShort) {
videoIdIsShort = isShort;
LogHelper.printDebug(() -> "videoIdIsShort: " + isShort);
}
}
return signature; // Return the original value since we are observing and not modifying.
}
/**
* Injection point. Called off the main thread.
*
* @param videoId The id of the last video loaded.
*/
public static void setPlayerResponseVideoId(@NonNull String videoId, boolean videoIsOpeningOrPlaying) {
public static void setPlayerResponseVideoId(@NonNull String videoId, boolean isShortAndOpeningOrPlaying) {
if (!playerResponseVideoId.equals(videoId)) {
LogHelper.printDebug(() -> "New player response video id: " + videoId);
playerResponseVideoId = videoId;
@@ -89,7 +118,7 @@ public final class VideoInformation {
/**
* Overrides the current playback speed.
*
* <p>
* <b> Used exclusively by {@link RememberPlaybackSpeedPatch} </b>
*/
public static void overridePlaybackSpeed(float speedOverride) {
@@ -124,32 +153,39 @@ public final class VideoInformation {
/**
* Seek on the current video.
* Does not function for playback of Shorts.
*
* <p>
* Caution: If called from a videoTimeHook() callback,
* this will cause a recursive call into the same videoTimeHook() callback.
*
* @param millisecond The millisecond to seek the video to.
* @return if the seek was successful
* @return true if the seek was successful.
*/
public static boolean seekTo(final long millisecond) {
final long videoLength = getVideoLength();
// Prevent issues such as play/ pause button or autoplay not working.
final long seekToMilliseconds = Math.min(millisecond, VideoInformation.getVideoLength() - 250);
ReVancedUtils.verifyOnMainThread();
try {
LogHelper.printDebug(() -> "Seeking to " + millisecond);
return (Boolean) seekMethod.invoke(playerControllerRef.get(), millisecond);
LogHelper.printDebug(() -> "Seeking to " + seekToMilliseconds);
//noinspection DataFlowIssue
return (Boolean) seekMethod.invoke(playerControllerRef.get(), seekToMilliseconds);
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to seek", ex);
return false;
}
}
/** @noinspection UnusedReturnValue*/
public static boolean seekToRelative(long millisecondsRelative) {
return seekTo(videoTime + millisecondsRelative);
}
/**
* Id of the current video playing. Includes Shorts.
* Id of the last video opened. Includes Shorts.
*
* @return The id of the video. Empty string if not set yet.
* @return The id of the video, or an empty string if no videos have been opened yet.
*/
@NonNull
public static String getVideoId() {
@@ -158,20 +194,36 @@ public final class VideoInformation {
/**
* Differs from {@link #videoId} as this is the video id for the
* last player response received, which may not be the current video playing.
*
* last player response received, which may not be the last video opened.
* <p>
* If Shorts are loading the background, this commonly will be
* different from the Short that is currently on screen.
*
* <p>
* For most use cases, you should instead use {@link #getVideoId()}.
*
* @return The id of the last video loaded. Empty string if not set yet.
* @return The id of the last video loaded, or an empty string if no videos have been loaded yet.
*/
@NonNull
public static String getPlayerResponseVideoId() {
return playerResponseVideoId;
}
/**
* @return If the last player response video id was a Short.
* Includes Shorts shelf items appearing in the feed that are not opened.
* @see #lastVideoIdIsShort()
*/
public static boolean lastPlayerResponseIsShort() {
return playerResponseVideoIdIsShort;
}
/**
* @return If the last player response video id _that was opened_ was a Short.
*/
public static boolean lastVideoIdIsShort() {
return videoIdIsShort;
}
/**
* @return The current playback speed.
*/
@@ -192,9 +244,9 @@ public final class VideoInformation {
/**
* Playback time of the current video playing. Includes Shorts.
*
* <p>
* Value will lag behind the actual playback time by a variable amount based on the playback speed.
*
* <p>
* If playback speed is 2.0x, this value may be up to 2000ms behind the actual playback time.
* If playback speed is 1.0x, this value may be up to 1000ms behind the actual playback time.
* If playback speed is 0.5x, this value may be up to 500ms behind the actual playback time.
@@ -208,12 +260,12 @@ public final class VideoInformation {
/**
* @return If the playback is at the end of the video.
*
* <p>
* If video is playing in the background with no video visible,
* this always returns false (even if the video is actually at the end).
*
* <p>
* This is equivalent to checking for {@link VideoState#ENDED},
* but can give a more up to date result for code calling from some hooks.
* but can give a more up-to-date result for code calling from some hooks.
*
* @see VideoState
*/

View File

@@ -32,6 +32,9 @@ public final class AnnouncementsPatch {
public static void showAnnouncement(final Activity context) {
if (!SettingsEnum.ANNOUNCEMENTS.getBoolean()) return;
// Check if there is internet connection
if (!ReVancedUtils.isNetworkConnected()) return;
ReVancedUtils.runOnBackgroundThread(() -> {
try {
HttpURLConnection connection = AnnouncementsRoutes.getAnnouncementsConnectionFromRoute(GET_LATEST_ANNOUNCEMENT, CONSUMER);
@@ -43,7 +46,7 @@ public final class AnnouncementsPatch {
if (connection.getResponseCode() != 200) {
if (SettingsEnum.ANNOUNCEMENT_LAST_HASH.getString().isEmpty()) return;
SettingsEnum.ANNOUNCEMENT_LAST_HASH.saveValue("");
SettingsEnum.ANNOUNCEMENT_LAST_HASH.resetToDefault();
ReVancedUtils.showToastLong("Failed to get announcement");
return;
@@ -118,7 +121,7 @@ public final class AnnouncementsPatch {
*/
private static boolean emptyLastAnnouncementHash() {
if (SettingsEnum.ANNOUNCEMENT_LAST_HASH.getString().isEmpty()) return true;
SettingsEnum.ANNOUNCEMENT_LAST_HASH.saveValue("");
SettingsEnum.ANNOUNCEMENT_LAST_HASH.resetToDefault();
return false;
}

View File

@@ -1,6 +1,5 @@
package app.revanced.integrations.patches.components;
import android.view.View;
import androidx.annotation.Nullable;
@@ -9,9 +8,10 @@ import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.ReVancedUtils;
import app.revanced.integrations.utils.StringTrieSearch;
@SuppressWarnings("unused")
public final class AdsFilter extends Filter {
private final StringTrieSearch exceptions = new StringTrieSearch();
private final StringFilterGroup shoppingLinks;
public AdsFilter() {
exceptions.addPatterns(
@@ -22,6 +22,16 @@ public final class AdsFilter extends Filter {
"library_recent_shelf"
);
// Identifiers.
final var carouselAd = new StringFilterGroup(
SettingsEnum.HIDE_GENERAL_ADS,
"carousel_ad"
);
addIdentifierCallbacks(carouselAd);
// Paths.
final var buttonedAd = new StringFilterGroup(
SettingsEnum.HIDE_BUTTONED_ADS,
"_buttoned_layout",
@@ -60,17 +70,17 @@ public final class AdsFilter extends Filter {
"offer_module_root"
);
final var carouselAd = new StringFilterGroup(
SettingsEnum.HIDE_GENERAL_ADS,
"carousel_ad"
);
final var viewProducts = new StringFilterGroup(
SettingsEnum.HIDE_PRODUCTS_BANNER,
"product_item",
"products_in_video"
);
shoppingLinks = new StringFilterGroup(
SettingsEnum.HIDE_SHOPPING_LINKS,
"expandable_list"
);
final var webLinkPanel = new StringFilterGroup(
SettingsEnum.HIDE_WEB_SEARCH_RESULTS,
"web_link_panel"
@@ -86,25 +96,29 @@ public final class AdsFilter extends Filter {
"cta_shelf_card"
);
this.pathFilterGroupList.addAll(
addPathCallbacks(
generalAds,
buttonedAd,
merchandise,
viewProducts,
selfSponsor,
webLinkPanel,
shoppingLinks,
movieAds
);
this.identifierFilterGroupList.addAll(carouselAd);
}
@Override
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (exceptions.matches(path))
return false;
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
// Check for the index because of likelihood of false positives.
if (matchedGroup == shoppingLinks && contentIndex != 0)
return false;
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
/**

View File

@@ -7,6 +7,7 @@ import androidx.annotation.RequiresApi;
import app.revanced.integrations.settings.SettingsEnum;
@SuppressWarnings("unused")
@RequiresApi(api = Build.VERSION_CODES.N)
final class ButtonsFilter extends Filter {
private static final String VIDEO_ACTION_BAR_PATH = "video_action_bar.eml";
@@ -20,14 +21,14 @@ final class ButtonsFilter extends Filter {
null,
VIDEO_ACTION_BAR_PATH
);
identifierFilterGroupList.addAll(actionBarGroup);
addIdentifierCallbacks(actionBarGroup);
bufferFilterPathGroup = new StringFilterGroup(
null,
"|CellType|CollectionType|CellType|ContainerType|button.eml|"
);
pathFilterGroupList.addAll(
addPathCallbacks(
new StringFilterGroup(
SettingsEnum.HIDE_LIKE_DISLIKE_BUTTON,
"|segmented_like_dislike_button"
@@ -48,33 +49,33 @@ final class ButtonsFilter extends Filter {
);
bufferButtonsGroupList.addAll(
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_LIVE_CHAT_BUTTON,
"yt_outline_message_bubble_overlap"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_REPORT_BUTTON,
"yt_outline_flag"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_SHARE_BUTTON,
"yt_outline_share"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_REMIX_BUTTON,
"yt_outline_youtube_shorts_plus"
),
// Check for clip button both here and using a path filter,
// as there's a chance the path is a generic action button and won't contain 'clip_button'
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_CLIP_BUTTON,
"yt_outline_scissors"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_SHOP_BUTTON,
"yt_outline_bag"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_THANKS_BUTTON,
"yt_outline_dollar_sign_heart"
)
@@ -82,7 +83,7 @@ final class ButtonsFilter extends Filter {
}
private boolean isEveryFilterGroupEnabled() {
for (var group : pathFilterGroupList)
for (var group : pathCallbacks)
if (!group.isEnabled()) return false;
for (var group : bufferButtonsGroupList)
@@ -93,7 +94,7 @@ final class ButtonsFilter extends Filter {
@Override
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
// If the current matched group is the action bar group,
// in case every filter group is enabled, hide the action bar.
if (matchedGroup == actionBarGroup) {
@@ -109,6 +110,6 @@ final class ButtonsFilter extends Filter {
if (!bufferButtonsGroupList.check(protobufBufferArray).isFiltered()) return false;
}
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
}

View File

@@ -2,6 +2,7 @@ package app.revanced.integrations.patches.components;
import app.revanced.integrations.settings.SettingsEnum;
@SuppressWarnings("unused")
final class CommentsFilter extends Filter {
public CommentsFilter() {
@@ -18,7 +19,7 @@ final class CommentsFilter extends Filter {
"comments_entry_point_simplebox"
);
this.pathFilterGroupList.addAll(
addPathCallbacks(
comments,
previewComment
);

View File

@@ -4,6 +4,7 @@ import androidx.annotation.Nullable;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.StringTrieSearch;
@SuppressWarnings("unused")
final class DescriptionComponentsFilter extends Filter {
private final StringTrieSearch exceptions = new StringTrieSearch();
@@ -48,7 +49,7 @@ final class DescriptionComponentsFilter extends Filter {
"transcript_section"
);
pathFilterGroupList.addAll(
addPathCallbacks(
chapterSection,
infoCardsSection,
gameSection,
@@ -61,9 +62,9 @@ final class DescriptionComponentsFilter extends Filter {
@Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (exceptions.matches(path)) return false;
return super.isFiltered(path, identifier, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
return super.isFiltered(path, identifier, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
}

View File

@@ -1,3 +0,0 @@
package app.revanced.integrations.patches.components;
final class DummyFilter extends Filter { }

View File

@@ -2,10 +2,11 @@ package app.revanced.integrations.patches.components;
import app.revanced.integrations.settings.SettingsEnum;
@SuppressWarnings("unused")
public final class HideInfoCardsFilterPatch extends Filter {
public HideInfoCardsFilterPatch() {
identifierFilterGroupList.addAll(
addIdentifierCallbacks(
new StringFilterGroup(
SettingsEnum.HIDE_INFO_CARDS,
"info_card_teaser_overlay.eml"

View File

@@ -1,22 +1,26 @@
package app.revanced.integrations.patches.components;
import android.os.Build;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.StringTrieSearch;
@SuppressWarnings("unused")
@RequiresApi(api = Build.VERSION_CODES.N)
public final class LayoutComponentsFilter extends Filter {
private final StringTrieSearch exceptions = new StringTrieSearch();
private static final StringTrieSearch mixPlaylistsExceptions = new StringTrieSearch();
private static ByteArrayAsStringFilterGroup mixPlaylistsExceptions2;
private static final ByteArrayFilterGroup mixPlaylistsExceptions2 = new ByteArrayFilterGroup(
null,
"cell_description_body"
);
private final CustomFilterGroup custom;
private static final ByteArrayAsStringFilterGroup mixPlaylists = new ByteArrayAsStringFilterGroup(
private static final ByteArrayFilterGroup mixPlaylists = new ByteArrayFilterGroup(
SettingsEnum.HIDE_MIX_PLAYLISTS,
"&list="
);
@@ -25,6 +29,13 @@ public final class LayoutComponentsFilter extends Filter {
private final StringFilterGroup notifyMe;
private final StringFilterGroup expandableMetadata;
static {
mixPlaylistsExceptions.addPatterns(
"V.ED", // Playlist browse id.
"java.lang.ref.WeakReference"
);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public LayoutComponentsFilter() {
exceptions.addPatterns(
@@ -35,16 +46,25 @@ public final class LayoutComponentsFilter extends Filter {
"library_recent_shelf"
);
mixPlaylistsExceptions.addPatterns(
"V.ED", // Playlist browse id.
"java.lang.ref.WeakReference"
// Identifiers.
final var graySeparator = new StringFilterGroup(
SettingsEnum.HIDE_GRAY_SEPARATOR,
"cell_divider" // layout residue (gray line above the buttoned ad),
);
mixPlaylistsExceptions2 = new ByteArrayAsStringFilterGroup(
null,
"cell_description_body"
final var chipsShelf = new StringFilterGroup(
SettingsEnum.HIDE_CHIPS_SHELF,
"chips_shelf"
);
addIdentifierCallbacks(
graySeparator,
chipsShelf
);
// Paths.
custom = new CustomFilterGroup(
SettingsEnum.CUSTOM_FILTER,
SettingsEnum.CUSTOM_FILTER_STRINGS
@@ -156,10 +176,6 @@ public final class LayoutComponentsFilter extends Filter {
"image_shelf"
);
final var graySeparator = new StringFilterGroup(
SettingsEnum.HIDE_GRAY_SEPARATOR,
"cell_divider" // layout residue (gray line above the buttoned ad),
);
final var timedReactions = new StringFilterGroup(
SettingsEnum.HIDE_TIMED_REACTIONS,
@@ -182,17 +198,21 @@ public final class LayoutComponentsFilter extends Filter {
"compact_sponsor_button"
);
final var chipsShelf = new StringFilterGroup(
SettingsEnum.HIDE_CHIPS_SHELF,
"chips_shelf"
);
final var channelWatermark = new StringFilterGroup(
SettingsEnum.HIDE_VIDEO_CHANNEL_WATERMARK,
"featured_channel_watermark_overlay"
);
this.pathFilterGroupList.addAll(
final var forYouShelf = new StringFilterGroup(
SettingsEnum.HIDE_FOR_YOU_SHELF,
"mixed_content_shelf"
);
addPathCallbacks(
custom,
expandableMetadata,
inFeedSurvey,
notifyMe,
channelBar,
communityPosts,
paidContent,
@@ -200,13 +220,10 @@ public final class LayoutComponentsFilter extends Filter {
channelWatermark,
communityGuidelines,
quickActions,
expandableMetadata,
relatedVideos,
compactBanner,
inFeedSurvey,
joinMembership,
medicalPanel,
notifyMe,
videoQualityMenuFooter,
infoPanel,
subscribersCommunityGuidelines,
@@ -216,31 +233,26 @@ public final class LayoutComponentsFilter extends Filter {
timedReactions,
imageShelf,
channelMemberShelf,
custom
);
this.identifierFilterGroupList.addAll(
graySeparator,
chipsShelf
forYouShelf
);
}
@Override
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
// The groups are excluded from the filter due to the exceptions list below.
// Filter them separately here.
if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata)
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
if (matchedGroup != custom && exceptions.matches(path))
return false; // Exceptions are not filtered.
// TODO: This also hides the feed Shorts shelf header
if (matchedGroup == searchResultShelfHeader && matchedIndex != 0) return false;
if (matchedGroup == searchResultShelfHeader && contentIndex != 0) return false;
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
/**
@@ -257,14 +269,15 @@ public final class LayoutComponentsFilter extends Filter {
if (mixPlaylistsExceptions.matches(conversionContext.toString()))
return false;
if (!mixPlaylists.check(bytes).isFiltered()) return false;
if (!mixPlaylists.check(bytes).isFiltered())
return false;
// Prevent hiding the description of some videos accidentally.
if (mixPlaylistsExceptions2.check(bytes).isFiltered()) return false;
if (mixPlaylistsExceptions2.check(bytes).isFiltered())
return false;
LogHelper.printDebug(() -> "Filtered mix playlist");
return true;
}
public static boolean showWatermark() {

View File

@@ -133,7 +133,7 @@ final class CustomFilterGroup extends StringFilterGroup {
for (String pattern : patterns) {
if (!StringTrieSearch.isValidPattern(pattern)) {
ReVancedUtils.showToastLong("Invalid custom filter, resetting to default");
setting.saveValue(setting.defaultValue);
setting.resetToDefault();
return getFilterPatterns(setting);
}
}
@@ -195,6 +195,14 @@ class ByteArrayFilterGroup extends FilterGroup<byte[]> {
super(setting, filters);
}
/**
* Converts the Strings into byte arrays. Used to search for text in binary data.
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public ByteArrayFilterGroup(SettingsEnum setting, String... filters) {
super(setting, Arrays.stream(filters).map(String::getBytes).toArray(byte[][]::new));
}
private synchronized void buildFailurePatterns() {
if (failurePatterns != null) return; // Thread race and another thread already initialized the search.
LogHelper.printDebug(() -> "Building failure array for: " + this);
@@ -211,12 +219,14 @@ class ByteArrayFilterGroup extends FilterGroup<byte[]> {
int matchedLength = 0;
int matchedIndex = -1;
if (isEnabled()) {
if (failurePatterns == null) {
int[][] failures = failurePatterns;
if (failures == null) {
buildFailurePatterns(); // Lazy load.
failures = failurePatterns;
}
for (int i = 0, length = filters.length; i < length; i++) {
byte[] filter = filters[i];
matchedIndex = indexOf(bytes, filter, failurePatterns[i]);
matchedIndex = indexOf(bytes, filter, failures[i]);
if (matchedIndex >= 0) {
matchedLength = filter.length;
break;
@@ -228,34 +238,16 @@ class ByteArrayFilterGroup extends FilterGroup<byte[]> {
}
final class ByteArrayAsStringFilterGroup extends ByteArrayFilterGroup {
@RequiresApi(api = Build.VERSION_CODES.N)
public ByteArrayAsStringFilterGroup(SettingsEnum setting, String... filters) {
super(setting, Arrays.stream(filters).map(String::getBytes).toArray(byte[][]::new));
}
}
abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<T> {
private final List<T> filterGroups = new ArrayList<>();
/**
* Search graph. Created only if needed.
*/
private volatile TrieSearch<V> search;
private final TrieSearch<V> search = createSearchGraph();
@SafeVarargs
protected final void addAll(final T... groups) {
filterGroups.addAll(Arrays.asList(groups));
search = null; // Rebuild, if already created.
}
protected final synchronized void buildSearch() {
// Since litho filtering is multi-threaded, this method can be concurrently called by multiple threads.
if (search != null) return; // Thread race and another thread already initialized the search.
LogHelper.printDebug(() -> "Creating prefix search tree for: " + this);
TrieSearch<V> search = createSearchGraph();
for (T group : filterGroups) {
for (T group : groups) {
if (!group.includeInSearch()) {
continue;
}
@@ -270,7 +262,6 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
});
}
}
this.search = search; // Must set after it's completely initialized.
}
@NonNull
@@ -293,9 +284,6 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
}
protected FilterGroup.FilterGroupResult check(V stack) {
if (search == null) {
buildSearch(); // Lazy load.
}
FilterGroup.FilterGroupResult result = new FilterGroup.FilterGroupResult();
search.matches(stack, result);
return result;
@@ -322,42 +310,90 @@ final class ByteArrayFilterGroupList extends FilterGroupList<byte[], ByteArrayFi
}
}
/**
* Filters litho based components.
*
* Callbacks to filter content are added using {@link #addIdentifierCallbacks(StringFilterGroup...)}
* and {@link #addPathCallbacks(StringFilterGroup...)}.
*
* To filter {@link FilterContentType#PROTOBUFFER}, first add a callback to
* either an identifier or a path.
* Then inside {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)}
* search for the buffer content using either a {@link ByteArrayFilterGroup} (if searching for 1 pattern)
* or a {@link ByteArrayFilterGroupList} (if searching for more than 1 pattern).
*
* All callbacks must be registered before the constructor completes.
*/
abstract class Filter {
/**
* All group filters must be set before the constructor call completes.
* Otherwise {@link #isFiltered(String, String, byte[], FilterGroupList, FilterGroup, int)}
* will never be called for any matches.
*/
protected final StringFilterGroupList pathFilterGroupList = new StringFilterGroupList();
protected final StringFilterGroupList identifierFilterGroupList = new StringFilterGroupList();
public enum FilterContentType {
IDENTIFIER,
PATH,
PROTOBUFFER
}
/**
* Identifier callbacks. Do not add to this instance,
* and instead use {@link #addIdentifierCallbacks(StringFilterGroup...)}.
*/
protected final List<StringFilterGroup> identifierCallbacks = new ArrayList<>();
/**
* Path callbacks. Do not add to this instance,
* and instead use {@link #addPathCallbacks(StringFilterGroup...)}.
*/
protected final List<StringFilterGroup> pathCallbacks = new ArrayList<>();
/**
* Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)}
* if any of the groups are found.
*/
protected final void addIdentifierCallbacks(StringFilterGroup... groups) {
identifierCallbacks.addAll(Arrays.asList(groups));
}
/**
* Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)}
* if any of the groups are found.
*/
protected final void addPathCallbacks(StringFilterGroup... groups) {
pathCallbacks.addAll(Arrays.asList(groups));
}
/**
* Called after an enabled filter has been matched.
* Default implementation is to always filter the matched item.
* Default implementation is to always filter the matched component and log the action.
* Subclasses can perform additional or different checks if needed.
* <p>
* If the content is to be filtered, subclasses should always
* call this method (and never return a plain 'true').
* That way the logs will always show when a component was filtered and which filter hide it.
* <p>
* Method is called off the main thread.
*
* @param matchedList The list the group filter belongs to.
* @param matchedGroup The actual filter that matched.
* @param matchedIndex Matched index of string/array.
* @return True if the litho item should be filtered out.
* @param contentType The type of content matched.
* @param contentIndex Matched index of the identifier or path.
* @return True if the litho component should be filtered out.
*/
@SuppressWarnings("rawtypes")
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (SettingsEnum.DEBUG.getBoolean()) {
if (matchedList == identifierFilterGroupList) {
LogHelper.printDebug(() -> getClass().getSimpleName() + " Filtered identifier: " + identifier);
String filterSimpleName = getClass().getSimpleName();
if (contentType == FilterContentType.IDENTIFIER) {
LogHelper.printDebug(() -> filterSimpleName + " Filtered identifier: " + identifier);
} else {
LogHelper.printDebug(() -> getClass().getSimpleName() + " Filtered path: " + path);
LogHelper.printDebug(() -> filterSimpleName + " Filtered path: " + path);
}
}
return true;
}
}
/**
* Placeholder for actual filters.
*/
final class DummyFilter extends Filter { }
@RequiresApi(api = Build.VERSION_CODES.N)
@SuppressWarnings("unused")
public final class LithoFilterPatch {
@@ -437,8 +473,10 @@ public final class LithoFilterPatch {
static {
for (Filter filter : filters) {
filterGroupLists(identifierSearchTree, filter, filter.identifierFilterGroupList);
filterGroupLists(pathSearchTree, filter, filter.pathFilterGroupList);
filterUsingCallbacks(identifierSearchTree, filter,
filter.identifierCallbacks, Filter.FilterContentType.IDENTIFIER);
filterUsingCallbacks(pathSearchTree, filter,
filter.pathCallbacks, Filter.FilterContentType.PATH);
}
LogHelper.printDebug(() -> "Using: "
@@ -448,18 +486,19 @@ public final class LithoFilterPatch {
+ " (" + pathSearchTree.getEstimatedMemorySize() + " KB)");
}
private static <T> void filterGroupLists(TrieSearch<T> pathSearchTree,
Filter filter, FilterGroupList<T, ? extends FilterGroup<T>> list) {
for (FilterGroup<T> group : list) {
private static void filterUsingCallbacks(StringTrieSearch pathSearchTree,
Filter filter, List<StringFilterGroup> groups,
Filter.FilterContentType type) {
for (StringFilterGroup group : groups) {
if (!group.includeInSearch()) {
continue;
}
for (T pattern : group.filters) {
for (String pattern : group.filters) {
pathSearchTree.addPattern(pattern, (textSearched, matchedStartIndex, matchedLength, callbackParameter) -> {
if (!group.isEnabled()) return false;
LithoFilterParameters parameters = (LithoFilterParameters) callbackParameter;
return filter.isFiltered(parameters.identifier, parameters.path, parameters.protoBuffer,
list, group, matchedStartIndex);
group, type, matchedStartIndex);
}
);
}

View File

@@ -12,7 +12,7 @@ public final class PlaybackSpeedMenuFilterPatch extends Filter {
public static volatile boolean isPlaybackSpeedMenuVisible;
public PlaybackSpeedMenuFilterPatch() {
pathFilterGroupList.addAll(new StringFilterGroup(
addPathCallbacks(new StringFilterGroup(
null,
"playback_speed_sheet_content.eml-js"
));
@@ -20,7 +20,7 @@ public final class PlaybackSpeedMenuFilterPatch extends Filter {
@Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
isPlaybackSpeedMenuVisible = true;
return false;

View File

@@ -8,65 +8,64 @@ import androidx.annotation.RequiresApi;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.shared.PlayerType;
@SuppressWarnings("unused")
public class PlayerFlyoutMenuItemsFilter extends Filter {
// Search the buffer only if the flyout menu path is found.
// Handle the searching in this class instead of adding to the global filter group (which searches all the time)
private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList();
private final ByteArrayFilterGroup exception;
@RequiresApi(api = Build.VERSION_CODES.N)
public PlayerFlyoutMenuItemsFilter() {
exception = new ByteArrayAsStringFilterGroup(
exception = new ByteArrayFilterGroup(
// Whitelist Quality menu item when "Hide Additional settings menu" is enabled
SettingsEnum.HIDE_ADDITIONAL_SETTINGS_MENU,
"quality_sheet"
);
// Using pathFilterGroupList due to new flyout panel(A/B)
pathFilterGroupList.addAll(
addPathCallbacks(
new StringFilterGroup(null, "overflow_menu_item.eml|")
);
flyoutFilterGroupList.addAll(
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_CAPTIONS_MENU,
"closed_caption"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_ADDITIONAL_SETTINGS_MENU,
"yt_outline_gear"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_LOOP_VIDEO_MENU,
"yt_outline_arrow_repeat_1_"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_AMBIENT_MODE_MENU,
"yt_outline_screen_light"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_REPORT_MENU,
"yt_outline_flag"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_HELP_MENU,
"yt_outline_question_circle"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_MORE_INFO_MENU,
"yt_outline_info_circle"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_SPEED_MENU,
"yt_outline_play_arrow_half_circle"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_AUDIO_TRACK_MENU,
"yt_outline_person_radar"
),
new ByteArrayAsStringFilterGroup(
new ByteArrayFilterGroup(
SettingsEnum.HIDE_WATCH_IN_VR_MENU,
"yt_outline_vr"
)
@@ -75,15 +74,15 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
@Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
// Shorts also use this player flyout panel
if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(protobufBufferArray).isFiltered())
return false;
// Only 1 group is added to the parent class, so the matched group must be the overflow menu.
if (matchedIndex == 0 && flyoutFilterGroupList.check(protobufBufferArray).isFiltered()) {
// Only 1 path callback was added, so the matched group must be the overflow menu.
if (contentIndex == 0 && flyoutFilterGroupList.check(protobufBufferArray).isFiltered()) {
// Super class handles logging.
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
return false;
}

View File

@@ -53,14 +53,14 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
/**
* Injection point.
*/
public static void newPlayerResponseVideoId(String videoId, boolean videoIsOpeningOrPlaying) {
public static void newPlayerResponseVideoId(String videoId, boolean isShortAndOpeningOrPlaying) {
try {
if (!videoIsOpeningOrPlaying || !SettingsEnum.RYD_SHORTS.getBoolean()) {
if (!isShortAndOpeningOrPlaying || !SettingsEnum.RYD_SHORTS.getBoolean()) {
return;
}
synchronized (lastVideoIds) {
if (lastVideoIds.put(videoId, Boolean.TRUE) == null) {
LogHelper.printDebug(() -> "New video id: " + videoId);
LogHelper.printDebug(() -> "New Short video id: " + videoId);
}
}
} catch (Exception ex) {
@@ -71,21 +71,21 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
private final ByteArrayFilterGroupList videoIdFilterGroup = new ByteArrayFilterGroupList();
public ReturnYouTubeDislikeFilterPatch() {
pathFilterGroupList.addAll(
addPathCallbacks(
new StringFilterGroup(SettingsEnum.RYD_SHORTS, "|shorts_dislike_button.eml|")
);
// After the dislikes icon name is some binary data and then the video id for that specific short.
videoIdFilterGroup.addAll(
// Video was previously disliked before video was opened.
new ByteArrayAsStringFilterGroup(null, "ic_right_dislike_on_shadowed"),
new ByteArrayFilterGroup(null, "ic_right_dislike_on_shadowed"),
// Video was not already disliked.
new ByteArrayAsStringFilterGroup(null, "ic_right_dislike_off_shadowed")
new ByteArrayFilterGroup(null, "ic_right_dislike_off_shadowed")
);
}
@Override
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(protobufBufferArray);
if (result.isFiltered()) {
String matchedVideoId = findVideoId(protobufBufferArray);
@@ -112,7 +112,7 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
}
/**
* This could use {@link TrieSearch}, but since the video ids are constantly changing
* This could use {@link TrieSearch}, but since the patterns are constantly changing
* the overhead of updating the Trie might negate the search performance gain.
*/
private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text) {

View File

@@ -10,7 +10,7 @@ import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
import static app.revanced.integrations.utils.ReVancedUtils.hideViewBy1dpUnderCondition;
import static app.revanced.integrations.utils.ReVancedUtils.hideViewUnderCondition;
/** @noinspection unused*/
@SuppressWarnings("unused")
@RequiresApi(api = Build.VERSION_CODES.N)
public final class ShortsFilter extends Filter {
public static PivotBar pivotBar; // Set by patch.
@@ -49,7 +49,7 @@ public final class ShortsFilter extends Filter {
"suggested_action"
);
identifierFilterGroupList.addAll(shorts, shelfHeader, thanksButton);
addIdentifierCallbacks(shorts, shelfHeader, thanksButton);
// Shorts player components.
var joinButton = new StringFilterGroup(
@@ -87,22 +87,22 @@ public final class ShortsFilter extends Filter {
"ContainerType|shorts_video_action_button"
);
pathFilterGroupList.addAll(
addPathCallbacks(
joinButton, subscribeButton, subscribeButtonPaused,
channelBar, soundButton, infoPanel, videoActionButton
);
var shortsCommentButton = new ByteArrayAsStringFilterGroup(
var shortsCommentButton = new ByteArrayFilterGroup(
SettingsEnum.HIDE_SHORTS_COMMENTS_BUTTON,
"reel_comment_button"
);
var shortsShareButton = new ByteArrayAsStringFilterGroup(
var shortsShareButton = new ByteArrayFilterGroup(
SettingsEnum.HIDE_SHORTS_SHARE_BUTTON,
"reel_share_button"
);
var shortsRemixButton = new ByteArrayAsStringFilterGroup(
var shortsRemixButton = new ByteArrayFilterGroup(
SettingsEnum.HIDE_SHORTS_REMIX_BUTTON,
"reel_remix_button"
);
@@ -112,19 +112,19 @@ public final class ShortsFilter extends Filter {
@Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
if (matchedList == pathFilterGroupList) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (contentType == FilterContentType.PATH) {
// Always filter if matched.
if (matchedGroup == soundButton ||
matchedGroup == infoPanel ||
matchedGroup == channelBar ||
matchedGroup == subscribeButtonPaused
) return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
) return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
// Video action buttons (comment, share, remix) have the same path.
if (matchedGroup == videoActionButton) {
if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) return super.isFiltered(
identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex
identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex
);
return false;
}
@@ -133,18 +133,18 @@ public final class ShortsFilter extends Filter {
// to avoid false positives.
if (path.startsWith(REEL_CHANNEL_BAR_PATH))
if (matchedGroup == subscribeButton) return super.isFiltered(
identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex
identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex
);
return false;
} else if (matchedGroup == shelfHeader) {
// Because the header is used in watch history and possibly other places, check for the index,
// which is 0 when the shelf header is used for Shorts.
if (matchedIndex != 0) return false;
if (contentIndex != 0) return false;
}
// Super class handles logging.
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
public static void hideShortsShelf(final View shortsShelfView) {

View File

@@ -9,11 +9,12 @@ import app.revanced.integrations.settings.SettingsEnum;
* Abuse LithoFilter for {@link RestoreOldVideoQualityMenuPatch}.
*/
public final class VideoQualityMenuFilterPatch extends Filter {
// Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread.
// Must be volatile or synchronized, as litho filtering runs off main thread
// and this field is then access from the main thread.
public static volatile boolean isVideoQualityMenuVisible;
public VideoQualityMenuFilterPatch() {
pathFilterGroupList.addAll(new StringFilterGroup(
addPathCallbacks(new StringFilterGroup(
SettingsEnum.RESTORE_OLD_VIDEO_QUALITY_MENU,
"quick_quality_sheet_content.eml-js"
));
@@ -21,7 +22,7 @@ public final class VideoQualityMenuFilterPatch extends Filter {
@Override
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
isVideoQualityMenuVisible = true;
return false;

View File

@@ -15,15 +15,23 @@ import java.util.Arrays;
public class CustomPlaybackSpeedPatch {
/**
* Maximum playback speed, exclusive value. Custom speeds must be less than this value.
* Limit is required otherwise double digit speeds show up out of order in the UI selector.
*
* Going over 8x does not increase the actual playback speed any higher,
* and the UI selector starts flickering and acting weird.
* Over 10x and the speeds show up out of order in the UI selector.
*/
public static final float MAXIMUM_PLAYBACK_SPEED = 10;
public static final float MAXIMUM_PLAYBACK_SPEED = 8;
/**
* Custom playback speeds.
*/
public static float[] customPlaybackSpeeds;
/**
* The last time the old playback menu was forcefully called.
*/
private static long lastTimeOldPlaybackMenuInvoked;
/**
* PreferenceList entries and values, of all available playback speeds.
*/
@@ -35,7 +43,7 @@ public class CustomPlaybackSpeedPatch {
private static void resetCustomSpeeds(@NonNull String toastMessage) {
ReVancedUtils.showToastLong(toastMessage);
SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.saveValue(SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.defaultValue);
SettingsEnum.CUSTOM_PLAYBACK_SPEEDS.resetToDefault();
}
private static void loadCustomSpeeds() {
@@ -101,36 +109,48 @@ public class CustomPlaybackSpeedPatch {
// For some reason, the custom playback speed flyout panel is activated when the user opens the share panel. (A/B tests)
// Check the child count of playback speed flyout panel to prevent this issue.
// Child count of playback speed flyout panel is always 8.
if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible
&& ((ViewGroup) recyclerView.getChildAt(0)).getChildCount() == 8) {
PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false;
ViewGroup parentView3rd = (ViewGroup) recyclerView.getParent().getParent().getParent();
ViewGroup parentView4th = (ViewGroup) parentView3rd.getParent();
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
// This only shows in phone layout.
final var touchInsidedView = parentView4th.getChildAt(0);
touchInsidedView.setSoundEffectsEnabled(false);
touchInsidedView.performClick();
// In tablet layout there is no Dismiss View, instead we just hide all two parent views.
parentView3rd.setVisibility(View.GONE);
parentView4th.setVisibility(View.GONE);
// This works without issues for both tablet and phone layouts,
// So no code is needed to check whether the current device is a tablet or phone.
// Close the new Playback speed menu and show the old one.
showOldPlaybackSpeedMenu();
if (!PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible || recyclerView.getChildCount() == 0) {
return;
}
ViewGroup PlaybackSpeedParentView = (ViewGroup) recyclerView.getChildAt(0);
if (PlaybackSpeedParentView == null || PlaybackSpeedParentView.getChildCount() != 8) {
return;
}
PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false;
ViewGroup parentView3rd = (ViewGroup) recyclerView.getParent().getParent().getParent();
ViewGroup parentView4th = (ViewGroup) parentView3rd.getParent();
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
// This only shows in phone layout.
final var touchInsidedView = parentView4th.getChildAt(0);
touchInsidedView.setSoundEffectsEnabled(false);
touchInsidedView.performClick();
// In tablet layout there is no Dismiss View, instead we just hide all two parent views.
parentView3rd.setVisibility(View.GONE);
parentView4th.setVisibility(View.GONE);
// This works without issues for both tablet and phone layouts,
// So no code is needed to check whether the current device is a tablet or phone.
// Close the new Playback speed menu and show the old one.
showOldPlaybackSpeedMenu();
} catch (Exception ex) {
LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex);
}
});
}
public static void showOldPlaybackSpeedMenu() {
private static void showOldPlaybackSpeedMenu() {
// This method is sometimes used multiple times.
// To prevent this, ignore method reuse within 1 second.
final long now = System.currentTimeMillis();
if (now - lastTimeOldPlaybackMenuInvoked < 1000) {
LogHelper.printDebug(() -> "Ignoring call to showOldPlaybackSpeedMenu");
return;
}
lastTimeOldPlaybackMenuInvoked = now;
LogHelper.printDebug(() -> "Old video quality menu shown");
// Rest of the implementation added by patch.

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