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
47 Commits
v0.106.0-d
...
v0.108.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ed0f46a7c | ||
|
|
e30d1201c9 | ||
|
|
feed762707 | ||
|
|
a3d754c209 | ||
|
|
d9d9538873 | ||
|
|
6544b87118 | ||
|
|
d7f050ba2f | ||
|
|
ab87cce7e5 | ||
|
|
9649c3dbc8 | ||
|
|
701f88460d | ||
|
|
b42790fbca | ||
|
|
3645a4a580 | ||
|
|
ae99408636 | ||
|
|
a97eab5fcd | ||
|
|
415c1948fc | ||
|
|
1f72d17d49 | ||
|
|
4c7f737913 | ||
|
|
9e6176886b | ||
|
|
c97d1b7ee5 | ||
|
|
4fe923527e | ||
|
|
111d2f21f9 | ||
|
|
1b4aa0fcc6 | ||
|
|
9e9399ddc3 | ||
|
|
7da9d440ee | ||
|
|
43b007e865 | ||
|
|
8997ab7962 | ||
|
|
ad812cd011 | ||
|
|
e2f52905dc | ||
|
|
2882ec1c9c | ||
|
|
cb5a4d0c9b | ||
|
|
b9ffd3853c | ||
|
|
2dc431f1bf | ||
|
|
513d4e4542 | ||
|
|
486b79b4e4 | ||
|
|
680f17257d | ||
|
|
6c36beeda1 | ||
|
|
12c7c6844b | ||
|
|
9b47361af4 | ||
|
|
8ba636a910 | ||
|
|
68f42fc980 | ||
|
|
8255909b2f | ||
|
|
a91b0363a8 | ||
|
|
e34e75133c | ||
|
|
1185ceedf7 | ||
|
|
2ee18fce69 | ||
|
|
e774be0f05 | ||
|
|
8a7098cce4 |
165
CHANGELOG.md
165
CHANGELOG.md
@@ -1,3 +1,168 @@
|
||||
# [0.108.0-dev.13](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.12...v0.108.0-dev.13) (2023-05-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/remember-video-quality:** do not show 'auto' in video resolution picker if a default quality is set ([#400](https://github.com/revanced/revanced-integrations/issues/400)) ([e30d120](https://github.com/revanced/revanced-integrations/commit/e30d1201c992f4896a0b7106230377d78506cd6f))
|
||||
|
||||
# [0.108.0-dev.12](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.11...v0.108.0-dev.12) (2023-05-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/swipe-controls:** restart when "press to swipe" preference is changed ([#399](https://github.com/revanced/revanced-integrations/issues/399)) ([a3d754c](https://github.com/revanced/revanced-integrations/commit/a3d754c209e443135759850c7634708b23330a7c))
|
||||
|
||||
# [0.108.0-dev.11](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.10...v0.108.0-dev.11) (2023-05-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **twitch:** add `auto-claim-channel-points` patch ([#398](https://github.com/revanced/revanced-integrations/issues/398)) ([d7f050b](https://github.com/revanced/revanced-integrations/commit/d7f050ba2ff513c91cccbf0095fc7756dbb47400))
|
||||
|
||||
# [0.108.0-dev.10](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.9...v0.108.0-dev.10) (2023-05-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube:** add `hide-filter-bar` patch ([9649c3d](https://github.com/revanced/revanced-integrations/commit/9649c3dbc8406c3639c4fff9dd179d6d29886e60))
|
||||
|
||||
# [0.108.0-dev.9](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.8...v0.108.0-dev.9) (2023-05-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/video-speed:** change custom video speeds inside app settings ([#393](https://github.com/revanced/revanced-integrations/issues/393)) ([b42790f](https://github.com/revanced/revanced-integrations/commit/b42790fbca0f6c854d41871834fd6266dd2ea106))
|
||||
|
||||
# [0.108.0-dev.8](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.7...v0.108.0-dev.8) (2023-05-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/theme:** apply custom seekbar color to video thumbnails ([#391](https://github.com/revanced/revanced-integrations/issues/391)) ([ae99408](https://github.com/revanced/revanced-integrations/commit/ae994086360b45340ed1ed896c35917d785bb4f9))
|
||||
|
||||
# [0.108.0-dev.7](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.6...v0.108.0-dev.7) (2023-05-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/hide-ads:** don't filter for `reels_player_overlay` ([415c194](https://github.com/revanced/revanced-integrations/commit/415c1948fccdc8eb27b76b043996017c5c56eac3))
|
||||
|
||||
# [0.108.0-dev.6](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.5...v0.108.0-dev.6) (2023-05-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/spoof-app-version:** restore watch history preview ([#394](https://github.com/revanced/revanced-integrations/issues/394)) ([4c7f737](https://github.com/revanced/revanced-integrations/commit/4c7f737913a0c3690f8230c51f6dd217e8b04c7a))
|
||||
|
||||
# [0.108.0-dev.5](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.4...v0.108.0-dev.5) (2023-05-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/remember-video-quality:** fix default video quality/speed being applied when resuming app ([#392](https://github.com/revanced/revanced-integrations/issues/392)) ([c97d1b7](https://github.com/revanced/revanced-integrations/commit/c97d1b7ee5be6a0f097f2995321608bc74f5822c))
|
||||
|
||||
# [0.108.0-dev.4](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.3...v0.108.0-dev.4) (2023-05-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/hide-player-overlay:** make it toggleable in settings ([#382](https://github.com/revanced/revanced-integrations/issues/382)) ([1b4aa0f](https://github.com/revanced/revanced-integrations/commit/1b4aa0fcc6b89acd4156e93685b1da7519aa7148))
|
||||
|
||||
# [0.108.0-dev.3](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.2...v0.108.0-dev.3) (2023-05-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube:** `hide-load-more-button` patch ([#389](https://github.com/revanced/revanced-integrations/issues/389)) ([7da9d44](https://github.com/revanced/revanced-integrations/commit/7da9d440eedfc895b49aac40498f0279156ad117))
|
||||
|
||||
# [0.108.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.108.0-dev.1...v0.108.0-dev.2) (2023-05-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/theme:** fix app crash if user clears seekbar color ([#390](https://github.com/revanced/revanced-integrations/issues/390)) ([e2f5290](https://github.com/revanced/revanced-integrations/commit/e2f52905dc445f881666c06877c3a69306335dcb))
|
||||
|
||||
# [0.108.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.107.1-dev.3...v0.108.0-dev.1) (2023-05-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/settings:** add reset button to edit preference dialog ([#383](https://github.com/revanced/revanced-integrations/issues/383)) ([cb5a4d0](https://github.com/revanced/revanced-integrations/commit/cb5a4d0c9b3b340928695fcb1d10b164a6dcef27))
|
||||
|
||||
## [0.107.1-dev.3](https://github.com/revanced/revanced-integrations/compare/v0.107.1-dev.2...v0.107.1-dev.3) (2023-05-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/theme:** fix toast shown on fresh app install ([#381](https://github.com/revanced/revanced-integrations/issues/381)) ([2dc431f](https://github.com/revanced/revanced-integrations/commit/2dc431f1bf54c12dfc45c4511a0b0792e214be4f))
|
||||
|
||||
## [0.107.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.107.1-dev.1...v0.107.1-dev.2) (2023-05-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/sponsorblock:** fix skip button in wrong location when full screen and comments visible ([#387](https://github.com/revanced/revanced-integrations/issues/387)) ([486b79b](https://github.com/revanced/revanced-integrations/commit/486b79b4e4927d4c05cfb4d5222a1d74fe60e327))
|
||||
|
||||
## [0.107.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.107.0...v0.107.1-dev.1) (2023-05-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/return-youtube-dislike:** fix potential error toast when using old UI layout ([#384](https://github.com/revanced/revanced-integrations/issues/384)) ([6c36bee](https://github.com/revanced/revanced-integrations/commit/6c36beeda139156bfbb5a17bc89aa63c25afa83c))
|
||||
|
||||
# [0.107.0](https://github.com/revanced/revanced-integrations/compare/v0.106.0...v0.107.0) (2023-05-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/theme:** set correct default seekbar color ([a91b036](https://github.com/revanced/revanced-integrations/commit/a91b0363a8aca4e195c9da4e48e2c332c1b1a7a6))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/theme:** change seekbar color via preference ([1185cee](https://github.com/revanced/revanced-integrations/commit/1185ceedf7fdb40759261ae8560e79604c8cb743))
|
||||
* **youtube:** `navigation-buttons` patch ([68f42fc](https://github.com/revanced/revanced-integrations/commit/68f42fc9800210f6c4d6f8e85c0132bf0cbc06d3))
|
||||
|
||||
# [0.107.0-dev.3](https://github.com/revanced/revanced-integrations/compare/v0.107.0-dev.2...v0.107.0-dev.3) (2023-05-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube:** `navigation-buttons` patch ([68f42fc](https://github.com/revanced/revanced-integrations/commit/68f42fc9800210f6c4d6f8e85c0132bf0cbc06d3))
|
||||
|
||||
# [0.107.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.107.0-dev.1...v0.107.0-dev.2) (2023-05-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/theme:** set correct default seekbar color ([a91b036](https://github.com/revanced/revanced-integrations/commit/a91b0363a8aca4e195c9da4e48e2c332c1b1a7a6))
|
||||
|
||||
# [0.107.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.106.0...v0.107.0-dev.1) (2023-05-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/theme:** change seekbar color via preference ([1185cee](https://github.com/revanced/revanced-integrations/commit/1185ceedf7fdb40759261ae8560e79604c8cb743))
|
||||
|
||||
# [0.106.0](https://github.com/revanced/revanced-integrations/compare/v0.105.0...v0.106.0) (2023-05-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/general-ads:** remove broken ad filter ([#355](https://github.com/revanced/revanced-integrations/issues/355)) ([061ebc6](https://github.com/revanced/revanced-integrations/commit/061ebc65465b2c8ef087c681070b465b82e3ebd5))
|
||||
* **youtube/return-youtube-dislike:** support old UI layouts ([#378](https://github.com/revanced/revanced-integrations/issues/378)) ([d3f8fb9](https://github.com/revanced/revanced-integrations/commit/d3f8fb97399aafe98a4198234338c6d0196a7e75))
|
||||
* **youtube/spoof-signature-verification:** more fixes for subtitle window positions ([#374](https://github.com/revanced/revanced-integrations/issues/374)) ([8cc1b6e](https://github.com/revanced/revanced-integrations/commit/8cc1b6ea4af4e642fb2d97233d50f34b0113f2c0))
|
||||
* **youtube:** no longer need to restart the app after changing `copy-video-url` or `downloads` patch ([#372](https://github.com/revanced/revanced-integrations/issues/372)) ([6b15514](https://github.com/revanced/revanced-integrations/commit/6b155148854fbfe155c9384ba8976b5ddf3d5992))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add appreciation message for new contributors ([78d56d4](https://github.com/revanced/revanced-integrations/commit/78d56d4fe182999555ddf5881a10880e3726782e))
|
||||
* **youtube/general-ads:** hide multiple audio track button on video player overlay ([#377](https://github.com/revanced/revanced-integrations/issues/377)) ([7fc7336](https://github.com/revanced/revanced-integrations/commit/7fc73368f161ee1973f36323054f8cbb53b6e7ce))
|
||||
* **youtube/general-ads:** hide new type of ad ([15f9c90](https://github.com/revanced/revanced-integrations/commit/15f9c90941535e93a0779118158c5b4a8accb799))
|
||||
* **youtube/hide-get-premium:** hide get premium advertisements under video player ([#376](https://github.com/revanced/revanced-integrations/issues/376)) ([36fd284](https://github.com/revanced/revanced-integrations/commit/36fd2844c468a4a9af3fe6ee5e62775f1e8dbe56))
|
||||
* **youtube/spoof-app-version:** user selectable version to spoof ([#375](https://github.com/revanced/revanced-integrations/issues/375)) ([f6f6c93](https://github.com/revanced/revanced-integrations/commit/f6f6c93c57bdbec13f09acd802f58554cb981f3a))
|
||||
|
||||
# [0.106.0-dev.7](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.6...v0.106.0-dev.7) (2023-05-01)
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# ReVanced Integrations
|
||||
# 🔩 ReVanced Integrations
|
||||
|
||||
The official ReVanced Integrations containing classes to be merged by ReVanced Patcher.
|
||||
|
||||
## ❓ How to use debugging:
|
||||
|
||||
# How to use debugging:
|
||||
- Usage on Windows: ```adb logcat | findstr "revanced" > log.txt```
|
||||
- Usage on Linux: ```adb logcat | grep --line-buffered "revanced" > log.txt```
|
||||
|
||||
This will write the log to a file called log.txt which you can view then.
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package app.revanced.integrations.adremover;
|
||||
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
|
||||
public class AdRemoverAPI {
|
||||
|
||||
/**
|
||||
* Removes Reels and Home ads
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
//ToDo: refactor this
|
||||
public static void HideViewWithLayout1dp(View view) {
|
||||
if (view instanceof LinearLayout) {
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams);
|
||||
} else if (view instanceof FrameLayout) {
|
||||
FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams2);
|
||||
} else if (view instanceof RelativeLayout) {
|
||||
RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams3);
|
||||
} else if (view instanceof Toolbar) {
|
||||
Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams4);
|
||||
} else if (view instanceof ViewGroup) {
|
||||
ViewGroup.LayoutParams layoutParams5 = new ViewGroup.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams5);
|
||||
} else {
|
||||
LogHelper.printDebug(() -> "HideViewWithLayout1dp - Id: " + view.getId() + " Type: " + view.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
import app.revanced.integrations.adremover.AdRemoverAPI;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
@@ -111,7 +110,6 @@ public final class GeneralAdsPatch extends Filter {
|
||||
"carousel_ad"
|
||||
);
|
||||
var shorts = new BlockRule(SettingsEnum.ADREMOVER_SHORTS_REMOVAL,
|
||||
"reels_player_overlay",
|
||||
"shorts_shelf",
|
||||
"inline_shorts",
|
||||
"shorts_grid"
|
||||
@@ -167,7 +165,7 @@ public final class GeneralAdsPatch extends Filter {
|
||||
|
||||
LogHelper.printDebug(() -> "Hiding view with setting: " + condition);
|
||||
|
||||
AdRemoverAPI.HideViewWithLayout1dp(view);
|
||||
ReVancedUtils.HideViewByLayoutParams(view);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,13 +2,12 @@ package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.adremover.AdRemoverAPI;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public class HideAlbumCardsPatch {
|
||||
//Used by app.revanced.patches.youtube.layout.hidealbumcards.patch.HideAlbumCardsPatch
|
||||
public static void hideAlbumCards(View view) {
|
||||
public static void hideAlbumCard(View view) {
|
||||
if (!SettingsEnum.HIDE_ALBUM_CARDS.getBoolean()) return;
|
||||
AdRemoverAPI.HideViewWithLayout1dp(view);
|
||||
ReVancedUtils.HideViewByLayoutParams(view);
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,28 @@ package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.adremover.AdRemoverAPI;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public class HideBreakingNewsPatch {
|
||||
//Used by app.revanced.patches.youtube.layout.homepage.breakingnews.patch.BreakingNewsPatch
|
||||
|
||||
/**
|
||||
* When spoofing to app versions older than 17.30.35, the watch history preview bar uses
|
||||
* the same layout components as the breaking news shelf.
|
||||
*
|
||||
* Breaking news does not appear to be present in these older versions anyways.
|
||||
*/
|
||||
private static boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory() {
|
||||
return SettingsEnum.SPOOF_APP_VERSION.getBoolean()
|
||||
&& SettingsEnum.SPOOF_APP_VERSION_TARGET.getString().compareTo("17.30.35") < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideBreakingNews(View view) {
|
||||
if (!SettingsEnum.HIDE_BREAKING_NEWS.getBoolean()) return;
|
||||
AdRemoverAPI.HideViewWithLayout1dp(view);
|
||||
if (!SettingsEnum.HIDE_BREAKING_NEWS.getBoolean()
|
||||
|| isSpoofingOldVersionWithHorizontalCardListWatchHistory()) return;
|
||||
ReVancedUtils.HideViewByLayoutParams(view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
|
||||
public class HideCreateButtonPatch {
|
||||
|
||||
//Used by app.revanced.patches.youtube.layout.createbutton.patch.CreateButtonRemoverPatch
|
||||
public static void hideCreateButton(View view) {
|
||||
boolean hidden = SettingsEnum.HIDE_CREATE_BUTTON.getBoolean();
|
||||
LogHelper.printDebug(() -> "Create button: " + (hidden ? "hidden" : "shown"));
|
||||
view.setVisibility(hidden ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@ package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.adremover.AdRemoverAPI;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public class HideCrowdfundingBoxPatch {
|
||||
//Used by app.revanced.patches.youtube.layout.hidecrowdfundingbox.patch.HideCrowdfundingBoxPatch
|
||||
public static void hideCrowdfundingBox(View view) {
|
||||
if (!SettingsEnum.HIDE_CROWDFUNDING_BOX.getBoolean()) return;
|
||||
AdRemoverAPI.HideViewWithLayout1dp(view);
|
||||
ReVancedUtils.HideViewByLayoutParams(view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public final class HideFilterBarPatch {
|
||||
public static int hideInFeed(final int height) {
|
||||
if (SettingsEnum.HIDE_FILTER_BAR_FEED_IN_FEED.getBoolean()) return 0;
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
public static void hideInRelatedVideos(final View chipView) {
|
||||
if (!SettingsEnum.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS.getBoolean()) return;
|
||||
|
||||
ReVancedUtils.HideViewByLayoutParams(chipView);
|
||||
}
|
||||
|
||||
public static int hideInSearch(final int height) {
|
||||
if (SettingsEnum.HIDE_FILTER_BAR_FEED_IN_SEARCH.getBoolean()) return 0;
|
||||
|
||||
return height;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public class HideLoadMoreButtonPatch {
|
||||
public static void hideLoadMoreButton(View view){
|
||||
if(!SettingsEnum.HIDE_LOAD_MORE_BUTTON.getBoolean()) return;
|
||||
ReVancedUtils.HideViewByLayoutParams(view);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public class HidePlayerOverlayPatch {
|
||||
public static void hidePlayerOverlay(ImageView view) {
|
||||
if (!SettingsEnum.HIDE_PLAYER_OVERLAY.getBoolean()) return;
|
||||
view.setImageResource(android.R.color.transparent);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
|
||||
public class HideShortsButtonPatch {
|
||||
|
||||
// Used by app.revanced.patches.youtube.layout.shorts.button.patch.ShortsButtonRemoverPatch
|
||||
public static void hideShortsButton(View view) {
|
||||
if (lastPivotTab != null && lastPivotTab.name() == "TAB_SHORTS") {
|
||||
boolean hide = SettingsEnum.HIDE_SHORTS_BUTTON.getBoolean();
|
||||
LogHelper.printDebug(() -> hide ? "Shorts button: hidden" : "Shorts button: shown");
|
||||
if (hide) {
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Needed for the ShortsButtonRemoverPatch
|
||||
public static Enum lastPivotTab;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
|
||||
import android.view.View;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public final class NavigationButtonsPatch {
|
||||
public static Enum lastNavigationButton;
|
||||
|
||||
public static void hideCreateButton(final View view) {
|
||||
view.setVisibility(SettingsEnum.HIDE_CREATE_BUTTON.getBoolean() ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
public static boolean switchCreateWithNotificationButton() {
|
||||
return SettingsEnum.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.getBoolean();
|
||||
}
|
||||
|
||||
public static void hideButton(final View buttonView) {
|
||||
if (lastNavigationButton == null) return;
|
||||
|
||||
for (NavigationButton button : NavigationButton.values())
|
||||
if (button.name.equals(lastNavigationButton.name()))
|
||||
if (button.enabled) buttonView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private enum NavigationButton {
|
||||
HOME("PIVOT_HOME", SettingsEnum.HIDE_HOME_BUTTON.getBoolean()),
|
||||
SHORTS("TAB_SHORTS", SettingsEnum.HIDE_SHORTS_BUTTON.getBoolean()),
|
||||
SUBSCRIPTIONS("PIVOT_SUBSCRIPTIONS", SettingsEnum.HIDE_SUBSCRIPTIONS_BUTTON.getBoolean());
|
||||
private final boolean enabled;
|
||||
private final String name;
|
||||
|
||||
NavigationButton(final String name, final boolean enabled) {
|
||||
this.name = name;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package app.revanced.integrations.patches;
|
||||
import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextWatcher;
|
||||
import android.widget.TextView;
|
||||
@@ -16,6 +16,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.shared.PlayerType;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
@@ -68,14 +69,9 @@ public class ReturnYouTubeDislikePatch {
|
||||
if (oldUITextView == null) {
|
||||
return;
|
||||
}
|
||||
Spanned dislikes = ReturnYouTubeDislike.getDislikesSpanForRegularVideo(oldUIOriginalSpan, false);
|
||||
if (dislikes == null) { // Dislikes not available.
|
||||
// Must reset text back to original as the TextView may contain dislikes of a prior video.
|
||||
dislikes = oldUIOriginalSpan;
|
||||
}
|
||||
oldUIReplacementSpan = dislikes;
|
||||
if (!dislikes.equals(oldUITextView.getText())) {
|
||||
oldUITextView.setText(dislikes);
|
||||
oldUIReplacementSpan = ReturnYouTubeDislike.getDislikesSpanForRegularVideo(oldUIOriginalSpan, false);
|
||||
if (!oldUIReplacementSpan.equals(oldUITextView.getText())) {
|
||||
oldUITextView.setText(oldUIReplacementSpan);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +80,11 @@ public class ReturnYouTubeDislikePatch {
|
||||
*
|
||||
* Used when spoofing the older app versions of {@link SpoofAppVersionPatch}.
|
||||
*/
|
||||
public static void setOldUILayoutDislikes(int buttonViewResourceId, @NonNull TextView textView) {
|
||||
public static void setOldUILayoutDislikes(int buttonViewResourceId, @Nullable TextView textView) {
|
||||
try {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()
|
||||
|| buttonViewResourceId != OLD_UI_DISLIKE_BUTTON_RESOURCE_ID) {
|
||||
|| buttonViewResourceId != OLD_UI_DISLIKE_BUTTON_RESOURCE_ID
|
||||
|| textView == null) {
|
||||
return;
|
||||
}
|
||||
if (oldUIOriginalSpan == null) {
|
||||
@@ -138,14 +135,23 @@ public class ReturnYouTubeDislikePatch {
|
||||
@NonNull AtomicReference<CharSequence> textRef,
|
||||
@NonNull CharSequence original) {
|
||||
try {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean() || PlayerType.getCurrent().isNoneOrHidden()) {
|
||||
return original;
|
||||
}
|
||||
SpannableString replacement = ReturnYouTubeDislike.getDislikeSpanForContext(conversionContext, original);
|
||||
if (replacement != null) {
|
||||
textRef.set(replacement);
|
||||
return replacement;
|
||||
|
||||
String conversionContextString = conversionContext.toString();
|
||||
final boolean isSegmentedButton;
|
||||
if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) {
|
||||
isSegmentedButton = true;
|
||||
} else if (conversionContextString.contains("|dislike_button.eml|")) {
|
||||
isSegmentedButton = false;
|
||||
} else {
|
||||
return original;
|
||||
}
|
||||
|
||||
Spanned replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, isSegmentedButton);
|
||||
textRef.set(replacement);
|
||||
return replacement;
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "onLithoTextLoaded failure", ex);
|
||||
}
|
||||
@@ -162,10 +168,7 @@ public class ReturnYouTubeDislikePatch {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
|
||||
return original;
|
||||
}
|
||||
SpannableString replacement = ReturnYouTubeDislike.getDislikeSpanForShort(original);
|
||||
if (replacement != null) {
|
||||
return replacement;
|
||||
}
|
||||
return ReturnYouTubeDislike.getDislikeSpanForShort(original);
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "onShortsComponentCreated failure", ex);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.patches.playback.speed.RememberPlaybackSpeedPatch;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
@@ -16,7 +17,7 @@ public final class VideoInformation {
|
||||
private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f;
|
||||
private static final String SEEK_METHOD_NAME = "seekTo";
|
||||
|
||||
private static WeakReference<Object> playerController;
|
||||
private static WeakReference<Object> playerControllerRef;
|
||||
private static Method seekMethod;
|
||||
|
||||
@NonNull
|
||||
@@ -30,17 +31,17 @@ public final class VideoInformation {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Sets a reference to the YouTube playback controller.
|
||||
*
|
||||
* @param thisRef Reference to the player controller object.
|
||||
* @param playerController player controller object.
|
||||
*/
|
||||
public static void playerController_onCreateHook(final Object thisRef) {
|
||||
playerController = new WeakReference<>(thisRef);
|
||||
videoLength = 0;
|
||||
videoTime = -1;
|
||||
|
||||
public static void initialize(@NonNull Object playerController) {
|
||||
try {
|
||||
seekMethod = thisRef.getClass().getMethod(SEEK_METHOD_NAME, Long.TYPE);
|
||||
playerControllerRef = new WeakReference<>(Objects.requireNonNull(playerController));
|
||||
videoTime = -1;
|
||||
videoLength = 0;
|
||||
playbackSpeed = DEFAULT_YOUTUBE_PLAYBACK_SPEED;
|
||||
|
||||
seekMethod = playerController.getClass().getMethod(SEEK_METHOD_NAME, Long.TYPE);
|
||||
seekMethod.setAccessible(true);
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "Failed to initialize", ex);
|
||||
@@ -56,7 +57,6 @@ public final class VideoInformation {
|
||||
if (!videoId.equals(newlyLoadedVideoId)) {
|
||||
LogHelper.printDebug(() -> "New video id: " + newlyLoadedVideoId);
|
||||
videoId = newlyLoadedVideoId;
|
||||
playbackSpeed = DEFAULT_YOUTUBE_PLAYBACK_SPEED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public final class VideoInformation {
|
||||
|
||||
try {
|
||||
LogHelper.printDebug(() -> "Seeking to " + millisecond);
|
||||
return (Boolean) seekMethod.invoke(playerController.get(), millisecond);
|
||||
return (Boolean) seekMethod.invoke(playerControllerRef.get(), millisecond);
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "Failed to seek", ex);
|
||||
return false;
|
||||
|
||||
@@ -2,7 +2,6 @@ package app.revanced.integrations.patches.playback.quality;
|
||||
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.NetworkType;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -20,8 +19,6 @@ public class RememberVideoQualityPatch {
|
||||
private static final SettingsEnum mobileQualitySetting = SettingsEnum.VIDEO_QUALITY_DEFAULT_MOBILE;
|
||||
|
||||
private static boolean qualityNeedsUpdating;
|
||||
@Nullable
|
||||
private static String currentVideoId;
|
||||
|
||||
/**
|
||||
* If the user selected a new quality from the flyout menu,
|
||||
@@ -91,7 +88,7 @@ public class RememberVideoQualityPatch {
|
||||
}
|
||||
}
|
||||
}
|
||||
LogHelper.printDebug(() -> "VideoId: " + currentVideoId + " videoQualities: " + videoQualities);
|
||||
LogHelper.printDebug(() -> "videoQualities: " + videoQualities);
|
||||
}
|
||||
|
||||
if (userChangedDefaultQuality) {
|
||||
@@ -113,15 +110,25 @@ public class RememberVideoQualityPatch {
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// If the desired quality index is equal to the original index,
|
||||
// then the video is already set to the desired default quality.
|
||||
//
|
||||
// The method could return here, but the UI video quality flyout will still
|
||||
// show 'Auto' (ie: Auto (480p))
|
||||
// It appears that "Auto" picks the resolution on video load,
|
||||
// and it does not appear to change the resolution during playback.
|
||||
//
|
||||
// To prevent confusion, set the video index anyways (even if it matches the existing index)
|
||||
// As that will force the UI picker to not display "Auto" which may confuse the user.
|
||||
if (qualityIndexToUse == originalQualityIndex) {
|
||||
LogHelper.printDebug(() -> "Video is already preferred quality: " + preferredQuality);
|
||||
return originalQualityIndex;
|
||||
} else {
|
||||
final int qualityToUseLog = qualityToUse;
|
||||
LogHelper.printDebug(() -> "Quality changed from: "
|
||||
+ videoQualities.get(originalQualityIndex) + " to: " + qualityToUseLog);
|
||||
}
|
||||
|
||||
final int qualityToUseLog = qualityToUse;
|
||||
LogHelper.printDebug(() -> "Quality changed from: "
|
||||
+ videoQualities.get(originalQualityIndex) + " to: " + qualityToUseLog);
|
||||
|
||||
Method m = qInterface.getClass().getMethod(qIndexMethod, Integer.TYPE);
|
||||
m.invoke(qInterface, qualityToUse);
|
||||
return qualityIndexToUse;
|
||||
@@ -144,25 +151,9 @@ public class RememberVideoQualityPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void newVideoStarted(@NonNull String videoId) {
|
||||
// The same videoId can be passed in multiple times for a single video playback.
|
||||
// Such as closing and opening the app, and sometimes when turning off/on the device screen.
|
||||
//
|
||||
// Known limitation, if:
|
||||
// 1. a default video quality exists, and remember quality is turned off
|
||||
// 2. user opens a video
|
||||
// 3. user changes the video quality
|
||||
// 4. user turns off then on the device screen (or does anything else that triggers the video id hook)
|
||||
// result: the video quality of the current video will revert back to the saved default
|
||||
//
|
||||
// qualityNeedsUpdating could be set only when the videoId changes
|
||||
// but then if the user closes and re-opens the same video the default video quality will not be applied.
|
||||
LogHelper.printDebug(() -> "newVideoStarted: " + videoId);
|
||||
public static void newVideoStarted(Object ignoredPlayerController) {
|
||||
LogHelper.printDebug(() -> "newVideoStarted");
|
||||
qualityNeedsUpdating = true;
|
||||
|
||||
if (!videoId.equals(currentVideoId)) {
|
||||
currentVideoId = videoId;
|
||||
videoQualities = null;
|
||||
}
|
||||
videoQualities = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,103 @@
|
||||
package app.revanced.integrations.patches.playback.speed;
|
||||
|
||||
import android.preference.ListPreference;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public class CustomVideoSpeedPatch {
|
||||
/**
|
||||
* Default playback speeds offered by YouTube.
|
||||
* Values are also used by {@link RememberPlaybackSpeedPatch}.
|
||||
*
|
||||
* If custom video speed is applied,
|
||||
* then this array is overwritten by the patch with custom speeds
|
||||
* Maximum playback speed, exclusive value. Custom speeds must be less than this value.
|
||||
*/
|
||||
public static final float[] videoSpeeds = {0.25f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f};
|
||||
public static final float MAXIMUM_PLAYBACK_SPEED = 10;
|
||||
|
||||
/**
|
||||
* Custom playback speeds.
|
||||
*/
|
||||
public static float[] customVideoSpeeds;
|
||||
|
||||
/**
|
||||
* Minimum value of {@link #customVideoSpeeds}
|
||||
*/
|
||||
public static float minVideoSpeed;
|
||||
|
||||
/**
|
||||
* Maxium value of {@link #customVideoSpeeds}
|
||||
*/
|
||||
public static float maxVideoSpeed;
|
||||
|
||||
/**
|
||||
* PreferenceList entries and values, of all available playback speeds.
|
||||
*/
|
||||
private static String[] preferenceListEntries, preferenceListEntryValues;
|
||||
|
||||
static {
|
||||
loadSpeeds();
|
||||
}
|
||||
|
||||
private static void resetCustomSpeeds(@NonNull String toastMessage) {
|
||||
ReVancedUtils.showToastLong(toastMessage);
|
||||
SettingsEnum.PLAYBACK_SPEED_AVAILABLE.saveValue(SettingsEnum.PLAYBACK_SPEED_AVAILABLE.defaultValue);
|
||||
}
|
||||
|
||||
private static void loadSpeeds() {
|
||||
try {
|
||||
String[] speedStrings = SettingsEnum.PLAYBACK_SPEED_AVAILABLE.getString().split("\\s+");
|
||||
Arrays.sort(speedStrings);
|
||||
if (speedStrings.length == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
customVideoSpeeds = new float[speedStrings.length];
|
||||
for (int i = 0, length = speedStrings.length; i < length; i++) {
|
||||
final float speed = Float.parseFloat(speedStrings[i]);
|
||||
if (speed <= 0 || arrayContains(customVideoSpeeds, speed)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (speed >= MAXIMUM_PLAYBACK_SPEED) {
|
||||
resetCustomSpeeds("Custom speeds must be less than " + MAXIMUM_PLAYBACK_SPEED
|
||||
+ ". Using default values.");
|
||||
loadSpeeds();
|
||||
return;
|
||||
}
|
||||
minVideoSpeed = Math.min(minVideoSpeed, speed);
|
||||
maxVideoSpeed = Math.max(maxVideoSpeed, speed);
|
||||
customVideoSpeeds[i] = speed;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printInfo(() -> "parse error", ex);
|
||||
resetCustomSpeeds("Invalid custom video speeds. Using default values.");
|
||||
loadSpeeds();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean arrayContains(float[] array, float value) {
|
||||
for (float arrayValue : array) {
|
||||
if (arrayValue == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a settings preference list with the available playback speeds.
|
||||
*/
|
||||
public static void initializeListPreference(ListPreference preference) {
|
||||
if (preferenceListEntries == null) {
|
||||
preferenceListEntries = new String[customVideoSpeeds.length];
|
||||
preferenceListEntryValues = new String[customVideoSpeeds.length];
|
||||
int i = 0;
|
||||
for (float speed : customVideoSpeeds) {
|
||||
String speedString = String.valueOf(speed);
|
||||
preferenceListEntries[i] = speedString + "x";
|
||||
preferenceListEntryValues[i] = speedString;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
preference.setEntries(preferenceListEntries);
|
||||
preference.setEntryValues(preferenceListEntryValues);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,17 @@
|
||||
package app.revanced.integrations.patches.playback.speed;
|
||||
|
||||
import android.preference.ListPreference;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.integrations.patches.VideoInformation;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public final class RememberPlaybackSpeedPatch {
|
||||
|
||||
/**
|
||||
* PreferenceList entries and values, of all available playback speeds.
|
||||
*/
|
||||
private static String[] preferenceListEntries, preferenceListEntryValues;
|
||||
|
||||
@Nullable
|
||||
private static String currentVideoId;
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Called when a new video loads.
|
||||
*/
|
||||
public static void newVideoLoaded(@NonNull String videoId) {
|
||||
if (videoId.equals(currentVideoId)) {
|
||||
return;
|
||||
}
|
||||
currentVideoId = videoId;
|
||||
public static void newVideoStarted(Object ignoredPlayerController) {
|
||||
LogHelper.printDebug(() -> "newVideoStarted");
|
||||
VideoInformation.overridePlaybackSpeed(SettingsEnum.PLAYBACK_SPEED_DEFAULT.getFloat());
|
||||
}
|
||||
|
||||
@@ -52,26 +36,4 @@ public final class RememberPlaybackSpeedPatch {
|
||||
return VideoInformation.getPlaybackSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a settings preference list.
|
||||
*
|
||||
* Normally this is done during patching by creating a static xml preference list,
|
||||
* but the available playback speeds differ depending if {@link CustomVideoSpeedPatch} is applied or not.
|
||||
*/
|
||||
public static void initializeListPreference(ListPreference preference) {
|
||||
if (preferenceListEntries == null) {
|
||||
float[] videoSpeeds = CustomVideoSpeedPatch.videoSpeeds;
|
||||
preferenceListEntries = new String[videoSpeeds.length];
|
||||
preferenceListEntryValues = new String[videoSpeeds.length];
|
||||
int i = 0;
|
||||
for (float speed : videoSpeeds) {
|
||||
String speedString = String.valueOf(speed);
|
||||
preferenceListEntries[i] = speedString + "x";
|
||||
preferenceListEntryValues[i] = speedString;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
preference.setEntries(preferenceListEntries);
|
||||
preference.setEntryValues(preferenceListEntryValues);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.integrations.patches.theme;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.integrations.patches.HideSeekbarPatch;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
/**
|
||||
* Used by {@link SeekbarColorPatch} change the color of the seekbar.
|
||||
* and {@link HideSeekbarPatch} to hide the seekbar of the feed and watch history.
|
||||
*/
|
||||
public class ProgressBarDrawable extends Drawable {
|
||||
|
||||
private final Paint paint = new Paint();
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
if (SettingsEnum.HIDE_SEEKBAR.getBoolean()) {
|
||||
return;
|
||||
}
|
||||
paint.setColor(SeekbarColorPatch.getCustomSeekbarColor());
|
||||
canvas.drawRect(getBounds(), paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
paint.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
paint.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package app.revanced.integrations.patches.theme;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public final class SeekbarColorPatch {
|
||||
|
||||
/**
|
||||
* Default color of seekbar.
|
||||
*/
|
||||
private static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000;
|
||||
|
||||
/**
|
||||
* Default YouTube seekbar color brightness.
|
||||
*/
|
||||
private static final float ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS;
|
||||
|
||||
/**
|
||||
* Color value of {@link SettingsEnum#SEEKBAR_COLOR}
|
||||
*/
|
||||
private static int customSeekbarColor;
|
||||
|
||||
/**
|
||||
* Custom seekbar hue, saturation, and brightness values.
|
||||
*/
|
||||
private static final float[] customSeekbarColorHSV = new float[3];
|
||||
|
||||
static {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(ORIGINAL_SEEKBAR_COLOR, hsv);
|
||||
ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS = hsv[2];
|
||||
|
||||
loadCustomSeekbarColorHSV();
|
||||
}
|
||||
|
||||
private static void loadCustomSeekbarColorHSV() {
|
||||
try {
|
||||
customSeekbarColor = Color.parseColor(SettingsEnum.SEEKBAR_COLOR.getString());
|
||||
Color.colorToHSV(customSeekbarColor, customSeekbarColorHSV);
|
||||
} catch (Exception ex) {
|
||||
ReVancedUtils.showToastShort("Invalid seekbar color value. Using default value.");
|
||||
SettingsEnum.SEEKBAR_COLOR.saveValue(SettingsEnum.SEEKBAR_COLOR.defaultValue);
|
||||
loadCustomSeekbarColorHSV();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getCustomSeekbarColor() {
|
||||
return customSeekbarColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Overrides color when seekbar is clicked, and all Litho components that use the YouTube seekbar color.
|
||||
*/
|
||||
public static int getSeekbarColorOverride(int colorValue) {
|
||||
return colorValue == ORIGINAL_SEEKBAR_COLOR
|
||||
? getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR)
|
||||
: colorValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* If {@link SettingsEnum#HIDE_SEEKBAR} is enabled, this returns a fully transparent color.
|
||||
*
|
||||
* Otherwise the original color is changed to the custom seekbar color, while retaining
|
||||
* the brightness and alpha changes of the parameter value compared to the original seekbar color.
|
||||
*/
|
||||
public static int getSeekbarColorValue(int originalColor) {
|
||||
try {
|
||||
if (SettingsEnum.HIDE_SEEKBAR.getBoolean()) {
|
||||
return 0x00000000;
|
||||
}
|
||||
if (customSeekbarColor == ORIGINAL_SEEKBAR_COLOR) {
|
||||
return originalColor; // Nothing to do
|
||||
}
|
||||
final int alphaDifference = Color.alpha(originalColor) - Color.alpha(ORIGINAL_SEEKBAR_COLOR);
|
||||
|
||||
// The seekbar uses the same color but different brightness for different situations.
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(originalColor, hsv);
|
||||
final float brightnessDifference = hsv[2] - ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS;
|
||||
|
||||
// Apply the brightness difference to the custom seekbar color.
|
||||
hsv[0] = customSeekbarColorHSV[0];
|
||||
hsv[1] = customSeekbarColorHSV[1];
|
||||
hsv[2] = clamp(customSeekbarColorHSV[2] + brightnessDifference, 0, 1);
|
||||
|
||||
final int replacementAlpha = clamp(Color.alpha(customSeekbarColor) + alphaDifference, 0, 255);
|
||||
final int replacementColor = Color.HSVToColor(replacementAlpha, hsv);
|
||||
LogHelper.printDebug(() -> String.format("Original color: #%08X replacement color: #%08X",
|
||||
originalColor, replacementColor));
|
||||
return replacementColor;
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "getSeekbarColorValue failure", ex);
|
||||
return originalColor;
|
||||
}
|
||||
}
|
||||
|
||||
static int clamp(int value, int lower, int upper) {
|
||||
return Math.max(lower, Math.min(value, upper));
|
||||
}
|
||||
|
||||
static float clamp(float value, float lower, float upper) {
|
||||
return Math.max(lower, Math.min(value, upper));
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package app.revanced.integrations.patches;
|
||||
package app.revanced.integrations.patches.theme;
|
||||
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
import app.revanced.integrations.utils.ThemeHelper;
|
||||
|
||||
public class LithoThemePatch {
|
||||
public class ThemeLithoComponentsPatch {
|
||||
// color constants used in relation with litho components
|
||||
private static final int[] WHITE_VALUES = {
|
||||
-1, // comments chip background
|
||||
@@ -31,7 +31,7 @@ public class LithoThemePatch {
|
||||
* @param originalValue The original color value.
|
||||
* @return The new or original color value
|
||||
*/
|
||||
public static int applyLithoTheme(int originalValue) {
|
||||
public static int getValue(int originalValue) {
|
||||
if (ThemeHelper.isDarkTheme()) {
|
||||
if (anyEquals(originalValue, DARK_VALUES)) return getBlackColor();
|
||||
} else {
|
||||
@@ -207,31 +207,10 @@ public class ReturnYouTubeDislike {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NULL if the span does not need changing or if RYD is not available.
|
||||
* @return the replacement span containing dislikes, or the original span if RYD is not available.
|
||||
*/
|
||||
@Nullable
|
||||
public static SpannableString getDislikeSpanForContext(@NonNull Object conversionContext, @NonNull CharSequence original) {
|
||||
if (PlayerType.getCurrent().isNoneOrHidden()) {
|
||||
return null;
|
||||
}
|
||||
String conversionContextString = conversionContext.toString();
|
||||
final boolean isSegmentedButton;
|
||||
if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) {
|
||||
isSegmentedButton = true;
|
||||
} else if (conversionContextString.contains("|dislike_button.eml|")) {
|
||||
isSegmentedButton = false;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getDislikesSpanForRegularVideo((Spannable) original, isSegmentedButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NULL if the span does not need changing or if RYD is not available.
|
||||
*/
|
||||
@Nullable
|
||||
public static SpannableString getDislikesSpanForRegularVideo(@NonNull Spanned original, boolean isSegmentedButton) {
|
||||
@NonNull
|
||||
public static Spanned getDislikesSpanForRegularVideo(@NonNull Spanned original, boolean isSegmentedButton) {
|
||||
if (dislikeDataIsShort) {
|
||||
// user:
|
||||
// 1, opened a video
|
||||
@@ -239,16 +218,16 @@ public class ReturnYouTubeDislike {
|
||||
// 3. closed the short
|
||||
// 4. regular video is now present, but the videoId and RYD data is still for the short
|
||||
LogHelper.printDebug(() -> "Ignoring getDislikeSpanForContext(), as data loaded is for prior short");
|
||||
return null;
|
||||
return original;
|
||||
}
|
||||
|
||||
return waitForFetchAndUpdateReplacementSpan(original, isSegmentedButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a Shorts dislike Spannable is created.
|
||||
*/
|
||||
public static SpannableString getDislikeSpanForShort(@NonNull Spanned original) {
|
||||
@NonNull
|
||||
public static Spanned getDislikeSpanForShort(@NonNull Spanned original) {
|
||||
dislikeDataIsShort = true; // it's now certain the video and data are a short
|
||||
return waitForFetchAndUpdateReplacementSpan(original, false);
|
||||
}
|
||||
@@ -258,17 +237,14 @@ public class ReturnYouTubeDislike {
|
||||
return span.toString().indexOf(MIDDLE_SEPARATOR_CHARACTER) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NULL if the span does not need changing or if RYD is not available.
|
||||
*/
|
||||
@Nullable
|
||||
private static SpannableString waitForFetchAndUpdateReplacementSpan(@NonNull Spanned oldSpannable, boolean isSegmentedButton) {
|
||||
@NonNull
|
||||
private static Spanned waitForFetchAndUpdateReplacementSpan(@NonNull Spanned oldSpannable, boolean isSegmentedButton) {
|
||||
try {
|
||||
synchronized (videoIdLockObject) {
|
||||
if (replacementLikeDislikeSpan != null) {
|
||||
if (spansHaveEqualTextAndColor(replacementLikeDislikeSpan, oldSpannable)) {
|
||||
LogHelper.printDebug(() -> "Ignoring previously created dislikes span");
|
||||
return null;
|
||||
return oldSpannable;
|
||||
}
|
||||
if (spansHaveEqualTextAndColor(Objects.requireNonNull(originalDislikeSpan), oldSpannable)) {
|
||||
LogHelper.printDebug(() -> "Replacing span with previously created dislike span");
|
||||
@@ -277,11 +253,11 @@ public class ReturnYouTubeDislike {
|
||||
}
|
||||
if (isSegmentedButton && isPreviouslyCreatedSegmentedSpan(oldSpannable)) {
|
||||
// need to recreate using original, as oldSpannable has prior outdated dislike values
|
||||
oldSpannable = originalDislikeSpan;
|
||||
if (oldSpannable == null) {
|
||||
if (originalDislikeSpan == null) {
|
||||
LogHelper.printDebug(() -> "Cannot add dislikes - original span is null"); // should never happen
|
||||
return null;
|
||||
return oldSpannable;
|
||||
}
|
||||
oldSpannable = originalDislikeSpan;
|
||||
} else {
|
||||
originalDislikeSpan = oldSpannable; // most up to date original
|
||||
}
|
||||
@@ -292,12 +268,12 @@ public class ReturnYouTubeDislike {
|
||||
Future<RYDVoteData> fetchFuture = getVoteFetchFuture();
|
||||
if (fetchFuture == null) {
|
||||
LogHelper.printDebug(() -> "fetch future not available (user enabled RYD while video was playing?)");
|
||||
return null;
|
||||
return oldSpannable;
|
||||
}
|
||||
RYDVoteData votingData = fetchFuture.get(MAX_MILLISECONDS_TO_BLOCK_UI_WHILE_WAITING_FOR_FETCH_VOTES_TO_COMPLETE, TimeUnit.MILLISECONDS);
|
||||
if (votingData == null) {
|
||||
LogHelper.printDebug(() -> "Cannot add dislike to UI (RYD data not available)");
|
||||
return null;
|
||||
return oldSpannable;
|
||||
}
|
||||
|
||||
SpannableString replacement = createDislikeSpan(oldSpannable, isSegmentedButton, votingData);
|
||||
@@ -312,7 +288,7 @@ public class ReturnYouTubeDislike {
|
||||
} catch (Exception e) {
|
||||
LogHelper.printException(() -> "waitForFetchAndUpdateReplacementSpan failure", e); // should never happen
|
||||
}
|
||||
return null;
|
||||
return oldSpannable;
|
||||
}
|
||||
|
||||
public static void sendVote(@NonNull Vote vote) {
|
||||
|
||||
@@ -136,21 +136,20 @@ public class ReturnYouTubeDislikeApi {
|
||||
/**
|
||||
* Simulates a slow response by doing meaningless calculations.
|
||||
* Used to debug the app UI and verify UI timeout logic works
|
||||
*
|
||||
* @param maximumTimeToWait maximum time to wait
|
||||
*/
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
private static long randomlyWaitIfLocallyDebugging(long maximumTimeToWait) {
|
||||
private static long randomlyWaitIfLocallyDebugging() {
|
||||
final boolean DEBUG_RANDOMLY_DELAY_NETWORK_CALLS = false; // set true to debug UI
|
||||
if (DEBUG_RANDOMLY_DELAY_NETWORK_CALLS) {
|
||||
final long amountOfTimeToWaste = (long) (Math.random() * maximumTimeToWait);
|
||||
final long amountOfTimeToWaste = (long) (Math.random()
|
||||
* (API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS + API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS));
|
||||
final long timeCalculationStarted = System.currentTimeMillis();
|
||||
LogHelper.printDebug(() -> "Artificially creating network delay of: " + amountOfTimeToWaste + " ms");
|
||||
LogHelper.printDebug(() -> "Artificially creating network delay of: " + amountOfTimeToWaste + "ms");
|
||||
|
||||
long meaninglessValue = 0;
|
||||
while (System.currentTimeMillis() - timeCalculationStarted < amountOfTimeToWaste) {
|
||||
// could do a thread sleep, but that will trigger an exception if the thread is interrupted
|
||||
meaninglessValue += Long.numberOfLeadingZeros((long) (Math.random() * Long.MAX_VALUE));
|
||||
meaninglessValue += Long.numberOfLeadingZeros((long)Math.exp(Math.random()));
|
||||
}
|
||||
// return the value, otherwise the compiler or VM might optimize and remove the meaningless time wasting work,
|
||||
// leaving an empty loop that hammers on the System.currentTimeMillis native call
|
||||
@@ -246,7 +245,7 @@ public class ReturnYouTubeDislikeApi {
|
||||
connection.setConnectTimeout(API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS); // timeout for TCP connection to server
|
||||
connection.setReadTimeout(API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS); // timeout for server response
|
||||
|
||||
randomlyWaitIfLocallyDebugging(2*(API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS + API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS));
|
||||
randomlyWaitIfLocallyDebugging();
|
||||
|
||||
final int responseCode = connection.getResponseCode();
|
||||
if (checkIfRateLimitWasHit(responseCode)) {
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
package app.revanced.integrations.settings;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.integrations.settings.SettingsEnum.ReturnType.BOOLEAN;
|
||||
import static app.revanced.integrations.settings.SettingsEnum.ReturnType.FLOAT;
|
||||
import static app.revanced.integrations.settings.SettingsEnum.ReturnType.INTEGER;
|
||||
import static app.revanced.integrations.settings.SettingsEnum.ReturnType.LONG;
|
||||
import static app.revanced.integrations.settings.SettingsEnum.ReturnType.STRING;
|
||||
import static app.revanced.integrations.settings.SharedPrefCategory.RETURN_YOUTUBE_DISLIKE;
|
||||
import static app.revanced.integrations.settings.SharedPrefCategory.SPONSOR_BLOCK;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.revanced.integrations.utils.StringRef;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.utils.StringRef;
|
||||
import static app.revanced.integrations.settings.SettingsEnum.ReturnType.*;
|
||||
import static app.revanced.integrations.settings.SharedPrefCategory.RETURN_YOUTUBE_DISLIKE;
|
||||
import static app.revanced.integrations.settings.SharedPrefCategory.SPONSOR_BLOCK;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
public enum SettingsEnum {
|
||||
//Download Settings
|
||||
@@ -33,6 +28,8 @@ public enum SettingsEnum {
|
||||
VIDEO_QUALITY_DEFAULT_MOBILE("revanced_default_video_quality_mobile", INTEGER, -2),
|
||||
PLAYBACK_SPEED_REMEMBER_LAST_SELECTED("revanced_remember_playback_speed_last_selected", BOOLEAN, TRUE),
|
||||
PLAYBACK_SPEED_DEFAULT("revanced_default_playback_speed", FLOAT, 1.0f),
|
||||
PLAYBACK_SPEED_AVAILABLE("revanced_custom_video_speeds", STRING,
|
||||
"0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true),
|
||||
|
||||
// TODO: Unused currently
|
||||
// Whitelist settings
|
||||
@@ -87,6 +84,7 @@ public enum SettingsEnum {
|
||||
HIDE_CAST_BUTTON("revanced_hide_cast_button", BOOLEAN, TRUE, true),
|
||||
HIDE_COMMENTS_SECTION("revanced_hide_comments_section", BOOLEAN, FALSE, true),
|
||||
HIDE_CREATE_BUTTON("revanced_hide_create_button", BOOLEAN, TRUE, true),
|
||||
SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON("revanced_switch_create_with_notifications_button", BOOLEAN, TRUE, true),
|
||||
HIDE_CROWDFUNDING_BOX("revanced_hide_crowdfunding_box", BOOLEAN, FALSE, true),
|
||||
HIDE_EMAIL_ADDRESS("revanced_hide_email_address", BOOLEAN, FALSE),
|
||||
HIDE_ENDSCREEN_CARDS("revanced_hide_endscreen_cards", BOOLEAN, TRUE),
|
||||
@@ -94,10 +92,14 @@ public enum SettingsEnum {
|
||||
HIDE_FULLSCREEN_PANELS("revanced_hide_fullscreen_panels", BOOLEAN, TRUE),
|
||||
HIDE_GET_PREMIUM("revanced_hide_get_premium", BOOLEAN, TRUE),
|
||||
HIDE_INFO_CARDS("revanced_hide_infocards", BOOLEAN, TRUE),
|
||||
HIDE_LOAD_MORE_BUTTON("revanced_hide_load_more_button", BOOLEAN, TRUE, true),
|
||||
HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE),
|
||||
HIDE_PLAYER_OVERLAY("revanced_hide_player_overlay", BOOLEAN, FALSE, true),
|
||||
HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true),
|
||||
HIDE_SEEKBAR("revanced_hide_seekbar", BOOLEAN, FALSE),
|
||||
HIDE_SEEKBAR("revanced_hide_seekbar", BOOLEAN, FALSE, true),
|
||||
HIDE_HOME_BUTTON("revanced_hide_home_button", BOOLEAN, FALSE, true),
|
||||
HIDE_SHORTS_BUTTON("revanced_hide_shorts_button", BOOLEAN, TRUE, true),
|
||||
HIDE_SUBSCRIPTIONS_BUTTON("revanced_hide_subscriptions_button", BOOLEAN, FALSE, true),
|
||||
HIDE_SHORTS_COMMENTS_BUTTON("revanced_hide_shorts_comments_button", BOOLEAN, FALSE),
|
||||
HIDE_TIMESTAMP("revanced_hide_timestamp", BOOLEAN, FALSE),
|
||||
HIDE_VIDEO_WATERMARK("revanced_hide_video_watermark", BOOLEAN, TRUE),
|
||||
@@ -107,6 +109,10 @@ public enum SettingsEnum {
|
||||
SPOOF_APP_VERSION_TARGET("revanced_spoof_app_version_target", STRING, "17.30.35", true, parents(SPOOF_APP_VERSION)),
|
||||
USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true),
|
||||
WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true),
|
||||
SEEKBAR_COLOR("revanced_seekbar_color", STRING, "#FF0000", true),
|
||||
HIDE_FILTER_BAR_FEED_IN_FEED("revanced_hide_filter_bar_feed_in_feed", BOOLEAN, FALSE, true),
|
||||
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),
|
||||
|
||||
// Misc. Settings
|
||||
SIGNATURE_SPOOFING("revanced_spoof_signature_verification", BOOLEAN, TRUE, "revanced_spoof_signature_verification_user_dialog_message"),
|
||||
@@ -120,15 +126,15 @@ public enum SettingsEnum {
|
||||
// Swipe controls
|
||||
ENABLE_SWIPE_BRIGHTNESS("revanced_enable_swipe_brightness", BOOLEAN, TRUE),
|
||||
ENABLE_SWIPE_VOLUME("revanced_enable_swipe_volume", BOOLEAN, TRUE),
|
||||
ENABLE_PRESS_TO_SWIPE("revanced_enable_press_to_swipe", BOOLEAN, FALSE,
|
||||
ENABLE_PRESS_TO_SWIPE("revanced_enable_press_to_swipe", BOOLEAN, FALSE, true,
|
||||
parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)),
|
||||
ENABLE_SWIPE_HAPTIC_FEEDBACK("revanced_enable_swipe_haptic_feedback", BOOLEAN, TRUE,
|
||||
parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)),
|
||||
SWIPE_MAGNITUDE_THRESHOLD("revanced_swipe_magnitude_threshold", FLOAT, 30f,
|
||||
SWIPE_MAGNITUDE_THRESHOLD("revanced_swipe_magnitude_threshold", FLOAT, 30f, // edit: why is this a float and not an Integer?
|
||||
parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)),
|
||||
SWIPE_OVERLAY_BACKGROUND_ALPHA("revanced_swipe_overlay_background_alpha", INTEGER, 127,
|
||||
parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)),
|
||||
SWIPE_OVERLAY_TEXT_SIZE("revanced_swipe_overlay_text_size", FLOAT, 22f,
|
||||
SWIPE_OVERLAY_TEXT_SIZE("revanced_swipe_overlay_text_size", FLOAT, 22f, // edit: why is this a float and not an Integer?
|
||||
parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)),
|
||||
SWIPE_OVERLAY_TIMEOUT("revanced_swipe_overlay_timeout", LONG, 500L,
|
||||
parents(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)),
|
||||
@@ -429,4 +435,4 @@ public enum SettingsEnum {
|
||||
LONG,
|
||||
FLOAT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
/**
|
||||
@@ -35,6 +36,11 @@ public enum SharedPrefCategory {
|
||||
preferences = Objects.requireNonNull(ReVancedUtils.getContext()).getSharedPreferences(prefName, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private void removeConflictingPreferenceKeyValue(@NonNull String key) {
|
||||
LogHelper.printException(() -> "Found conflicting preference: " + key);
|
||||
preferences.edit().remove(key).apply();
|
||||
}
|
||||
|
||||
private void saveObjectAsString(@NonNull String key, @Nullable Object value) {
|
||||
preferences.edit().putString(key, (value == null ? null : value.toString())).apply();
|
||||
}
|
||||
@@ -91,7 +97,14 @@ public enum SharedPrefCategory {
|
||||
}
|
||||
return _default;
|
||||
} catch (ClassCastException ex) {
|
||||
return preferences.getInt(key, _default); // old data, previously stored as primitive
|
||||
try {
|
||||
// Old data previously stored as primitive.
|
||||
return preferences.getInt(key, _default);
|
||||
} catch (ClassCastException ex2) {
|
||||
// Value stored is a completely different type (should never happen).
|
||||
removeConflictingPreferenceKeyValue(key);
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +117,12 @@ public enum SharedPrefCategory {
|
||||
}
|
||||
return _default;
|
||||
} catch (ClassCastException ex) {
|
||||
return preferences.getLong(key, _default);
|
||||
try {
|
||||
return preferences.getLong(key, _default);
|
||||
} catch (ClassCastException ex2) {
|
||||
removeConflictingPreferenceKeyValue(key);
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +135,12 @@ public enum SharedPrefCategory {
|
||||
}
|
||||
return _default;
|
||||
} catch (ClassCastException ex) {
|
||||
return preferences.getFloat(key, _default);
|
||||
try {
|
||||
return preferences.getFloat(key, _default);
|
||||
} catch (ClassCastException ex2) {
|
||||
removeConflictingPreferenceKeyValue(key);
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.apps.youtube.app.application.Shell_HomeActivity;
|
||||
|
||||
import app.revanced.integrations.patches.playback.speed.RememberPlaybackSpeedPatch;
|
||||
import app.revanced.integrations.patches.playback.speed.CustomVideoSpeedPatch;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.settings.SharedPrefCategory;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
@@ -88,7 +88,7 @@ public class ReVancedSettingsFragment extends PreferenceFragment {
|
||||
// if the preference was included, then initialize it based on the available playback speed
|
||||
Preference defaultSpeedPreference = findPreference(SettingsEnum.PLAYBACK_SPEED_DEFAULT.path);
|
||||
if (defaultSpeedPreference instanceof ListPreference) {
|
||||
RememberPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
|
||||
CustomVideoSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
|
||||
}
|
||||
|
||||
// set the summary text for any ListPreferences
|
||||
@@ -120,6 +120,9 @@ public class ReVancedSettingsFragment extends PreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets summary text to the currently selected list option.
|
||||
*/
|
||||
private void updateListPreferenceSummary(ListPreference listPreference, SettingsEnum setting) {
|
||||
final int entryIndex = listPreference.findIndexOfValue(setting.getObjectValue().toString());
|
||||
if (entryIndex >= 0) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package app.revanced.integrations.settingsmenu;
|
||||
|
||||
import static app.revanced.integrations.utils.StringRef.str;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
|
||||
public class ResettableEditTextPreference extends EditTextPreference {
|
||||
|
||||
public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
public ResettableEditTextPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
public ResettableEditTextPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||
super.onPrepareDialogBuilder(builder);
|
||||
SettingsEnum setting = SettingsEnum.settingFromPath(getKey());
|
||||
if (setting != null) {
|
||||
builder.setNeutralButton(str("revanced_settings_reset"), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showDialog(Bundle state) {
|
||||
super.showDialog(state);
|
||||
|
||||
// Override the button click listener to prevent dismissing the dialog.
|
||||
Button button = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEUTRAL);
|
||||
if (button == null) {
|
||||
return;
|
||||
}
|
||||
button.setOnClickListener(v -> {
|
||||
try {
|
||||
SettingsEnum setting = Objects.requireNonNull(SettingsEnum.settingFromPath(getKey()));
|
||||
String defaultStringValue = setting.defaultValue.toString();
|
||||
EditText editText = getEditText();
|
||||
editText.setText(defaultStringValue);
|
||||
editText.setSelection(defaultStringValue.length()); // move cursor to end of text
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "reset failure", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -102,9 +102,9 @@ public class SegmentPlaybackController {
|
||||
@Nullable
|
||||
private static String timeWithoutSegments;
|
||||
|
||||
private static float sponsorBarLeft = 1f;
|
||||
private static float sponsorBarRight = 1f;
|
||||
private static float sponsorBarThickness = 2f;
|
||||
private static int sponsorBarAbsoluteLeft;
|
||||
private static int sponsorAbsoluteBarRight;
|
||||
private static int sponsorBarThickness;
|
||||
|
||||
@Nullable
|
||||
static SponsorSegment[] getSegments() {
|
||||
@@ -177,7 +177,7 @@ public class SegmentPlaybackController {
|
||||
* Injection point.
|
||||
* Initializes SponsorBlock when the video player starts playing a new video.
|
||||
*/
|
||||
public static void initialize(Object _o) {
|
||||
public static void initialize(Object ignoredPlayerController) {
|
||||
try {
|
||||
ReVancedUtils.verifyOnMainThread();
|
||||
SponsorBlockSettings.initialize();
|
||||
@@ -235,7 +235,7 @@ public class SegmentPlaybackController {
|
||||
SponsorSegment[] segments = SBRequester.getSegments(videoId);
|
||||
|
||||
ReVancedUtils.runOnMainThread(()-> {
|
||||
if (!videoId.equals(SegmentPlaybackController.currentVideoId)) {
|
||||
if (!videoId.equals(currentVideoId)) {
|
||||
// user changed videos before get segments network call could complete
|
||||
LogHelper.printDebug(() -> "Ignoring segments for prior video: " + videoId);
|
||||
return;
|
||||
@@ -525,7 +525,7 @@ public class SegmentPlaybackController {
|
||||
if (!userManuallySkipped) {
|
||||
// check for any smaller embedded segments, and count those as autoskipped
|
||||
final boolean showSkipToast = SettingsEnum.SB_SHOW_TOAST_ON_SKIP.getBoolean();
|
||||
for (final SponsorSegment otherSegment : segments) {
|
||||
for (final SponsorSegment otherSegment : Objects.requireNonNull(segments)) {
|
||||
if (segmentToSkip.end < otherSegment.start) {
|
||||
break; // no other segments can be contained
|
||||
}
|
||||
@@ -599,20 +599,6 @@ public class SegmentPlaybackController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setSponsorBarAbsoluteLeft(final Rect rect) {
|
||||
setSponsorBarAbsoluteLeft(rect.left);
|
||||
}
|
||||
|
||||
public static void setSponsorBarAbsoluteLeft(final float left) {
|
||||
if (sponsorBarLeft != left) {
|
||||
LogHelper.printDebug(() -> String.format("setSponsorBarAbsoluteLeft: left=%.2f", left));
|
||||
sponsorBarLeft = left;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
@@ -620,13 +606,9 @@ public class SegmentPlaybackController {
|
||||
try {
|
||||
Field field = self.getClass().getDeclaredField("replaceMeWithsetSponsorBarRect");
|
||||
field.setAccessible(true);
|
||||
Rect rect = (Rect) field.get(self);
|
||||
if (rect == null) {
|
||||
LogHelper.printException(() -> "Could not find sponsorblock rect");
|
||||
} else {
|
||||
setSponsorBarAbsoluteLeft(rect.left);
|
||||
setSponsorBarAbsoluteRight(rect.right);
|
||||
}
|
||||
Rect rect = (Rect) Objects.requireNonNull(field.get(self));
|
||||
setSponsorBarAbsoluteLeft(rect);
|
||||
setSponsorBarAbsoluteRight(rect);
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "setSponsorBarRect failure", ex);
|
||||
}
|
||||
@@ -635,27 +617,31 @@ public class SegmentPlaybackController {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setSponsorBarAbsoluteRight(final Rect rect) {
|
||||
setSponsorBarAbsoluteRight(rect.right);
|
||||
public static void setSponsorBarAbsoluteLeft(Rect rect) {
|
||||
final int left = rect.left;
|
||||
if (sponsorBarAbsoluteLeft != left) {
|
||||
LogHelper.printDebug(() -> "setSponsorBarAbsoluteLeft: " + left);
|
||||
sponsorBarAbsoluteLeft = left;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setSponsorBarAbsoluteRight(final float right) {
|
||||
if (sponsorBarRight != right) {
|
||||
LogHelper.printDebug(() -> String.format("setSponsorBarAbsoluteRight: right=%.2f", right));
|
||||
sponsorBarRight = right;
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setSponsorBarAbsoluteRight(Rect rect) {
|
||||
final int right = rect.right;
|
||||
if (sponsorAbsoluteBarRight != right) {
|
||||
LogHelper.printDebug(() -> "setSponsorBarAbsoluteRight: " + right);
|
||||
sponsorAbsoluteBarRight = right;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static void setSponsorBarThickness(final int thickness) {
|
||||
setSponsorBarThickness((float) thickness);
|
||||
}
|
||||
|
||||
public static void setSponsorBarThickness(final float thickness) {
|
||||
public static void setSponsorBarThickness(int thickness) {
|
||||
if (sponsorBarThickness != thickness) {
|
||||
LogHelper.printDebug(() -> String.format("setSponsorBarThickness: %.2f", thickness));
|
||||
LogHelper.printDebug(() -> "setSponsorBarThickness: " + thickness);
|
||||
sponsorBarThickness = thickness;
|
||||
}
|
||||
}
|
||||
@@ -736,25 +722,23 @@ public class SegmentPlaybackController {
|
||||
*/
|
||||
public static void drawSponsorTimeBars(final Canvas canvas, final float posY) {
|
||||
try {
|
||||
if (sponsorBarThickness < 0.1) return;
|
||||
if (segments == null) return;
|
||||
final long videoLength = VideoInformation.getVideoLength();
|
||||
if (videoLength <= 0) return;
|
||||
|
||||
final float thicknessDiv2 = sponsorBarThickness / 2;
|
||||
final float top = posY - thicknessDiv2;
|
||||
final int thicknessDiv2 = sponsorBarThickness / 2; // rounds down
|
||||
final float top = posY - (sponsorBarThickness - thicknessDiv2);
|
||||
final float bottom = posY + thicknessDiv2;
|
||||
final float absoluteLeft = sponsorBarLeft;
|
||||
final float absoluteRight = sponsorBarRight;
|
||||
final float videoMillisecondsToPixels = (1f / videoLength) * (sponsorAbsoluteBarRight - sponsorBarAbsoluteLeft);
|
||||
final float leftPadding = sponsorBarAbsoluteLeft;
|
||||
|
||||
final float tmp1 = (1f / videoLength) * (absoluteRight - absoluteLeft);
|
||||
for (SponsorSegment segment : segments) {
|
||||
final float left = segment.start * tmp1 + absoluteLeft;
|
||||
final float left = leftPadding + segment.start * videoMillisecondsToPixels;
|
||||
final float right;
|
||||
if (segment.category == SegmentCategory.HIGHLIGHT) {
|
||||
right = left + getHighlightSegmentTimeBarScreenWidth();
|
||||
} else {
|
||||
right = segment.end * tmp1 + absoluteLeft;
|
||||
right = leftPadding + segment.end * videoMillisecondsToPixels;
|
||||
}
|
||||
canvas.drawRect(left, top, right, bottom, segment.category.paint);
|
||||
}
|
||||
|
||||
@@ -3,52 +3,35 @@ package app.revanced.integrations.sponsorblock.ui;
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.getResourceIdentifier;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.patches.VideoInformation;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
import app.revanced.integrations.videoplayer.BottomControlButton;
|
||||
|
||||
public class CreateSegmentButtonController {
|
||||
private static WeakReference<ImageView> buttonReference = new WeakReference<>(null);
|
||||
private static Animation fadeIn;
|
||||
private static Animation fadeOut;
|
||||
private static boolean isShowing;
|
||||
|
||||
/**
|
||||
* injection point
|
||||
*/
|
||||
public static void initialize(Object viewStub) {
|
||||
public static void initialize(View youtubeControlsLayout) {
|
||||
try {
|
||||
LogHelper.printDebug(() -> "initializing new segment button");
|
||||
|
||||
RelativeLayout youtubeControlsLayout = (RelativeLayout) viewStub;
|
||||
String buttonIdentifier = "sb_sponsorblock_button";
|
||||
ImageView imageView = youtubeControlsLayout.findViewById(getResourceIdentifier(buttonIdentifier, "id"));
|
||||
if (imageView == null) {
|
||||
LogHelper.printException(() -> "Couldn't find imageView with \"" + buttonIdentifier + "\"");
|
||||
return;
|
||||
}
|
||||
ImageView imageView = Objects.requireNonNull(youtubeControlsLayout.findViewById(
|
||||
getResourceIdentifier("sb_sponsorblock_button", "id")));
|
||||
imageView.setVisibility(View.GONE);
|
||||
imageView.setOnClickListener(v -> {
|
||||
LogHelper.printDebug(() -> "New segment button clicked");
|
||||
SponsorBlockViewController.toggleNewSegmentLayoutVisibility();
|
||||
});
|
||||
buttonReference = new WeakReference<>(imageView);
|
||||
|
||||
// Animations
|
||||
if (fadeIn == null) {
|
||||
fadeIn = ReVancedUtils.getResourceAnimation("fade_in");
|
||||
fadeIn.setDuration(ReVancedUtils.getResourceInteger("fade_duration_fast"));
|
||||
fadeOut = ReVancedUtils.getResourceAnimation("fade_out");
|
||||
fadeOut.setDuration(ReVancedUtils.getResourceInteger("fade_duration_scheduled"));
|
||||
}
|
||||
isShowing = true;
|
||||
changeVisibilityImmediate(false);
|
||||
buttonReference = new WeakReference<>(imageView);
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "initialize failure", ex);
|
||||
}
|
||||
@@ -86,7 +69,7 @@ public class CreateSegmentButtonController {
|
||||
return;
|
||||
}
|
||||
if (!immediate) {
|
||||
iView.startAnimation(fadeIn);
|
||||
iView.startAnimation(BottomControlButton.getButtonFadeIn());
|
||||
}
|
||||
iView.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
@@ -95,7 +78,7 @@ public class CreateSegmentButtonController {
|
||||
if (iView.getVisibility() == View.VISIBLE) {
|
||||
iView.clearAnimation();
|
||||
if (!immediate) {
|
||||
iView.startAnimation(fadeOut);
|
||||
iView.startAnimation(BottomControlButton.getButtonFadeOut());
|
||||
}
|
||||
iView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class SponsorBlockViewController {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void initialize(Object obj) {
|
||||
public static void initialize(ViewGroup viewGroup) {
|
||||
try {
|
||||
LogHelper.printDebug(() -> "initializing");
|
||||
|
||||
@@ -64,7 +64,6 @@ public class SponsorBlockViewController {
|
||||
LayoutInflater.from(context).inflate(getResourceIdentifier("inline_sponsor_overlay", "layout"), layout);
|
||||
inlineSponsorOverlayRef = new WeakReference<>(layout);
|
||||
|
||||
ViewGroup viewGroup = (ViewGroup) obj;
|
||||
viewGroup.addView(layout);
|
||||
viewGroup.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
|
||||
@Override
|
||||
|
||||
@@ -3,11 +3,10 @@ package app.revanced.integrations.sponsorblock.ui;
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.getResourceIdentifier;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.patches.VideoInformation;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
@@ -15,40 +14,26 @@ import app.revanced.integrations.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.integrations.sponsorblock.SponsorBlockUtils;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
import app.revanced.integrations.videoplayer.BottomControlButton;
|
||||
|
||||
public class VotingButtonController {
|
||||
private static WeakReference<ImageView> buttonReference = new WeakReference<>(null);
|
||||
private static Animation fadeIn;
|
||||
private static Animation fadeOut;
|
||||
private static boolean isShowing;
|
||||
|
||||
/**
|
||||
* injection point
|
||||
*/
|
||||
public static void initialize(Object viewStub) {
|
||||
public static void initialize(View youtubeControlsLayout) {
|
||||
try {
|
||||
LogHelper.printDebug(() -> "initializing voting button");
|
||||
RelativeLayout controlsLayout = (RelativeLayout) viewStub;
|
||||
String buttonResourceName = "sb_voting_button";
|
||||
ImageView imageView = controlsLayout.findViewById(getResourceIdentifier(buttonResourceName, "id"));
|
||||
if (imageView == null) {
|
||||
LogHelper.printException(() -> "Couldn't find imageView with \"" + buttonResourceName + "\"");
|
||||
return;
|
||||
}
|
||||
ImageView imageView = Objects.requireNonNull(youtubeControlsLayout.findViewById(
|
||||
getResourceIdentifier("sb_voting_button", "id")));
|
||||
imageView.setVisibility(View.GONE);
|
||||
imageView.setOnClickListener(v -> {
|
||||
SponsorBlockUtils.onVotingClicked(v.getContext());
|
||||
});
|
||||
buttonReference = new WeakReference<>(imageView);
|
||||
|
||||
// Animations
|
||||
if (fadeIn == null) {
|
||||
fadeIn = ReVancedUtils.getResourceAnimation("fade_in");
|
||||
fadeIn.setDuration(ReVancedUtils.getResourceInteger("fade_duration_fast"));
|
||||
fadeOut = ReVancedUtils.getResourceAnimation("fade_out");
|
||||
fadeOut.setDuration(ReVancedUtils.getResourceInteger("fade_duration_scheduled"));
|
||||
}
|
||||
isShowing = true;
|
||||
changeVisibilityImmediate(false);
|
||||
buttonReference = new WeakReference<>(imageView);
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "Unable to set RelativeLayout", ex);
|
||||
}
|
||||
@@ -86,7 +71,7 @@ public class VotingButtonController {
|
||||
return;
|
||||
}
|
||||
if (!immediate) {
|
||||
iView.startAnimation(fadeIn);
|
||||
iView.startAnimation(BottomControlButton.getButtonFadeIn());
|
||||
}
|
||||
iView.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
@@ -95,7 +80,7 @@ public class VotingButtonController {
|
||||
if (iView.getVisibility() == View.VISIBLE) {
|
||||
iView.clearAnimation();
|
||||
if (!immediate) {
|
||||
iView.startAnimation(fadeOut);
|
||||
iView.startAnimation(BottomControlButton.getButtonFadeOut());
|
||||
}
|
||||
iView.setVisibility(View.GONE);
|
||||
}
|
||||
@@ -116,7 +101,6 @@ public class VotingButtonController {
|
||||
ReVancedUtils.verifyOnMainThread();
|
||||
View v = buttonReference.get();
|
||||
if (v == null) {
|
||||
LogHelper.printDebug(() -> "Cannot hide voting button (value is null)");
|
||||
return;
|
||||
}
|
||||
v.setVisibility(View.GONE);
|
||||
|
||||
@@ -6,9 +6,11 @@ import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Toast;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -239,6 +241,31 @@ public class ReVancedUtils {
|
||||
|| (type == ConnectivityManager.TYPE_BLUETOOTH) ? NetworkType.MOBILE : NetworkType.OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a view by setting its layout params to 1x1
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static void HideViewByLayoutParams(View view) {
|
||||
if (view instanceof LinearLayout) {
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams);
|
||||
} else if (view instanceof FrameLayout) {
|
||||
FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams2);
|
||||
} else if (view instanceof RelativeLayout) {
|
||||
RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams3);
|
||||
} else if (view instanceof Toolbar) {
|
||||
Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams4);
|
||||
} else if (view instanceof ViewGroup) {
|
||||
ViewGroup.LayoutParams layoutParams5 = new ViewGroup.LayoutParams(1, 1);
|
||||
view.setLayoutParams(layoutParams5);
|
||||
} else {
|
||||
LogHelper.printDebug(() -> "Hidden view with id " + view.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public enum NetworkType {
|
||||
NONE,
|
||||
MOBILE,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user