You've already forked revanced-integrations
mirror of
https://github.com/revanced/revanced-integrations
synced 2025-11-19 03:23:27 +01:00
Compare commits
44 Commits
v0.118.0-d
...
v0.119.2-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b25ab1a0d8 | ||
|
|
9b2add7553 | ||
|
|
dceaf7a1ec | ||
|
|
49d9bf80f2 | ||
|
|
8a40ca616e | ||
|
|
1479d6bc26 | ||
|
|
771dd608dc | ||
|
|
92523fe1f7 | ||
|
|
a1477c097c | ||
|
|
486c894257 | ||
|
|
78b5fe2128 | ||
|
|
245c3b3537 | ||
|
|
d4b859d6fb | ||
|
|
4498f39b8c | ||
|
|
176196b52c | ||
|
|
30788ba1a3 | ||
|
|
1d13cf2d5d | ||
|
|
6eb301776e | ||
|
|
ed6571734e | ||
|
|
3ac869fa6a | ||
|
|
d47fd19d0b | ||
|
|
6730aaf2b8 | ||
|
|
1efd5c8315 | ||
|
|
63ddb0b31d | ||
|
|
1a702bce60 | ||
|
|
bedb02e4f6 | ||
|
|
6075c9ed17 | ||
|
|
4215be4250 | ||
|
|
a198ef83dd | ||
|
|
b280de3195 | ||
|
|
3d0fc1d610 | ||
|
|
25f73eb3a9 | ||
|
|
f451d67dcb | ||
|
|
5185673780 | ||
|
|
93a30453d9 | ||
|
|
d156951460 | ||
|
|
9685070eda | ||
|
|
1689bf4125 | ||
|
|
c992289d59 | ||
|
|
e2254681cd | ||
|
|
b87d806659 | ||
|
|
b472aeeed7 | ||
|
|
7dfa0e4653 | ||
|
|
165b061fa9 |
190
CHANGELOG.md
190
CHANGELOG.md
@@ -1,3 +1,193 @@
|
||||
## [0.119.2-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.119.1...v0.119.2-dev.1) (2023-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - ReturnYouTubeDislike:** Fix dislikes not showing on Shorts ([#495](https://github.com/ReVanced/revanced-integrations/issues/495)) ([9b2add7](https://github.com/ReVanced/revanced-integrations/commit/9b2add7553488436c63fa14bd62966dfb92705bf))
|
||||
|
||||
## [0.119.1](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0...v0.119.1) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Do not hide subscribe button outside of Shorts ([1479d6b](https://github.com/ReVanced/revanced-integrations/commit/1479d6bc2668758ea55f9d640684547f710099f0))
|
||||
|
||||
## [0.119.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0...v0.119.1-dev.1) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Do not hide subscribe button outside of Shorts ([1479d6b](https://github.com/ReVanced/revanced-integrations/commit/1479d6bc2668758ea55f9d640684547f710099f0))
|
||||
|
||||
# [0.119.0](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0...v0.119.0) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Add filter to filter group list ([30788ba](https://github.com/ReVanced/revanced-integrations/commit/30788ba1a3e8d666b55a37e9389246e4bfa039cb))
|
||||
* **YouTube - Hide shorts components:** Do not prevent filtering components ([6eb3017](https://github.com/ReVanced/revanced-integrations/commit/6eb301776e202cf1d923f96cc83ddf6f0430b211))
|
||||
* **YouTube - Hide shorts components:** Hide the subscribe button when paused ([6730aaf](https://github.com/ReVanced/revanced-integrations/commit/6730aaf2b864b747a6b77411cdaceee653b36218))
|
||||
* **YouTube - ReturnYouTubeDislike:** Do not retry API call if same fetch recently failed ([#493](https://github.com/ReVanced/revanced-integrations/issues/493)) ([486c894](https://github.com/ReVanced/revanced-integrations/commit/486c894257e91dedc04b38191e0e01e38c66b5c4))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide shorts components:** Hide subscribe button when paused separately from subscribe button ([3ac869f](https://github.com/ReVanced/revanced-integrations/commit/3ac869fa6ae095f074481d98d9a4eea207eda00d))
|
||||
* **YouTube - Return YouTube Dislike:** Support version `18.37.36` ([#490](https://github.com/ReVanced/revanced-integrations/issues/490)) ([245c3b3](https://github.com/ReVanced/revanced-integrations/commit/245c3b35373313d49cc5b1c2fd8e9deebb6258a5))
|
||||
* **YouTube:** Add `Disable fine scrubbing gesture` patch ([4498f39](https://github.com/ReVanced/revanced-integrations/commit/4498f39b8c4900fccdc359d0c687c26db23526c3))
|
||||
|
||||
# [0.119.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0-dev.5...v0.119.0-dev.6) (2023-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - ReturnYouTubeDislike:** Do not retry API call if same fetch recently failed ([#493](https://github.com/ReVanced/revanced-integrations/issues/493)) ([486c894](https://github.com/ReVanced/revanced-integrations/commit/486c894257e91dedc04b38191e0e01e38c66b5c4))
|
||||
|
||||
# [0.119.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0-dev.4...v0.119.0-dev.5) (2023-10-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Return YouTube Dislike:** Support version `18.37.36` ([#490](https://github.com/ReVanced/revanced-integrations/issues/490)) ([245c3b3](https://github.com/ReVanced/revanced-integrations/commit/245c3b35373313d49cc5b1c2fd8e9deebb6258a5))
|
||||
|
||||
# [0.119.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0-dev.3...v0.119.0-dev.4) (2023-10-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Disable fine scrubbing gesture` patch ([4498f39](https://github.com/ReVanced/revanced-integrations/commit/4498f39b8c4900fccdc359d0c687c26db23526c3))
|
||||
|
||||
# [0.119.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0-dev.2...v0.119.0-dev.3) (2023-10-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Add filter to filter group list ([30788ba](https://github.com/ReVanced/revanced-integrations/commit/30788ba1a3e8d666b55a37e9389246e4bfa039cb))
|
||||
|
||||
# [0.119.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.119.0-dev.1...v0.119.0-dev.2) (2023-10-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Do not prevent filtering components ([6eb3017](https://github.com/ReVanced/revanced-integrations/commit/6eb301776e202cf1d923f96cc83ddf6f0430b211))
|
||||
|
||||
# [0.119.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.118.1-dev.1...v0.119.0-dev.1) (2023-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide shorts components:** Hide subscribe button when paused separately from subscribe button ([3ac869f](https://github.com/ReVanced/revanced-integrations/commit/3ac869fa6ae095f074481d98d9a4eea207eda00d))
|
||||
|
||||
## [0.118.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0...v0.118.1-dev.1) (2023-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Hide the subscribe button when paused ([6730aaf](https://github.com/ReVanced/revanced-integrations/commit/6730aaf2b864b747a6b77411cdaceee653b36218))
|
||||
|
||||
# [0.118.0](https://github.com/ReVanced/revanced-integrations/compare/v0.117.1...v0.118.0) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Do not always hide the component ([3d0fc1d](https://github.com/ReVanced/revanced-integrations/commit/3d0fc1d610cdf50bb7cc4687d899e0acbf3fb83e))
|
||||
* Remove parameter from route ([4b0925e](https://github.com/ReVanced/revanced-integrations/commit/4b0925e33762c02e95ef9b1aadcae1038af71a50))
|
||||
* **YouTube - Client spoof:** Display seekbar thumbnails in high quality ([f71c1a0](https://github.com/ReVanced/revanced-integrations/commit/f71c1a0c156b2320e06dd98b3e5b276560d438aa))
|
||||
* **YouTube - Client spoof:** Do not record feed videos to history by default ([#478](https://github.com/ReVanced/revanced-integrations/issues/478)) ([ef1cca0](https://github.com/ReVanced/revanced-integrations/commit/ef1cca02c165d9c24e64b43fae375ae57bf90a52))
|
||||
* **YouTube - Client spoof:** fix occasionally frozen video playback ([#486](https://github.com/ReVanced/revanced-integrations/issues/486)) ([b0b6ff6](https://github.com/ReVanced/revanced-integrations/commit/b0b6ff6a82820d4578c5cfc5f69ae7aaaac49c7f))
|
||||
* **YouTube - Client spoof:** fix storyboard fetched out of order ([#481](https://github.com/ReVanced/revanced-integrations/issues/481)) ([8398774](https://github.com/ReVanced/revanced-integrations/commit/83987747e67541cd44221ede8c4020baba36c7b8))
|
||||
* **YouTube - Client spoof:** Fix toast shown for live streams ([#489](https://github.com/ReVanced/revanced-integrations/issues/489)) ([27f49df](https://github.com/ReVanced/revanced-integrations/commit/27f49dfd1e8fbfd3e28270da91ad437df8a54761))
|
||||
* **YouTube - Client spoof:** fix toast shown if opening paid or age restricted video ([#482](https://github.com/ReVanced/revanced-integrations/issues/482)) ([e72b65b](https://github.com/ReVanced/revanced-integrations/commit/e72b65b599353715a6467463226abc603bc850f7))
|
||||
* **YouTube - Client spoof:** Removed unused code ([#480](https://github.com/ReVanced/revanced-integrations/issues/480)) ([e6903bf](https://github.com/ReVanced/revanced-integrations/commit/e6903bff95b485d21773537bbcc162411b616618))
|
||||
* **YouTube - Client spoof:** Restore clipping videos functionality ([2cd1738](https://github.com/ReVanced/revanced-integrations/commit/2cd1738d2494add13c48b64ccc9aad2432b2d8e3))
|
||||
* **YouTube - Client spoof:** Restore seekbar thumbnails ([978f630](https://github.com/ReVanced/revanced-integrations/commit/978f630c0267ec2b0d9bb9b5b0b3cdc9abef65ec))
|
||||
* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([01019b0](https://github.com/ReVanced/revanced-integrations/commit/01019b09c1c106ed814b994dd8af558a18873c1d))
|
||||
* **YouTube - Custom filter:** Use new lines between components instead of commas ([#475](https://github.com/ReVanced/revanced-integrations/issues/475)) ([17ed396](https://github.com/ReVanced/revanced-integrations/commit/17ed39673954a5b571bc1654be20afc235682ca4))
|
||||
* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#487](https://github.com/ReVanced/revanced-integrations/issues/487)) ([00c4c40](https://github.com/ReVanced/revanced-integrations/commit/00c4c4025bc27495e490fdb231ac803881c9887f))
|
||||
* **YouTube - Hide layout components:** Always hide redundant 'player audio track' button ([#473](https://github.com/ReVanced/revanced-integrations/issues/473)) ([d86851b](https://github.com/ReVanced/revanced-integrations/commit/d86851baf1ef1993f5ba9543a4a3fe8d50c3a199))
|
||||
* **YouTube - Hide layout components:** Do not hide chapters in feed unexpectedly ([bedb02e](https://github.com/ReVanced/revanced-integrations/commit/bedb02e4f6122f3dcdc106648648eec4d6a3cbe5))
|
||||
* **YouTube - Hide shorts components:** Hide subscribe button in paused state ([9685070](https://github.com/ReVanced/revanced-integrations/commit/9685070eda5b448eb33324b4bfabd4c7eae42f9f))
|
||||
* **YouTube - ReturnYouTubeDislike:** Add debug logging to litho text ([#476](https://github.com/ReVanced/revanced-integrations/issues/476)) ([e3b8e8b](https://github.com/ReVanced/revanced-integrations/commit/e3b8e8be41796d0300c8421e28e5b8cf43ffb25e))
|
||||
* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#488](https://github.com/ReVanced/revanced-integrations/issues/488)) ([165b061](https://github.com/ReVanced/revanced-integrations/commit/165b061fa9c5fd48b0dbb9540fd6ea6a9ffaf312))
|
||||
* **YouTube - SponsorBlock:** Adjust import/export UI text ([#491](https://github.com/ReVanced/revanced-integrations/issues/491)) ([4215be4](https://github.com/ReVanced/revanced-integrations/commit/4215be4250d195ecf89b041c96834be56c164f34))
|
||||
* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#484](https://github.com/ReVanced/revanced-integrations/issues/484)) ([da923a3](https://github.com/ReVanced/revanced-integrations/commit/da923a38a06baf8c30d38211e8354be4edb0ad51))
|
||||
* **YouTube:** fix old quality and custom speed not working on tablets ([#477](https://github.com/ReVanced/revanced-integrations/issues/477)) ([2352fa5](https://github.com/ReVanced/revanced-integrations/commit/2352fa542658035c5f4400fb5892217887710e4d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TU Dortmund:** Add `Show on lockscreen` patch ([#472](https://github.com/ReVanced/revanced-integrations/issues/472)) ([526d66f](https://github.com/ReVanced/revanced-integrations/commit/526d66f6a91e0ed907db609a4adaa97f3239898b))
|
||||
* **Twitch - Block embedded ads:** Switch from `ttv.lol` to `luminous.dev` ([2c34180](https://github.com/ReVanced/revanced-integrations/commit/2c3418041cf19ae4c1c7b67eda8398578384b753))
|
||||
* **YouTube - Hide layout components:** Disable hiding search result shelf header by default ([b280de3](https://github.com/ReVanced/revanced-integrations/commit/b280de31957631180f07057cc7e466bd26e2f7fb))
|
||||
* **YouTube - Hide layout components:** Hide "Join" button ([e225468](https://github.com/ReVanced/revanced-integrations/commit/e2254681cd77481376e4c3f8c556db510fdfce6c))
|
||||
* **YouTube - Hide layout components:** Hide "Notify me" button ([b87d806](https://github.com/ReVanced/revanced-integrations/commit/b87d8066597a2c989480de47561007844964a0e4))
|
||||
* **YouTube - Hide layout components:** Hide search result shelf header ([93a3045](https://github.com/ReVanced/revanced-integrations/commit/93a30453d9693e015b1f58a12f85cf355770a4ca))
|
||||
* **YouTube - Hide layout components:** Hide timed reactions ([b472aee](https://github.com/ReVanced/revanced-integrations/commit/b472aeeed7904f6b6d537dfbddda1a97c7ddcd5e))
|
||||
* **YouTube:** Add `Bypass URL redirects` patch ([9109653](https://github.com/ReVanced/revanced-integrations/commit/91096532eedf396920d69932638f667cbf850cbe))
|
||||
* **YouTube:** Bump compatibility to `18.37.36` ([#483](https://github.com/ReVanced/revanced-integrations/issues/483)) ([5dadb0d](https://github.com/ReVanced/revanced-integrations/commit/5dadb0d523f2b1eb4216d43770af37a156c8a477))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Only request required fields ([d20b768](https://github.com/ReVanced/revanced-integrations/commit/d20b768bc23d167d9f0d2c651c75b3f92944e731))
|
||||
* Remove unnecessary api key parameter ([ba5e7d8](https://github.com/ReVanced/revanced-integrations/commit/ba5e7d870ee88ad45c233d914e1e2795de920cb2))
|
||||
|
||||
# [0.118.0-dev.24](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.23...v0.118.0-dev.24) (2023-10-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Do not hide chapters in feed unexpectedly ([bedb02e](https://github.com/ReVanced/revanced-integrations/commit/bedb02e4f6122f3dcdc106648648eec4d6a3cbe5))
|
||||
|
||||
# [0.118.0-dev.23](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.22...v0.118.0-dev.23) (2023-10-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Adjust import/export UI text ([#491](https://github.com/ReVanced/revanced-integrations/issues/491)) ([4215be4](https://github.com/ReVanced/revanced-integrations/commit/4215be4250d195ecf89b041c96834be56c164f34))
|
||||
|
||||
# [0.118.0-dev.22](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.21...v0.118.0-dev.22) (2023-10-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Do not always hide the component ([3d0fc1d](https://github.com/ReVanced/revanced-integrations/commit/3d0fc1d610cdf50bb7cc4687d899e0acbf3fb83e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Disable hiding search result shelf header by default ([b280de3](https://github.com/ReVanced/revanced-integrations/commit/b280de31957631180f07057cc7e466bd26e2f7fb))
|
||||
|
||||
# [0.118.0-dev.21](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.20...v0.118.0-dev.21) (2023-10-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Hide search result shelf header ([93a3045](https://github.com/ReVanced/revanced-integrations/commit/93a30453d9693e015b1f58a12f85cf355770a4ca))
|
||||
|
||||
# [0.118.0-dev.20](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.19...v0.118.0-dev.20) (2023-10-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide shorts components:** Hide subscribe button in paused state ([9685070](https://github.com/ReVanced/revanced-integrations/commit/9685070eda5b448eb33324b4bfabd4c7eae42f9f))
|
||||
|
||||
# [0.118.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.18...v0.118.0-dev.19) (2023-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Hide "Join" button ([e225468](https://github.com/ReVanced/revanced-integrations/commit/e2254681cd77481376e4c3f8c556db510fdfce6c))
|
||||
* **YouTube - Hide layout components:** Hide "Notify me" button ([b87d806](https://github.com/ReVanced/revanced-integrations/commit/b87d8066597a2c989480de47561007844964a0e4))
|
||||
* **YouTube - Hide layout components:** Hide timed reactions ([b472aee](https://github.com/ReVanced/revanced-integrations/commit/b472aeeed7904f6b6d537dfbddda1a97c7ddcd5e))
|
||||
|
||||
# [0.118.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.17...v0.118.0-dev.18) (2023-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#488](https://github.com/ReVanced/revanced-integrations/issues/488)) ([165b061](https://github.com/ReVanced/revanced-integrations/commit/165b061fa9c5fd48b0dbb9540fd6ea6a9ffaf312))
|
||||
|
||||
# [0.118.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.16...v0.118.0-dev.17) (2023-09-28)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public final class DisableFineScrubbingGesturePatch {
|
||||
/**
|
||||
* Disables the fine scrubbing gesture.
|
||||
* @param tracker The velocity tracker that is used to determine the gesture.
|
||||
* @param event The motion event that is used to determine the gesture.
|
||||
*/
|
||||
public static void disableGesture(VelocityTracker tracker, MotionEvent event) {
|
||||
if (SettingsEnum.DISABLE_FINE_SCRUBBING_GESTURE.getBoolean()) return;
|
||||
|
||||
tracker.addMovement(event);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,14 +19,17 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
SettingsEnum.HIDE_MIX_PLAYLISTS,
|
||||
"&list="
|
||||
);
|
||||
private final StringFilterGroup searchResultShelfHeader;
|
||||
private final StringFilterGroup inFeedSurvey;
|
||||
private final StringFilterGroup notifyMe;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public LayoutComponentsFilter() {
|
||||
exceptions.addPatterns(
|
||||
"home_video_with_context",
|
||||
"related_video_with_context",
|
||||
"comment_thread", // skip filtering anything in the comments
|
||||
"|comment.", // skip filtering anything in the comments replies
|
||||
"comment_thread", // Whitelist comments
|
||||
"|comment.", // Whitelist comment replies
|
||||
"library_recent_shelf"
|
||||
);
|
||||
|
||||
@@ -61,7 +64,7 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"compact_banner"
|
||||
);
|
||||
|
||||
final var inFeedSurvey = new StringFilterGroup(
|
||||
inFeedSurvey = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_FEED_SURVEY,
|
||||
"in_feed_survey",
|
||||
"slimline_survey"
|
||||
@@ -146,6 +149,27 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"cell_divider" // layout residue (gray line above the buttoned ad),
|
||||
);
|
||||
|
||||
final var timedReactions = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_TIMED_REACTIONS,
|
||||
"emoji_control_panel",
|
||||
"timed_reaction"
|
||||
);
|
||||
|
||||
searchResultShelfHeader = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SEARCH_RESULT_SHELF_HEADER,
|
||||
"shelf_header.eml"
|
||||
);
|
||||
|
||||
notifyMe = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_NOTIFY_ME_BUTTON,
|
||||
"set_reminder_button"
|
||||
);
|
||||
|
||||
final var joinMembership = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_JOIN_MEMBERSHIP_BUTTON,
|
||||
"compact_sponsor_button"
|
||||
);
|
||||
|
||||
final var chipsShelf = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_CHIPS_SHELF,
|
||||
"chips_shelf"
|
||||
@@ -156,36 +180,45 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
communityPosts,
|
||||
paidContent,
|
||||
latestPosts,
|
||||
chapters,
|
||||
communityGuidelines,
|
||||
quickActions,
|
||||
expandableMetadata,
|
||||
relatedVideos,
|
||||
compactBanner,
|
||||
inFeedSurvey,
|
||||
joinMembership,
|
||||
medicalPanel,
|
||||
notifyMe,
|
||||
infoPanel,
|
||||
subscribersCommunityGuidelines,
|
||||
channelGuidelines,
|
||||
audioTrackButton,
|
||||
artistCard,
|
||||
timedReactions,
|
||||
imageShelf,
|
||||
subscribersCommunityGuidelines,
|
||||
channelMemberShelf,
|
||||
custom
|
||||
);
|
||||
|
||||
this.identifierFilterGroupList.addAll(
|
||||
graySeparator,
|
||||
chipsShelf
|
||||
chipsShelf,
|
||||
chapters
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
|
||||
|
||||
if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey) return true;
|
||||
|
||||
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;
|
||||
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.*;
|
||||
|
||||
@@ -13,12 +14,24 @@ import java.util.function.Consumer;
|
||||
|
||||
abstract class FilterGroup<T> {
|
||||
final static class FilterGroupResult {
|
||||
SettingsEnum setting;
|
||||
boolean filtered;
|
||||
private SettingsEnum setting;
|
||||
private int matchedIndex;
|
||||
private int matchedLength;
|
||||
// In the future it might be useful to include which pattern matched,
|
||||
// but for now that is not needed.
|
||||
|
||||
FilterGroupResult(SettingsEnum setting, boolean filtered) {
|
||||
FilterGroupResult() {
|
||||
this(null, -1, 0);
|
||||
}
|
||||
|
||||
FilterGroupResult(SettingsEnum setting, int matchedIndex, int matchedLength) {
|
||||
setValues(setting, matchedIndex, matchedLength);
|
||||
}
|
||||
|
||||
public void setValues(SettingsEnum setting, int matchedIndex, int matchedLength) {
|
||||
this.setting = setting;
|
||||
this.filtered = filtered;
|
||||
this.matchedIndex = matchedIndex;
|
||||
this.matchedLength = matchedLength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,7 +43,21 @@ abstract class FilterGroup<T> {
|
||||
}
|
||||
|
||||
public boolean isFiltered() {
|
||||
return filtered;
|
||||
return matchedIndex >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matched index of first pattern that matched, or -1 if nothing matched.
|
||||
*/
|
||||
public int getMatchedIndex() {
|
||||
return matchedIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of the matched filter pattern.
|
||||
*/
|
||||
public int getMatchedLength() {
|
||||
return matchedLength;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +108,21 @@ class StringFilterGroup extends FilterGroup<String> {
|
||||
|
||||
@Override
|
||||
public FilterGroupResult check(final String string) {
|
||||
return new FilterGroupResult(setting, isEnabled() && ReVancedUtils.containsAny(string, filters));
|
||||
int matchedIndex = -1;
|
||||
int matchedLength = 0;
|
||||
if (isEnabled()) {
|
||||
for (String pattern : filters) {
|
||||
if (!string.isEmpty()) {
|
||||
final int indexOf = pattern.indexOf(string);
|
||||
if (indexOf >= 0) {
|
||||
matchedIndex = indexOf;
|
||||
matchedLength = pattern.length();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new FilterGroupResult(setting, matchedIndex, matchedLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,19 +196,22 @@ class ByteArrayFilterGroup extends FilterGroup<byte[]> {
|
||||
|
||||
@Override
|
||||
public FilterGroupResult check(final byte[] bytes) {
|
||||
var matched = false;
|
||||
int matchedLength = 0;
|
||||
int matchedIndex = -1;
|
||||
if (isEnabled()) {
|
||||
if (failurePatterns == null) {
|
||||
buildFailurePatterns(); // Lazy load.
|
||||
}
|
||||
for (int i = 0, length = filters.length; i < length; i++) {
|
||||
if (indexOf(bytes, filters[i], failurePatterns[i]) >= 0) {
|
||||
matched = true;
|
||||
byte[] filter = filters[i];
|
||||
matchedIndex = indexOf(bytes, filter, failurePatterns[i]);
|
||||
if (matchedIndex >= 0) {
|
||||
matchedLength = filter.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new FilterGroupResult(setting, matched);
|
||||
return new FilterGroupResult(setting, matchedIndex, matchedLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,11 +248,10 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
|
||||
continue;
|
||||
}
|
||||
for (V pattern : group.filters) {
|
||||
search.addPattern(pattern, (textSearched, matchedStartIndex, callbackParameter) -> {
|
||||
search.addPattern(pattern, (textSearched, matchedStartIndex, matchedLength, callbackParameter) -> {
|
||||
if (group.isEnabled()) {
|
||||
FilterGroup.FilterGroupResult result = (FilterGroup.FilterGroupResult) callbackParameter;
|
||||
result.setting = group.setting;
|
||||
result.filtered = true;
|
||||
result.setValues(group.setting, matchedStartIndex, matchedLength);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -241,9 +284,10 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
|
||||
if (search == null) {
|
||||
buildSearch(); // Lazy load.
|
||||
}
|
||||
FilterGroup.FilterGroupResult result = new FilterGroup.FilterGroupResult(null, false);
|
||||
FilterGroup.FilterGroupResult result = new FilterGroup.FilterGroupResult();
|
||||
search.matches(stack, result);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
protected abstract TrieSearch<V> createSearchGraph();
|
||||
@@ -399,7 +443,7 @@ public final class LithoFilterPatch {
|
||||
continue;
|
||||
}
|
||||
for (T pattern : group.filters) {
|
||||
pathSearchTree.addPattern(pattern, (textSearched, matchedStartIndex, callbackParameter) -> {
|
||||
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,
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package app.revanced.integrations.patches.components;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.integrations.patches.ReturnYouTubeDislikePatch;
|
||||
import app.revanced.integrations.patches.VideoInformation;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.TrieSearch;
|
||||
|
||||
/**
|
||||
* Searches for video id's in the proto buffer of Shorts dislike.
|
||||
*
|
||||
* Because multiple litho dislike spans are created in the background
|
||||
* (and also anytime litho refreshes the components, which is somewhat arbitrary),
|
||||
* that makes the value of {@link VideoInformation#getVideoId()} and {@link VideoInformation#getPlayerResponseVideoId()}
|
||||
* unreliable to determine which video id a Shorts litho span belongs to.
|
||||
*
|
||||
* But the correct video id does appear in the protobuffer just before a Shorts litho span is created.
|
||||
*
|
||||
* Once a way to asynchronously update litho text is found, this strategy will no longer be needed.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
||||
|
||||
/**
|
||||
* Last unique video id's loaded. Value is ignored and Map is treated as a Set.
|
||||
* Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry().
|
||||
*/
|
||||
@GuardedBy("itself")
|
||||
private static final Map<String, Boolean> lastVideoIds = new LinkedHashMap<>() {
|
||||
/**
|
||||
* Number of video id's to keep track of for searching thru the buffer.
|
||||
* A minimum value of 3 should be sufficient, but check a few more just in case.
|
||||
*/
|
||||
private static final int NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK = 5;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry eldest) {
|
||||
return size() > NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void newPlayerResponseVideoId(String videoId) {
|
||||
try {
|
||||
if (!SettingsEnum.RYD_SHORTS.getBoolean()) {
|
||||
return;
|
||||
}
|
||||
synchronized (lastVideoIds) {
|
||||
if (lastVideoIds.put(videoId, Boolean.TRUE) == null) {
|
||||
LogHelper.printDebug(() -> "New video id: " + videoId);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "newPlayerResponseVideoId failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private final ByteArrayFilterGroupList videoIdFilterGroup = new ByteArrayFilterGroupList();
|
||||
|
||||
public ReturnYouTubeDislikeFilterPatch() {
|
||||
pathFilterGroupList.addAll(
|
||||
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"),
|
||||
// Video was not already disliked.
|
||||
new ByteArrayAsStringFilterGroup(null, "ic_right_dislike_off_shadowed")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
|
||||
FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(protobufBufferArray);
|
||||
if (result.isFiltered()) {
|
||||
String matchedVideoId = findVideoId(protobufBufferArray);
|
||||
// Matched video will be null if in incognito mode.
|
||||
// Must pass a null id to correctly clear out the current video data.
|
||||
// Otherwise if a Short is opened in non-incognito, then incognito is enabled and another Short is opened,
|
||||
// the new incognito Short will show the old prior data.
|
||||
ReturnYouTubeDislikePatch.newVideoLoaded(matchedVideoId, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String findVideoId(byte[] protobufBufferArray) {
|
||||
synchronized (lastVideoIds) {
|
||||
for (String videoId : lastVideoIds.keySet()) {
|
||||
if (byteArrayContainsString(protobufBufferArray, videoId)) {
|
||||
return videoId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This could use {@link TrieSearch}, but since the video ids 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) {
|
||||
for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) {
|
||||
boolean found = true;
|
||||
for (int j = 0, textLength = text.length(); j < textLength; j++) {
|
||||
if (array[i + j] != (byte) text.charAt(j)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,15 @@ 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*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public final class ShortsFilter extends Filter {
|
||||
public static PivotBar pivotBar; // Set by patch.
|
||||
private final String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml";
|
||||
|
||||
private final StringFilterGroup channelBar;
|
||||
private final StringFilterGroup subscribeButton;
|
||||
private final StringFilterGroup subscribeButtonPaused;
|
||||
private final StringFilterGroup soundButton;
|
||||
private final StringFilterGroup infoPanel;
|
||||
private final StringFilterGroup shelfHeader;
|
||||
@@ -53,15 +56,22 @@ public final class ShortsFilter extends Filter {
|
||||
SettingsEnum.HIDE_SHORTS_JOIN_BUTTON,
|
||||
"sponsor_button"
|
||||
);
|
||||
var subscribeButton = new StringFilterGroup(
|
||||
|
||||
subscribeButton = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_SUBSCRIBE_BUTTON,
|
||||
"subscribe_button"
|
||||
);
|
||||
|
||||
subscribeButtonPaused = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_SUBSCRIBE_BUTTON_PAUSED,
|
||||
"shorts_paused_state"
|
||||
);
|
||||
|
||||
channelBar = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_CHANNEL_BAR,
|
||||
REEL_CHANNEL_BAR_PATH
|
||||
);
|
||||
|
||||
soundButton = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_SOUND_BUTTON,
|
||||
"reel_pivot_button"
|
||||
@@ -78,7 +88,8 @@ public final class ShortsFilter extends Filter {
|
||||
);
|
||||
|
||||
pathFilterGroupList.addAll(
|
||||
joinButton, subscribeButton, channelBar, soundButton, infoPanel, videoActionButton
|
||||
joinButton, subscribeButton, subscribeButtonPaused,
|
||||
channelBar, soundButton, infoPanel, videoActionButton
|
||||
);
|
||||
|
||||
var shortsCommentButton = new ByteArrayAsStringFilterGroup(
|
||||
@@ -104,20 +115,28 @@ public final class ShortsFilter extends Filter {
|
||||
FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) {
|
||||
if (matchedList == pathFilterGroupList) {
|
||||
// Always filter if matched.
|
||||
if (matchedGroup == soundButton || matchedGroup == infoPanel || matchedGroup == channelBar)
|
||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
|
||||
if (matchedGroup == soundButton ||
|
||||
matchedGroup == infoPanel ||
|
||||
matchedGroup == channelBar ||
|
||||
matchedGroup == subscribeButtonPaused
|
||||
) return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex);
|
||||
|
||||
// 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);
|
||||
if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) return super.isFiltered(
|
||||
identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filter other path groups from pathFilterGroupList, only when reelChannelBar is visible
|
||||
// to avoid false positives.
|
||||
if (!path.startsWith(REEL_CHANNEL_BAR_PATH))
|
||||
return false;
|
||||
if (path.startsWith(REEL_CHANNEL_BAR_PATH))
|
||||
if (matchedGroup == subscribeButton) return super.isFiltered(
|
||||
identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex
|
||||
);
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.integrations.patches;
|
||||
package app.revanced.integrations.patches.spoof;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,6 @@ import androidx.annotation.NonNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
|
||||
/**
|
||||
* ReturnYouTubeDislike API estimated like/dislike/view counts.
|
||||
*
|
||||
@@ -81,17 +79,21 @@ public final class RYDVoteData {
|
||||
}
|
||||
|
||||
public void updateUsingVote(Vote vote) {
|
||||
if (vote == Vote.LIKE) {
|
||||
likeCount = fetchedLikeCount + 1;
|
||||
dislikeCount = fetchedDislikeCount;
|
||||
} else if (vote == Vote.DISLIKE) {
|
||||
likeCount = fetchedLikeCount;
|
||||
dislikeCount = fetchedDislikeCount + 1;
|
||||
} else if (vote == Vote.LIKE_REMOVE) {
|
||||
likeCount = fetchedLikeCount;
|
||||
dislikeCount = fetchedDislikeCount;
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
switch (vote) {
|
||||
case LIKE:
|
||||
likeCount = fetchedLikeCount + 1;
|
||||
dislikeCount = fetchedDislikeCount;
|
||||
break;
|
||||
case DISLIKE:
|
||||
likeCount = fetchedLikeCount;
|
||||
dislikeCount = fetchedDislikeCount + 1;
|
||||
break;
|
||||
case LIKE_REMOVE:
|
||||
likeCount = fetchedLikeCount;
|
||||
dislikeCount = fetchedDislikeCount;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
updatePercentages();
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ public class ReturnYouTubeDislikeApi {
|
||||
private static final int API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS = 2000;
|
||||
|
||||
/**
|
||||
* {@link #fetchVotes(String)} HTTP read timeout
|
||||
* To locally debug and force timeouts, change this to a very small number (ie: 100)
|
||||
* {@link #fetchVotes(String)} HTTP read timeout.
|
||||
* To locally debug and force timeouts, change this to a very small number (ie: 100)
|
||||
*/
|
||||
private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 4000;
|
||||
private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 5000;
|
||||
|
||||
/**
|
||||
* Default connection and response timeout for voting and registration.
|
||||
@@ -391,13 +391,37 @@ public class ReturnYouTubeDislikeApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean sendVote(String videoId, String userId, ReturnYouTubeDislike.Vote vote) {
|
||||
/**
|
||||
* Must call off main thread, as this will make a network call if user is not yet registered.
|
||||
*
|
||||
* @return ReturnYouTubeDislike user ID. If user registration has never happened
|
||||
* and the network call fails, this returns NULL.
|
||||
*/
|
||||
@Nullable
|
||||
private static String getUserId() {
|
||||
ReVancedUtils.verifyOffMainThread();
|
||||
|
||||
String userId = SettingsEnum.RYD_USER_ID.getString();
|
||||
if (!userId.isEmpty()) {
|
||||
return userId;
|
||||
}
|
||||
|
||||
userId = registerAsNewUser();
|
||||
if (userId != null) {
|
||||
SettingsEnum.RYD_USER_ID.saveValue(userId);
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
public static boolean sendVote(String videoId, ReturnYouTubeDislike.Vote vote) {
|
||||
ReVancedUtils.verifyOffMainThread();
|
||||
Objects.requireNonNull(videoId);
|
||||
Objects.requireNonNull(userId);
|
||||
Objects.requireNonNull(vote);
|
||||
|
||||
try {
|
||||
String userId = getUserId();
|
||||
if (userId == null) return false;
|
||||
|
||||
if (checkIfRateLimitInEffect("sendVote")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@ public enum SettingsEnum {
|
||||
HIDE_EMERGENCY_BOX("revanced_hide_emergency_box", BOOLEAN, TRUE),
|
||||
HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE),
|
||||
HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE),
|
||||
HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE),
|
||||
HIDE_SEARCH_RESULT_SHELF_HEADER("revanced_hide_search_result_shelf_header", BOOLEAN, FALSE),
|
||||
HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE),
|
||||
HIDE_JOIN_MEMBERSHIP_BUTTON("revanced_hide_join_membership_button", BOOLEAN, TRUE),
|
||||
HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE),
|
||||
HIDE_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE),
|
||||
HIDE_HIDE_INFO_PANELS("revanced_hide_info_panels", BOOLEAN, TRUE),
|
||||
@@ -132,7 +136,8 @@ public enum SettingsEnum {
|
||||
HIDE_FILTER_BAR_FEED_IN_SEARCH("revanced_hide_filter_bar_feed_in_search", BOOLEAN, FALSE, true),
|
||||
HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS("revanced_hide_filter_bar_feed_in_related_videos", BOOLEAN, FALSE, true),
|
||||
HIDE_SHORTS_JOIN_BUTTON("revanced_hide_shorts_join_button", BOOLEAN, TRUE),
|
||||
HIDE_SHORTS_SUBSCRIBE_BUTTON("revanced_hide_shorts_subscribe_button", BOOLEAN, FALSE),
|
||||
HIDE_SHORTS_SUBSCRIBE_BUTTON("revanced_hide_shorts_subscribe_button", BOOLEAN, TRUE),
|
||||
HIDE_SHORTS_SUBSCRIBE_BUTTON_PAUSED("revanced_hide_shorts_subscribe_button_paused", BOOLEAN, FALSE),
|
||||
HIDE_SHORTS_THANKS_BUTTON("revanced_hide_shorts_thanks_button", BOOLEAN, TRUE),
|
||||
HIDE_SHORTS_COMMENTS_BUTTON("revanced_hide_shorts_comments_button", BOOLEAN, FALSE),
|
||||
HIDE_SHORTS_REMIX_BUTTON("revanced_hide_shorts_remix_button", BOOLEAN, TRUE),
|
||||
@@ -165,6 +170,7 @@ public enum SettingsEnum {
|
||||
EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true),
|
||||
AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE),
|
||||
SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE),
|
||||
DISABLE_FINE_SCRUBBING_GESTURE("revanced_disable_fine_scrubbing_gesture", BOOLEAN, TRUE),
|
||||
SPOOF_SIGNATURE("revanced_spoof_signature_verification_enabled", BOOLEAN, TRUE, true,
|
||||
"revanced_spoof_signature_verification_enabled_user_dialog_message"),
|
||||
SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false,
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.SwitchPreference;
|
||||
|
||||
import app.revanced.integrations.patches.ReturnYouTubeDislikePatch;
|
||||
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
||||
import app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
@@ -19,6 +20,10 @@ import app.revanced.integrations.settings.SharedPrefCategory;
|
||||
|
||||
public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
|
||||
private static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER =
|
||||
SettingsEnum.SPOOF_APP_VERSION.getBoolean()
|
||||
&& SettingsEnum.SPOOF_APP_VERSION_TARGET.getString().compareTo("18.33.40") <= 0;
|
||||
|
||||
/**
|
||||
* If dislikes are shown on Shorts.
|
||||
*/
|
||||
@@ -63,7 +68,7 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
final boolean rydIsEnabled = (Boolean) newValue;
|
||||
SettingsEnum.RYD_ENABLED.saveValue(rydIsEnabled);
|
||||
ReturnYouTubeDislike.onEnabledChange(rydIsEnabled);
|
||||
ReturnYouTubeDislikePatch.onRYDStatusChange(rydIsEnabled);
|
||||
|
||||
updateUIState();
|
||||
return true;
|
||||
@@ -73,7 +78,11 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
shortsPreference = new SwitchPreference(context);
|
||||
shortsPreference.setChecked(SettingsEnum.RYD_SHORTS.getBoolean());
|
||||
shortsPreference.setTitle(str("revanced_ryd_shorts_title"));
|
||||
shortsPreference.setSummaryOn(str("revanced_ryd_shorts_summary_on"));
|
||||
String shortsSummary = str("revanced_ryd_shorts_summary_on",
|
||||
IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER
|
||||
? ""
|
||||
: "\n\n" + str("revanced_ryd_shorts_summary_disclaimer"));
|
||||
shortsPreference.setSummaryOn(shortsSummary);
|
||||
shortsPreference.setSummaryOff(str("revanced_ryd_shorts_summary_off"));
|
||||
shortsPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
SettingsEnum.RYD_SHORTS.saveValue(newValue);
|
||||
@@ -89,7 +98,7 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
percentagePreference.setSummaryOff(str("revanced_ryd_dislike_percentage_summary_off"));
|
||||
percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
SettingsEnum.RYD_DISLIKE_PERCENTAGE.saveValue(newValue);
|
||||
ReturnYouTubeDislike.clearCache();
|
||||
ReturnYouTubeDislike.clearAllUICaches();
|
||||
updateUIState();
|
||||
return true;
|
||||
});
|
||||
@@ -102,7 +111,7 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
compactLayoutPreference.setSummaryOff(str("revanced_ryd_compact_layout_summary_off"));
|
||||
compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
SettingsEnum.RYD_COMPACT_LAYOUT.saveValue(newValue);
|
||||
ReturnYouTubeDislike.clearCache();
|
||||
ReturnYouTubeDislike.clearAllUICaches();
|
||||
updateUIState();
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
|
||||
} else if (!SettingsEnum.SB_CREATE_NEW_SEGMENT.getBoolean()) {
|
||||
SponsorBlockViewController.hideNewSegmentLayout();
|
||||
}
|
||||
// voting and add new segment buttons automatically shows/hides themselves
|
||||
// Voting and add new segment buttons automatically shows/hide themselves.
|
||||
|
||||
sbEnabled.setChecked(enabled);
|
||||
|
||||
@@ -109,6 +109,12 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
|
||||
privateUserId.setText(SettingsEnum.SB_PRIVATE_USER_ID.getString());
|
||||
privateUserId.setEnabled(enabled);
|
||||
|
||||
// If the user has a private user id, then include a subtext that mentions not to share it.
|
||||
String exportSummarySubText = SponsorBlockSettings.userHasSBPrivateId()
|
||||
? str("sb_settings_ie_sum_warning")
|
||||
: "";
|
||||
importExport.setSummary(str("sb_settings_ie_sum", exportSummarySubText));
|
||||
|
||||
apiUrl.setEnabled(enabled);
|
||||
importExport.setEnabled(enabled);
|
||||
segmentCategory.setEnabled(enabled);
|
||||
@@ -329,6 +335,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
|
||||
return false;
|
||||
}
|
||||
SettingsEnum.SB_PRIVATE_USER_ID.saveValue(newUUID);
|
||||
updateUI();
|
||||
fetchAndDisplayStats();
|
||||
return true;
|
||||
});
|
||||
@@ -375,7 +382,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
|
||||
}
|
||||
};
|
||||
importExport.setTitle(str("sb_settings_ie"));
|
||||
importExport.setSummary(str("sb_settings_ie_sum"));
|
||||
// Summary is set in updateUI()
|
||||
importExport.getEditText().setInputType(InputType.TYPE_CLASS_TEXT
|
||||
| InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
||||
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
|
||||
@@ -17,6 +17,8 @@ enum class PlayerType {
|
||||
*/
|
||||
HIDDEN,
|
||||
/**
|
||||
* A regular video is minimized.
|
||||
*
|
||||
* When spoofing to 16.x YouTube and watching a short with a regular video in the background,
|
||||
* the type can be this (and not [HIDDEN]).
|
||||
*/
|
||||
@@ -26,7 +28,9 @@ enum class PlayerType {
|
||||
WATCH_WHILE_SLIDING_MAXIMIZED_FULLSCREEN,
|
||||
WATCH_WHILE_SLIDING_MINIMIZED_MAXIMIZED,
|
||||
/**
|
||||
* When opening a short while a regular video is minimized, the type can momentarily be this.
|
||||
* Player is either sliding to [HIDDEN] state because a Short was opened while a regular video is on screen.
|
||||
* OR
|
||||
* The user has swiped a minimized player away to be closed (and no Short is being opened).
|
||||
*/
|
||||
WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED,
|
||||
WATCH_WHILE_SLIDING_FULLSCREEN_DISMISSED,
|
||||
@@ -84,20 +88,38 @@ enum class PlayerType {
|
||||
return this == NONE || this == HIDDEN
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current player type is
|
||||
* [NONE], [HIDDEN], [WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED].
|
||||
*
|
||||
* Useful to check if a Short is being played or opened.
|
||||
*
|
||||
* Usually covers all use cases with no false positives, except if called from some hooks
|
||||
* when spoofing to an old version this will return false even
|
||||
* though a Short is being opened or is on screen (see [isNoneHiddenOrMinimized]).
|
||||
*
|
||||
* @return If nothing, a Short, or a regular video is sliding off screen to a dismissed or hidden state.
|
||||
*/
|
||||
fun isNoneHiddenOrSlidingMinimized(): Boolean {
|
||||
return isNoneOrHidden() || this == WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current player type is
|
||||
* [NONE], [HIDDEN], [WATCH_WHILE_MINIMIZED], [WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED].
|
||||
*
|
||||
* Useful to check if a Short is being played,
|
||||
* although will return false positive if a regular video is opened and minimized (and no short is playing).
|
||||
* although will return false positive if a regular video is
|
||||
* opened and minimized (and a Short is not playing or being opened).
|
||||
*
|
||||
* @return If nothing, a Short,
|
||||
* or a regular video is minimized video or sliding off screen to a dismissed or hidden state.
|
||||
* Typically used to detect if a Short is playing when the player cannot be in a minimized state,
|
||||
* such as the user interacting with a button or element of the player.
|
||||
*
|
||||
* @return If nothing, a Short, a regular video is sliding off screen to a dismissed or hidden state,
|
||||
* a regular video is minimized (and a new video is not being opened).
|
||||
*/
|
||||
fun isNoneHiddenOrMinimized(): Boolean {
|
||||
return this == NONE || this == HIDDEN
|
||||
|| this == WATCH_WHILE_MINIMIZED
|
||||
|| this == WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED
|
||||
return isNoneHiddenOrSlidingMinimized() || this == WATCH_WHILE_MINIMIZED
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,25 +10,15 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import android.widget.*;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
import java.text.Bidi;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class ReVancedUtils {
|
||||
|
||||
@@ -93,9 +83,17 @@ public class ReVancedUtils {
|
||||
}
|
||||
|
||||
public static boolean containsAny(@NonNull String value, @NonNull String... targets) {
|
||||
for (String string : targets)
|
||||
if (!string.isEmpty() && value.contains(string)) return true;
|
||||
return false;
|
||||
return indexOfFirstFound(value, targets) >= 0;
|
||||
}
|
||||
|
||||
public static int indexOfFirstFound(@NonNull String value, @NonNull String... targets) {
|
||||
for (String string : targets) {
|
||||
if (!string.isEmpty()) {
|
||||
final int indexOf = value.indexOf(string);
|
||||
if (indexOf >= 0) return indexOf;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,11 +23,12 @@ public abstract class TrieSearch<T> {
|
||||
*
|
||||
* @param textSearched Text that was searched.
|
||||
* @param matchedStartIndex Start index of the search text, where the pattern was matched.
|
||||
* @param matchedLength Length of the match.
|
||||
* @param callbackParameter Optional parameter passed into {@link TrieSearch#matches(Object, Object)}.
|
||||
* @return True, if the search should stop here.
|
||||
* If false, searching will continue to look for other matches.
|
||||
*/
|
||||
boolean patternMatched(T textSearched, int matchedStartIndex, Object callbackParameter);
|
||||
boolean patternMatched(T textSearched, int matchedStartIndex, int matchedLength, Object callbackParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +65,8 @@ public abstract class TrieSearch<T> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return callback == null
|
||||
|| callback.patternMatched(searchText, searchTextIndex - patternStartIndex, callbackParameter);
|
||||
return callback == null || callback.patternMatched(searchText,
|
||||
searchTextIndex - patternStartIndex, patternLength, callbackParameter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +162,7 @@ public abstract class TrieSearch<T> {
|
||||
if (callback == null) {
|
||||
return true; // No callback and all matches are valid.
|
||||
}
|
||||
if (callback.patternMatched(searchText, matchStartIndex, callbackParameter)) {
|
||||
if (callback.patternMatched(searchText, matchStartIndex, currentMatchLength, callbackParameter)) {
|
||||
return true; // Callback confirmed the match.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package app.revanced.tumblr.patches;
|
||||
|
||||
import com.tumblr.rumblr.model.TimelineObject;
|
||||
import com.tumblr.rumblr.model.Timelineable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public final class TimelineFilterPatch {
|
||||
private static final HashSet<String> blockedObjectTypes = new HashSet<>();
|
||||
|
||||
static {
|
||||
// This dummy gets removed by the TimelineFilterPatch and in its place,
|
||||
// equivalent instructions with a different constant string
|
||||
// will be inserted for each Timeline object type filter.
|
||||
// Modifying this line may break the patch.
|
||||
blockedObjectTypes.add("BLOCKED_OBJECT_DUMMY");
|
||||
}
|
||||
|
||||
// Calls to this method are injected where the list of Timeline objects is first received.
|
||||
// We modify the list filter out elements that we want to hide.
|
||||
public static void filterTimeline(final List<TimelineObject<? extends Timelineable>> timelineObjects) {
|
||||
final var iterator = timelineObjects.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
var timelineElement = iterator.next();
|
||||
if (timelineElement == null) continue;
|
||||
|
||||
String elementType = timelineElement.getData().getTimelineObjectType().toString();
|
||||
if (blockedObjectTypes.contains(elementType)) iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.tumblr.rumblr.model;
|
||||
|
||||
public class TimelineObject<T extends Timelineable> {
|
||||
public final T getData() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.tumblr.rumblr.model;
|
||||
|
||||
public enum TimelineObjectType {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.tumblr.rumblr.model;
|
||||
|
||||
public interface Timelineable {
|
||||
TimelineObjectType getTimelineObjectType();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
android.useAndroidX = true
|
||||
version = 0.118.0-dev.17
|
||||
version = 0.119.2-dev.1
|
||||
|
||||
Reference in New Issue
Block a user