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
49 Commits
v0.104.0-d
...
v0.107.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ba636a910 | ||
|
|
68f42fc980 | ||
|
|
8255909b2f | ||
|
|
a91b0363a8 | ||
|
|
e34e75133c | ||
|
|
1185ceedf7 | ||
|
|
2ee18fce69 | ||
|
|
e774be0f05 | ||
|
|
8a7098cce4 | ||
|
|
a93a704c22 | ||
|
|
061ebc6546 | ||
|
|
0c6b22e929 | ||
|
|
7fc73368f1 | ||
|
|
8923fa9fd6 | ||
|
|
15f9c90941 | ||
|
|
c8784a5966 | ||
|
|
d3f8fb9739 | ||
|
|
ff0d64287c | ||
|
|
36fd2844c4 | ||
|
|
0de83fff0e | ||
|
|
24a609288f | ||
|
|
78d56d4fe1 | ||
|
|
27fdcfff08 | ||
|
|
f6f6c93c57 | ||
|
|
a661dac623 | ||
|
|
8cc1b6ea4a | ||
|
|
829895874b | ||
|
|
6b15514885 | ||
|
|
5b53e02613 | ||
|
|
2deacc5035 | ||
|
|
46d70a3e00 | ||
|
|
91ce39378a | ||
|
|
df4b03fed5 | ||
|
|
9f8063880c | ||
|
|
75dad2f307 | ||
|
|
80dc8f0421 | ||
|
|
6f2ae313cf | ||
|
|
cb7063b2b3 | ||
|
|
3b37a3b41f | ||
|
|
13e4be8567 | ||
|
|
be7b6f2a20 | ||
|
|
b9f6c62060 | ||
|
|
8493f57879 | ||
|
|
436a84ee07 | ||
|
|
f2603d3d79 | ||
|
|
246deb1602 | ||
|
|
050766de1d | ||
|
|
6952c50595 | ||
|
|
7fc8e882d8 |
2
.github/config.yml
vendored
Normal file
2
.github/config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
firstPRMergeComment: >
|
||||
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) if you want to receive a contributor role.
|
||||
183
CHANGELOG.md
183
CHANGELOG.md
@@ -1,3 +1,186 @@
|
||||
# [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)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
# [0.106.0-dev.6](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.5...v0.106.0-dev.6) (2023-05-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
# [0.106.0-dev.5](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.4...v0.106.0-dev.5) (2023-04-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/general-ads:** hide new type of ad ([15f9c90](https://github.com/revanced/revanced-integrations/commit/15f9c90941535e93a0779118158c5b4a8accb799))
|
||||
|
||||
# [0.106.0-dev.4](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.3...v0.106.0-dev.4) (2023-04-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [0.106.0-dev.3](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.2...v0.106.0-dev.3) (2023-04-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
# [0.106.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.1...v0.106.0-dev.2) (2023-04-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add appreciation message for new contributors ([78d56d4](https://github.com/revanced/revanced-integrations/commit/78d56d4fe182999555ddf5881a10880e3726782e))
|
||||
|
||||
# [0.106.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.105.1-dev.2...v0.106.0-dev.1) (2023-04-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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.105.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.105.1-dev.1...v0.105.1-dev.2) (2023-04-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
## [0.105.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.105.0...v0.105.1-dev.1) (2023-04-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [0.105.0](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.105.0) (2023-04-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/minimized-playback:** disable minimized playback for shorts ([#371](https://github.com/revanced/revanced-integrations/issues/371)) ([df4b03f](https://github.com/revanced/revanced-integrations/commit/df4b03fed5a0622b18bf4a8dca1940d26a590d8f))
|
||||
* **youtube/return-youtube-dislike:** fix dislikes using wrong font if dark mode is enabled during video playback ([#368](https://github.com/revanced/revanced-integrations/issues/368)) ([3b37a3b](https://github.com/revanced/revanced-integrations/commit/3b37a3b41f7bfbc4a6d6d12e2deb2acd9bb2ccc8))
|
||||
* **youtube/spoof-signature-verification:** additional fixes for subtitle window positions ([#369](https://github.com/revanced/revanced-integrations/issues/369)) ([6f2ae31](https://github.com/revanced/revanced-integrations/commit/6f2ae313cf492166d64e5e33e759f2b234191b64))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/sponsorblock:** automatically hide skip button ([#365](https://github.com/revanced/revanced-integrations/issues/365)) ([75dad2f](https://github.com/revanced/revanced-integrations/commit/75dad2f3071c19aa097ebdc7bd83d1ce9afb78ea))
|
||||
|
||||
# [0.105.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.105.0-dev.1...v0.105.0-dev.2) (2023-04-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/minimized-playback:** disable minimized playback for shorts ([#371](https://github.com/revanced/revanced-integrations/issues/371)) ([df4b03f](https://github.com/revanced/revanced-integrations/commit/df4b03fed5a0622b18bf4a8dca1940d26a590d8f))
|
||||
|
||||
# [0.105.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.104.1-dev.2...v0.105.0-dev.1) (2023-04-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/sponsorblock:** automatically hide skip button ([#365](https://github.com/revanced/revanced-integrations/issues/365)) ([75dad2f](https://github.com/revanced/revanced-integrations/commit/75dad2f3071c19aa097ebdc7bd83d1ce9afb78ea))
|
||||
|
||||
## [0.104.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.104.1-dev.1...v0.104.1-dev.2) (2023-04-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/spoof-signature-verification:** additional fixes for subtitle window positions ([#369](https://github.com/revanced/revanced-integrations/issues/369)) ([6f2ae31](https://github.com/revanced/revanced-integrations/commit/6f2ae313cf492166d64e5e33e759f2b234191b64))
|
||||
|
||||
## [0.104.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.104.1-dev.1) (2023-04-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/return-youtube-dislike:** fix dislikes using wrong font if dark mode is enabled during video playback ([#368](https://github.com/revanced/revanced-integrations/issues/368)) ([3b37a3b](https://github.com/revanced/revanced-integrations/commit/3b37a3b41f7bfbc4a6d6d12e2deb2acd9bb2ccc8))
|
||||
|
||||
# [0.104.0](https://github.com/revanced/revanced-integrations/compare/v0.103.0...v0.104.0) (2023-04-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **spoof-wifi-connection:** fixed crash when wifi is disabled ([#363](https://github.com/revanced/revanced-integrations/issues/363)) ([7fc8e88](https://github.com/revanced/revanced-integrations/commit/7fc8e882d8d268484b6e273fdb0371db2feef1d3))
|
||||
* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#366](https://github.com/revanced/revanced-integrations/issues/366)) ([246deb1](https://github.com/revanced/revanced-integrations/commit/246deb16020adda26d9d0a0449157f4855678d18))
|
||||
* **youtube/sponsorblock:** Include milliseconds in the voting menu ([#362](https://github.com/revanced/revanced-integrations/issues/362)) ([6952c50](https://github.com/revanced/revanced-integrations/commit/6952c505957153d7fdeb7ee42b3f824c155993f5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/wide-searchbar:** rename patch ([8493f57](https://github.com/revanced/revanced-integrations/commit/8493f57879f0075c73932240b61bf0c52efda0ed))
|
||||
* **youtube:** remove non working patch `hide-my-mix` ([436a84e](https://github.com/revanced/revanced-integrations/commit/436a84ee0785e5b0bed1b9a4a02b5be86eff4a4a))
|
||||
|
||||
# [0.104.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.103.1-dev.2...v0.104.0-dev.1) (2023-04-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/wide-searchbar:** rename patch ([2320880](https://github.com/revanced/revanced-integrations/commit/2320880a42bf37335ececf1f8e6cb83bd57f347d))
|
||||
* **youtube:** bump compatibility to `18.15.40` ([#367](https://github.com/revanced/revanced-integrations/issues/367)) ([52a3193](https://github.com/revanced/revanced-integrations/commit/52a31930870b838e766d08c3203bd8cd7ae443ba))
|
||||
* **youtube:** remove non working patch `hide-my-mix` ([98edcdd](https://github.com/revanced/revanced-integrations/commit/98edcdd589c0d3615530b44c8bbaeb94ae599afb))
|
||||
|
||||
## [0.103.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.103.1-dev.1...v0.103.1-dev.2) (2023-04-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#366](https://github.com/revanced/revanced-integrations/issues/366)) ([afd9b6e](https://github.com/revanced/revanced-integrations/commit/afd9b6e30566d735075c16d3f5173e406c965a8c))
|
||||
|
||||
## [0.103.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.103.0...v0.103.1-dev.1) (2023-04-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/sponsorblock:** Include milliseconds in the voting menu ([#362](https://github.com/revanced/revanced-integrations/issues/362)) ([1ada30d](https://github.com/revanced/revanced-integrations/commit/1ada30d5c925f1b0f21d45865240780e4ecd84d7))
|
||||
|
||||
# [0.103.0](https://github.com/revanced/revanced-integrations/compare/v0.102.0...v0.103.0) (2023-04-21)
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ android {
|
||||
dependencies {
|
||||
compileOnly(project(mapOf("path" to ":dummy")))
|
||||
compileOnly("androidx.annotation:annotation:1.6.0")
|
||||
compileOnly("androidx.appcompat:appcompat:1.6.1")
|
||||
compileOnly("androidx.appcompat:appcompat:1.7.0-alpha02")
|
||||
compileOnly("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
|
||||
compileOnly("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
}
|
||||
|
||||
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@@ -20,6 +20,8 @@
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
-dontobfuscate
|
||||
-dontoptimize
|
||||
-keepattributes * # https://www.guardsquare.com/manual/configuration/attributes
|
||||
-keep class app.revanced.** {
|
||||
*;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ final class ButtonsPatch extends Filter {
|
||||
new BlockRule(SettingsEnum.HIDE_LIKE_DISLIKE_BUTTON, "|like_button", "dislike_button"),
|
||||
new BlockRule(SettingsEnum.HIDE_DOWNLOAD_BUTTON, "download_button"),
|
||||
new BlockRule(SettingsEnum.HIDE_PLAYLIST_BUTTON, "save_to_playlist_button"),
|
||||
new BlockRule(SettingsEnum.HIDE_ACTION_BUTTONS, "ContainerType|video_action_button")
|
||||
new BlockRule(SettingsEnum.HIDE_CLIP_BUTTON, "|clip_button.eml|"),
|
||||
new BlockRule(SettingsEnum.HIDE_ACTION_BUTTONS, "ContainerType|video_action_button", "|CellType|CollectionType|CellType|ContainerType|button.eml|")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import app.revanced.integrations.utils.ReVancedUtils;
|
||||
public class CopyVideoUrlPatch {
|
||||
public static void copyUrl(Boolean withTimestamp) {
|
||||
try {
|
||||
String url = String.format("https://youtu.be/%s", VideoInformation.getCurrentVideoId());
|
||||
String url = String.format("https://youtu.be/%s", VideoInformation.getVideoId());
|
||||
if (withTimestamp) {
|
||||
long seconds = VideoInformation.getVideoTime() / 1000;
|
||||
url += String.format("?t=%s", seconds);
|
||||
|
||||
@@ -33,6 +33,7 @@ public final class GeneralAdsPatch extends Filter {
|
||||
var infoPanel = new BlockRule(SettingsEnum.ADREMOVER_INFO_PANEL_REMOVAL, "publisher_transparency_panel", "single_item_information_panel");
|
||||
var latestPosts = new BlockRule(SettingsEnum.ADREMOVER_HIDE_LATEST_POSTS, "post_shelf");
|
||||
var channelGuidelines = new BlockRule(SettingsEnum.ADREMOVER_HIDE_CHANNEL_GUIDELINES, "channel_guidelines_entry_banner");
|
||||
var audioTrackButton = new BlockRule(SettingsEnum.HIDE_AUDIO_TRACK_BUTTON, "multi_feed_icon_button");
|
||||
var artistCard = new BlockRule(SettingsEnum.HIDE_ARTIST_CARDS, "official_card");
|
||||
var selfSponsor = new BlockRule(SettingsEnum.ADREMOVER_SELF_SPONSOR_REMOVAL, "cta_shelf_card");
|
||||
var chapterTeaser = new BlockRule(SettingsEnum.ADREMOVER_CHAPTER_TEASER_REMOVAL, "expandable_metadata", "macro_markers_carousel");
|
||||
@@ -64,8 +65,8 @@ public final class GeneralAdsPatch extends Filter {
|
||||
"carousel_footered_layout",
|
||||
"text_image_button_layout",
|
||||
"primetime_promo",
|
||||
"feature_grid_interstitial",
|
||||
"product_details",
|
||||
"full_width_portrait_image_layout",
|
||||
"brand_video_shelf"
|
||||
);
|
||||
var movieAds = new BlockRule(
|
||||
@@ -97,6 +98,7 @@ public final class GeneralAdsPatch extends Filter {
|
||||
merchandise,
|
||||
infoPanel,
|
||||
channelGuidelines,
|
||||
audioTrackButton,
|
||||
artistCard,
|
||||
selfSponsor,
|
||||
webLinkPanel,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public class HideGetPremiumPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean hideGetPremiumView() {
|
||||
return SettingsEnum.HIDE_GET_PREMIUM.getBoolean();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.integrations.adremover.AdRemoverAPI;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public class HideMixPlaylistsPatch {
|
||||
|
||||
public static void hideMixPlaylists(View view) {
|
||||
if (!SettingsEnum.HIDE_MIX_PLAYLISTS.getBoolean()) return;
|
||||
AdRemoverAPI.HideViewWithLayout1dp(view);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package app.revanced.integrations.patches;
|
||||
|
||||
import static app.revanced.integrations.utils.StringRef.str;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -28,6 +29,7 @@ public class MicroGSupport {
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@TargetApi(26)
|
||||
public static void checkAvailability() {
|
||||
var context = Objects.requireNonNull(ReVancedUtils.getContext());
|
||||
|
||||
@@ -41,10 +43,11 @@ public class MicroGSupport {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
|
||||
try (var client = context.getContentResolver().acquireContentProviderClient(VANCED_MICROG_PROVIDER)) {
|
||||
if (client != null) return;
|
||||
LogHelper.printInfo(() -> "Vanced MicroG is not running in the background");
|
||||
startIntent(context, DONT_KILL_MY_APP_LINK, str("microg_not_running_warning"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.shared.PlayerType;
|
||||
|
||||
public class MinimizedPlaybackPatch {
|
||||
|
||||
public static boolean isNotPlayingShorts(boolean isPipEnabled) {
|
||||
return !PlayerType.getCurrent().isNoneOrHidden() && isPipEnabled;
|
||||
public static boolean isPlaybackNotShort() {
|
||||
return !PlayerType.getCurrent().isNoneOrHidden();
|
||||
}
|
||||
|
||||
public static boolean isMinimizedPlaybackEnabled() {
|
||||
return SettingsEnum.ENABLE_MINIMIZED_PLAYBACK.getBoolean();
|
||||
public static boolean overrideMinimizedPlaybackAvailable() {
|
||||
// This could be done entirely in the patch,
|
||||
// but having a unique method to search for makes manually inspecting the patched apk much easier.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public class NewActionbarPatch {
|
||||
|
||||
//Used by app.revanced.patches.youtube.layout.widesearchbar.patch.WideSearchbarPatch
|
||||
public static boolean getNewActionBar() {
|
||||
return SettingsEnum.WIDE_SEARCHBAR.getBoolean(); // TODO: maybe this has to be inverted
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,23 +2,110 @@ package app.revanced.integrations.patches;
|
||||
|
||||
import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote;
|
||||
|
||||
import android.text.SpannableString;
|
||||
import android.text.Editable;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextWatcher;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
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;
|
||||
|
||||
public class ReturnYouTubeDislikePatch {
|
||||
|
||||
/**
|
||||
* Resource identifier of old UI dislike button.
|
||||
*/
|
||||
private static final int OLD_UI_DISLIKE_BUTTON_RESOURCE_ID
|
||||
= ReVancedUtils.getResourceIdentifier("dislike_button", "id");
|
||||
|
||||
/**
|
||||
* Dislikes text label used by old UI.
|
||||
*/
|
||||
@NonNull
|
||||
private static WeakReference<TextView> oldUITextViewRef = new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Original old UI 'Dislikes' text before patch modifications.
|
||||
* Required to reset the dislikes when changing videos and RYD is not available.
|
||||
* Set only once during the first load.
|
||||
*/
|
||||
private static Spanned oldUIOriginalSpan;
|
||||
|
||||
/**
|
||||
* Replacement span that contains dislike value. Used by {@link #oldUiTextWatcher}.
|
||||
*/
|
||||
@Nullable
|
||||
private static Spanned oldUIReplacementSpan;
|
||||
|
||||
/**
|
||||
* Old UI dislikes can be set multiple times by YouTube.
|
||||
* To prevent it from reverting changes made here, this listener overrides any future changes YouTube makes.
|
||||
*/
|
||||
private static final TextWatcher oldUiTextWatcher = new TextWatcher() {
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (oldUIReplacementSpan == null || oldUIReplacementSpan.toString().equals(s.toString())) {
|
||||
return;
|
||||
}
|
||||
s.replace(0, s.length(), oldUIReplacementSpan);
|
||||
}
|
||||
};
|
||||
|
||||
private static void updateOldUIDislikesTextView() {
|
||||
TextView oldUITextView = oldUITextViewRef.get();
|
||||
if (oldUITextView == null) {
|
||||
return;
|
||||
}
|
||||
oldUIReplacementSpan = ReturnYouTubeDislike.getDislikesSpanForRegularVideo(oldUIOriginalSpan, false);
|
||||
if (!oldUIReplacementSpan.equals(oldUITextView.getText())) {
|
||||
oldUITextView.setText(oldUIReplacementSpan);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. Called on main thread.
|
||||
*
|
||||
* Used when spoofing the older app versions of {@link SpoofAppVersionPatch}.
|
||||
*/
|
||||
public static void setOldUILayoutDislikes(int buttonViewResourceId, @NonNull TextView textView) {
|
||||
try {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()
|
||||
|| buttonViewResourceId != OLD_UI_DISLIKE_BUTTON_RESOURCE_ID) {
|
||||
return;
|
||||
}
|
||||
if (oldUIOriginalSpan == null) {
|
||||
// Use value of the first instance, as it appears TextViews can be recycled
|
||||
// and might contain dislikes previously added by the patch.
|
||||
oldUIOriginalSpan = (Spanned) textView.getText();
|
||||
}
|
||||
oldUITextViewRef = new WeakReference<>(textView);
|
||||
// No way to check if a listener is already attached, so remove and add again.
|
||||
textView.removeTextChangedListener(oldUiTextWatcher);
|
||||
textView.addTextChangedListener(oldUiTextWatcher);
|
||||
|
||||
updateOldUIDislikesTextView();
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "setOldUILayoutDislikes failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void newVideoLoaded(String videoId) {
|
||||
public static void newVideoLoaded(@NonNull String videoId) {
|
||||
try {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) return;
|
||||
ReturnYouTubeDislike.newVideoLoaded(videoId);
|
||||
@@ -47,16 +134,25 @@ 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(() -> "onComponentCreated AtomicReference failure", ex);
|
||||
LogHelper.printException(() -> "onLithoTextLoaded failure", ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
@@ -71,10 +167,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);
|
||||
}
|
||||
@@ -97,6 +190,7 @@ public class ReturnYouTubeDislikePatch {
|
||||
for (Vote v : Vote.values()) {
|
||||
if (v.value == vote) {
|
||||
ReturnYouTubeDislike.sendVote(v);
|
||||
updateOldUIDislikesTextView();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,8 @@ import app.revanced.integrations.settings.SettingsEnum;
|
||||
public class SpoofAppVersionPatch {
|
||||
|
||||
public static String getYouTubeVersionOverride(String version) {
|
||||
if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()){
|
||||
// Override with the most recent version that does not show the new UI player layout.
|
||||
// If the new UI shows up for some users, then change this to an older version (such as 17.29.34).
|
||||
return "17.30.34";
|
||||
if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()) {
|
||||
return SettingsEnum.SPOOF_APP_VERSION_TARGET.getString();
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.shared.PlayerType;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
|
||||
|
||||
public class SpoofSignatureVerificationPatch {
|
||||
/**
|
||||
* Protobuf parameters used for autoplay in scrim.
|
||||
@@ -28,6 +31,28 @@ public class SpoofSignatureVerificationPatch {
|
||||
"SAFg" // Autoplay in scrim
|
||||
};
|
||||
|
||||
/**
|
||||
* On app first start, the first video played usually contains a single non-default window setting value
|
||||
* and all other subtitle settings for the video are (incorrect) default shorts window settings.
|
||||
* For this situation, the shorts settings must be replaced.
|
||||
*
|
||||
* But some videos use multiple text positions on screen (such as https://youtu.be/3hW1rMNC89o),
|
||||
* and by chance many of the subtitles uses window positions that match a default shorts position.
|
||||
* To handle these videos, selectively allowing the shorts specific window settings to 'pass thru' unchanged,
|
||||
* but only if the video contains multiple non-default subtitle window positions.
|
||||
*
|
||||
* Do not enable 'pass thru mode' until this many non default subtitle settings are observed for a single video.
|
||||
*/
|
||||
private static final int NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU = 2;
|
||||
|
||||
/**
|
||||
* The number of non default subtitle settings encountered for the current video.
|
||||
*/
|
||||
private static int numberOfNonDefaultSettingsObserved;
|
||||
|
||||
@Nullable
|
||||
private static String currentVideoId;
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
@@ -49,7 +74,7 @@ public class SpoofSignatureVerificationPatch {
|
||||
if (isPlayingFeed) {
|
||||
// Videos in feed won't autoplay with sound.
|
||||
return PROTOBUF_PARAMETER_SCRIM + PROTOBUF_PARAMETER_SHORTS;
|
||||
} else{
|
||||
} else {
|
||||
// Spoof the parameter to prevent playback issues.
|
||||
return PROTOBUF_PARAMETER_SHORTS;
|
||||
}
|
||||
@@ -108,7 +133,7 @@ public class SpoofSignatureVerificationPatch {
|
||||
final boolean signatureSpoofing = SettingsEnum.SIGNATURE_SPOOFING.getBoolean();
|
||||
if (SettingsEnum.DEBUG.getBoolean()) {
|
||||
if (ap != lastAp || ah != lastAh || av != lastAv || vs != lastVs || sd != lastSd) {
|
||||
LogHelper.printDebug(() -> "video: " + VideoInformation.getCurrentVideoId() + " spoof: " + signatureSpoofing
|
||||
LogHelper.printDebug(() -> "video: " + VideoInformation.getVideoId() + " spoof: " + signatureSpoofing
|
||||
+ " ap:" + ap + " ah:" + ah + " av:" + av + " vs:" + vs + " sd:" + sd);
|
||||
lastAp = ap;
|
||||
lastAh = ah;
|
||||
@@ -121,21 +146,44 @@ public class SpoofSignatureVerificationPatch {
|
||||
// Videos with custom captions that specify screen positions appear to always have correct screen positions (even with spoofing).
|
||||
// But for auto generated and most other captions, the spoof incorrectly gives various default Shorts caption settings.
|
||||
// Check for these known default shorts captions parameters, and replace with the known correct values.
|
||||
if (signatureSpoofing && !PlayerType.getCurrent().isNoneOrHidden()) { // video is not a Short or Story
|
||||
//
|
||||
// If a regular video uses a custom subtitle setting that match a default short setting,
|
||||
// then this will incorrectly replace the setting.
|
||||
// But, if the video uses multiple subtitles in different screen locations, then detect the non-default values
|
||||
// and do not replace any window settings for the video (regardless if they match a shorts default).
|
||||
if (signatureSpoofing && !PlayerType.getCurrent().isNoneOrHidden()
|
||||
&& numberOfNonDefaultSettingsObserved < NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU) {
|
||||
for (SubtitleWindowReplacementSettings setting : SubtitleWindowReplacementSettings.values()) {
|
||||
if (setting.match(ap, ah, av, vs, sd)) {
|
||||
return setting.replacementSetting();
|
||||
}
|
||||
}
|
||||
// Parameters are either subtitles with custom positions, or a set of unidentified (and incorrect) default parameters.
|
||||
// The subtitles could be forced to the bottom no matter what, but that would override custom screen positions.
|
||||
// For now, just return the original parameters.
|
||||
|
||||
numberOfNonDefaultSettingsObserved++;
|
||||
LogHelper.printDebug(() ->
|
||||
numberOfNonDefaultSettingsObserved < NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU
|
||||
? "Non default subtitle found."
|
||||
: "Multiple non default subtitles found. Allowing all subtitles for this video to pass thru unchanged.");
|
||||
}
|
||||
|
||||
// No matches, pass back the original values
|
||||
return new int[]{ap, ah, av};
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setCurrentVideoId(@NonNull String videoId) {
|
||||
try {
|
||||
if (videoId.equals(currentVideoId)) {
|
||||
return;
|
||||
}
|
||||
currentVideoId = videoId;
|
||||
numberOfNonDefaultSettingsObserved = 0;
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "setCurrentVideoId failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Known incorrect default Shorts subtitle parameters, and the corresponding correct (non-Shorts) values.
|
||||
@@ -152,8 +200,8 @@ public class SpoofSignatureVerificationPatch {
|
||||
final int ap, ah, av;
|
||||
final boolean vs, sd;
|
||||
|
||||
// replacement values
|
||||
final int replacementAp, replacementAh, replacementAv;
|
||||
// replacement int values
|
||||
final int[] replacement;
|
||||
|
||||
SubtitleWindowReplacementSettings(int ap, int ah, int av, boolean vs, boolean sd,
|
||||
int replacementAp, int replacementAh, int replacementAv) {
|
||||
@@ -162,9 +210,7 @@ public class SpoofSignatureVerificationPatch {
|
||||
this.av = av;
|
||||
this.vs = vs;
|
||||
this.sd = sd;
|
||||
this.replacementAp = replacementAp;
|
||||
this.replacementAh = replacementAh;
|
||||
this.replacementAv = replacementAv;
|
||||
this.replacement = new int[]{replacementAp, replacementAh, replacementAv};
|
||||
}
|
||||
|
||||
boolean match(int ap, int ah, int av, boolean vs, boolean sd) {
|
||||
@@ -172,7 +218,7 @@ public class SpoofSignatureVerificationPatch {
|
||||
}
|
||||
|
||||
int[] replacementSetting() {
|
||||
return new int[]{replacementAp, replacementAh, replacementAv};
|
||||
return replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public final class VideoInformation {
|
||||
try {
|
||||
seekMethod = thisRef.getClass().getMethod(SEEK_METHOD_NAME, Long.TYPE);
|
||||
seekMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "Failed to initialize", ex);
|
||||
}
|
||||
}
|
||||
@@ -141,26 +141,25 @@ public final class VideoInformation {
|
||||
* @return The id of the video. Empty string if not set yet.
|
||||
*/
|
||||
@NonNull
|
||||
public static String getCurrentVideoId() {
|
||||
public static String getVideoId() {
|
||||
return videoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current playback speed.
|
||||
*/
|
||||
public static float getCurrentPlaybackSpeed() {
|
||||
public static float getPlaybackSpeed() {
|
||||
return playbackSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of the current video playing.
|
||||
* Includes Shorts playback.
|
||||
* Length of the current video playing. Includes Shorts and YouTube Stories.
|
||||
*
|
||||
* @return The length of the video in milliseconds.
|
||||
* If the video is not yet loaded, or if the video is playing in the background with no video visible,
|
||||
* then this returns zero.
|
||||
*/
|
||||
public static long getCurrentVideoLength() {
|
||||
public static long getVideoLength() {
|
||||
return videoLength;
|
||||
}
|
||||
|
||||
@@ -172,7 +171,7 @@ public final class VideoInformation {
|
||||
* should use the callback video time and avoid using this method
|
||||
* (in situations of recursive hook callbacks, the value returned here may be outdated).
|
||||
*
|
||||
* Includes Shorts playback.
|
||||
* Includes Shorts and YouTube Stories.
|
||||
*
|
||||
* @return The time of the video in milliseconds. -1 if not set yet.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.integrations.patches;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public final class WideSearchbarPatch {
|
||||
public static boolean enableWideSearchbar() {
|
||||
return SettingsEnum.WIDE_SEARCHBAR.getBoolean();
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public final class RememberPlaybackSpeedPatch {
|
||||
* Overrides the video speed. Called after video loads, and immediately after user selects a different playback speed
|
||||
*/
|
||||
public static float getPlaybackSpeedOverride() {
|
||||
return VideoInformation.getCurrentPlaybackSpeed();
|
||||
return VideoInformation.getPlaybackSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
@@ -0,0 +1,30 @@
|
||||
package app.revanced.integrations.patches.theme;
|
||||
|
||||
import android.graphics.Color;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public final class ThemePatch {
|
||||
public static final int DEFAULT_SEEKBAR_COLOR = 0xffff0000;
|
||||
|
||||
public static final int ORIGINAL_SEEKBAR_CLICKED_COLOR = -65536;
|
||||
|
||||
private static void resetSeekbarColor() {
|
||||
ReVancedUtils.showToastShort("Invalid seekbar color value. Using default value.");
|
||||
SettingsEnum.SEEKBAR_COLOR.saveValue("#" + Integer.toHexString(DEFAULT_SEEKBAR_COLOR));
|
||||
}
|
||||
|
||||
public static int getSeekbarClickedColorValue(final int colorValue) {
|
||||
// YouTube uses a specific color when the seekbar is clicked. Override in that case.
|
||||
return colorValue == ORIGINAL_SEEKBAR_CLICKED_COLOR ? getSeekbarColorValue() : colorValue;
|
||||
}
|
||||
|
||||
public static int getSeekbarColorValue() {
|
||||
try {
|
||||
return Color.parseColor(SettingsEnum.SEEKBAR_COLOR.getString());
|
||||
} catch (IllegalArgumentException exception) {
|
||||
resetSeekbarColor();
|
||||
return DEFAULT_SEEKBAR_COLOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.ImageSpan;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
@@ -75,7 +76,7 @@ public class ReturnYouTubeDislike {
|
||||
/**
|
||||
* If {@link #currentVideoId} and the RYD data is for the last shorts loaded.
|
||||
*/
|
||||
private static volatile boolean lastVideoLoadedWasShort;
|
||||
private static volatile boolean dislikeDataIsShort;
|
||||
|
||||
/**
|
||||
* Stores the results of the vote api fetch, and used as a barrier to wait until fetch completes.
|
||||
@@ -140,7 +141,7 @@ public class ReturnYouTubeDislike {
|
||||
LogHelper.printDebug(() -> "Clearing data");
|
||||
}
|
||||
currentVideoId = videoId;
|
||||
lastVideoLoadedWasShort = false;
|
||||
dislikeDataIsShort = false;
|
||||
voteFetchFuture = null;
|
||||
originalDislikeSpan = null;
|
||||
replacementLikeDislikeSpan = null;
|
||||
@@ -197,7 +198,7 @@ public class ReturnYouTubeDislike {
|
||||
// If a Short is opened while a regular video is on screen, this will incorrectly set this as false.
|
||||
// But this check is needed to fix unusual situations of opening/closing the app
|
||||
// while both a regular video and a short are on screen.
|
||||
lastVideoLoadedWasShort = PlayerType.getCurrent().isNoneOrHidden();
|
||||
dislikeDataIsShort = PlayerType.getCurrent().isNoneOrHidden();
|
||||
|
||||
// No need to wrap the call in a try/catch,
|
||||
// as any exceptions are propagated out in the later Future#Get call.
|
||||
@@ -206,41 +207,28 @@ 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;
|
||||
}
|
||||
|
||||
if (lastVideoLoadedWasShort) {
|
||||
@NonNull
|
||||
public static Spanned getDislikesSpanForRegularVideo(@NonNull Spanned original, boolean isSegmentedButton) {
|
||||
if (dislikeDataIsShort) {
|
||||
// user:
|
||||
// 1, opened a video
|
||||
// 2. opened a short (without closing the regular video)
|
||||
// 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((Spannable) original, isSegmentedButton);
|
||||
return waitForFetchAndUpdateReplacementSpan(original, isSegmentedButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a Shorts dislike Spannable is created.
|
||||
*/
|
||||
public static SpannableString getDislikeSpanForShort(@NonNull Spanned original) {
|
||||
lastVideoLoadedWasShort = true; // it's now certain the video and data are a short
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -249,31 +237,27 @@ 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) {
|
||||
String oldSpannableString = oldSpannable.toString();
|
||||
if (replacementLikeDislikeSpan.toString().equals(oldSpannableString)) {
|
||||
if (spansHaveEqualTextAndColor(replacementLikeDislikeSpan, oldSpannable)) {
|
||||
LogHelper.printDebug(() -> "Ignoring previously created dislikes span");
|
||||
return null;
|
||||
return oldSpannable;
|
||||
}
|
||||
if (originalDislikeSpan.toString().equals(oldSpannableString)) {
|
||||
if (spansHaveEqualTextAndColor(Objects.requireNonNull(originalDislikeSpan), oldSpannable)) {
|
||||
LogHelper.printDebug(() -> "Replacing span with previously created dislike span");
|
||||
return replacementLikeDislikeSpan;
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -284,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);
|
||||
@@ -304,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) {
|
||||
@@ -313,7 +297,7 @@ public class ReturnYouTubeDislike {
|
||||
try {
|
||||
// Must make a local copy of videoId, since it may change between now and when the vote thread runs.
|
||||
String videoIdToVoteFor = getCurrentVideoId();
|
||||
if (videoIdToVoteFor == null || lastVideoLoadedWasShort != PlayerType.getCurrent().isNoneOrHidden()) {
|
||||
if (videoIdToVoteFor == null || dislikeDataIsShort != PlayerType.getCurrent().isNoneOrHidden()) {
|
||||
// User enabled RYD after starting playback of a video.
|
||||
// Or shorts was loaded with regular video present, then shorts was closed,
|
||||
// and then user voted on the now visible original video.
|
||||
@@ -470,6 +454,27 @@ public class ReturnYouTubeDislike {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean spansHaveEqualTextAndColor(@NonNull Spanned one, @NonNull Spanned two) {
|
||||
// Cannot use equals on the span, because many of the inner styling spans do not implement equals.
|
||||
// Instead, compare the underlying text and the text color to handle when dark mode is changed.
|
||||
// Cannot compare the status of device dark mode, as Litho components are updated just before dark mode status changes.
|
||||
if (!one.toString().equals(two.toString())) {
|
||||
return false;
|
||||
}
|
||||
ForegroundColorSpan[] oneColors = one.getSpans(0, one.length(), ForegroundColorSpan.class);
|
||||
ForegroundColorSpan[] twoColors = two.getSpans(0, two.length(), ForegroundColorSpan.class);
|
||||
final int oneLength = oneColors.length;
|
||||
if (oneLength != twoColors.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < oneLength; i++) {
|
||||
if (oneColors[i].getForegroundColor() != twoColors[i].getForegroundColor()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static SpannableString newSpannableWithDislikes(@NonNull Spanned sourceStyling, @NonNull RYDVoteData voteData) {
|
||||
return newSpanUsingStylingOfAnotherSpan(sourceStyling,
|
||||
SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean()
|
||||
|
||||
@@ -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,31 +1,26 @@
|
||||
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 app.revanced.integrations.patches.theme.ThemePatch;
|
||||
|
||||
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
|
||||
// TODO: DOWNLOAD_PATH("revanced_download_path", STRING, Environment.getExternalStorageDirectory().getPath() + "/Download"),
|
||||
DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE, true),
|
||||
DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE),
|
||||
DOWNLOADS_PACKAGE_NAME("revanced_downloads_package_name", STRING, "org.schabi.newpipe" /* NewPipe */, parents(DOWNLOADS_BUTTON_SHOWN)),
|
||||
|
||||
// Copy video URL settings
|
||||
COPY_VIDEO_URL_BUTTON_SHOWN("revanced_copy_video_url_enabled", BOOLEAN, TRUE, true),
|
||||
COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE, true),
|
||||
COPY_VIDEO_URL_BUTTON_SHOWN("revanced_copy_video_url_enabled", BOOLEAN, TRUE),
|
||||
COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE),
|
||||
|
||||
// Video settings
|
||||
OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS("revanced_use_old_style_quality_settings", BOOLEAN, TRUE),
|
||||
@@ -74,44 +69,50 @@ public enum SettingsEnum {
|
||||
HIDE_LIKE_DISLIKE_BUTTON("revanced_hide_like_dislike_button", BOOLEAN, FALSE),
|
||||
HIDE_DOWNLOAD_BUTTON("revanced_hide_download_button", BOOLEAN, FALSE),
|
||||
HIDE_PLAYLIST_BUTTON("revanced_hide_playlist_button", BOOLEAN, FALSE),
|
||||
HIDE_CLIP_BUTTON("revanced_hide_clip_button", BOOLEAN, FALSE, "revanced_hide_clip_button_user_dialog_message"),
|
||||
HIDE_ACTION_BUTTONS("revanced_hide_action_buttons", BOOLEAN, FALSE),
|
||||
|
||||
// Layout settings
|
||||
DISABLE_STARTUP_SHORTS_PLAYER("revanced_startup_shorts_player_enabled", BOOLEAN, FALSE),
|
||||
HIDE_ALBUM_CARDS("revanced_hide_album_cards", BOOLEAN, FALSE, true),
|
||||
HIDE_ARTIST_CARDS("revanced_hide_artist_cards", BOOLEAN, FALSE),
|
||||
HIDE_AUDIO_TRACK_BUTTON("revanced_hide_audio_track_button", BOOLEAN, FALSE),
|
||||
HIDE_AUTOPLAY_BUTTON("revanced_hide_autoplay_button", BOOLEAN, TRUE, true),
|
||||
HIDE_BREAKING_NEWS("revanced_hide_breaking_news", BOOLEAN, TRUE, true),
|
||||
HIDE_CAPTIONS_BUTTON("revanced_hide_captions_button", BOOLEAN, FALSE),
|
||||
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),
|
||||
HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", BOOLEAN, TRUE, true),
|
||||
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_MIX_PLAYLISTS("revanced_hide_mix_playlists", BOOLEAN, FALSE, true),
|
||||
HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE),
|
||||
HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true),
|
||||
HIDE_SEEKBAR("revanced_hide_seekbar", BOOLEAN, FALSE),
|
||||
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),
|
||||
HIDE_WATCH_IN_VR("revanced_hide_watch_in_vr", BOOLEAN, FALSE, true),
|
||||
PLAYER_POPUP_PANELS("revanced_player_popup_panels_enabled", BOOLEAN, FALSE),
|
||||
SPOOF_APP_VERSION("revanced_spoof_app_version", BOOLEAN, FALSE, true, "revanced_spoof_app_version_user_dialog_message"),
|
||||
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, Integer.toHexString(ThemePatch.DEFAULT_SEEKBAR_COLOR), true),
|
||||
|
||||
// Misc. Settings
|
||||
SIGNATURE_SPOOFING("revanced_spoof_signature_verification", BOOLEAN, TRUE, "revanced_spoof_signature_verification_user_dialog_message"),
|
||||
CAPTIONS_ENABLED("revanced_autocaptions_enabled", BOOLEAN, FALSE),
|
||||
DISABLE_ZOOM_HAPTICS("revanced_disable_zoom_haptics", BOOLEAN, TRUE),
|
||||
ENABLE_EXTERNAL_BROWSER("revanced_enable_external_browser", BOOLEAN, TRUE, true),
|
||||
ENABLE_MINIMIZED_PLAYBACK("revanced_enable_minimized_playback", BOOLEAN, TRUE),
|
||||
PREFERRED_AUTO_REPEAT("revanced_pref_auto_repeat", BOOLEAN, FALSE),
|
||||
TAP_SEEKING_ENABLED("revanced_enable_tap_seeking", BOOLEAN, TRUE),
|
||||
USE_HDR_AUTO_BRIGHTNESS("revanced_pref_hdr_autobrightness", BOOLEAN, TRUE),
|
||||
@@ -147,7 +148,8 @@ public enum SettingsEnum {
|
||||
SB_ENABLED("sb-enabled", BOOLEAN, TRUE, SPONSOR_BLOCK),
|
||||
SB_VOTING_ENABLED("sb-voting-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_CREATE_NEW_SEGMENT_ENABLED("sb-new-segment-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_USE_COMPACT_SKIPBUTTON("sb-use-compact-skip-button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_USE_COMPACT_SKIP_BUTTON("sb-use-compact-skip-button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_AUTO_HIDE_SKIP_BUTTON("sb-auto-hide-skip-segment-button", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_SHOW_TOAST_ON_SKIP("show-toast", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_TRACK_SKIP_COUNT("count-skips", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
|
||||
SB_UUID("uuid", STRING, "", SPONSOR_BLOCK),
|
||||
|
||||
@@ -20,33 +20,17 @@ import app.revanced.integrations.settings.SharedPrefCategory;
|
||||
public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
|
||||
/**
|
||||
* If ReturnYouTubeDislike is enabled
|
||||
*/
|
||||
private SwitchPreference enabledPreference;
|
||||
|
||||
/**
|
||||
* If dislikes are shown as percentage
|
||||
* If dislikes are shown as percentage.
|
||||
*/
|
||||
private SwitchPreference percentagePreference;
|
||||
|
||||
/**
|
||||
* If segmented like/dislike button uses smaller compact layout
|
||||
* If segmented like/dislike button uses smaller compact layout.
|
||||
*/
|
||||
private SwitchPreference compactLayoutPreference;
|
||||
|
||||
private void updateUIState() {
|
||||
enabledPreference.setSummary(SettingsEnum.RYD_ENABLED.getBoolean()
|
||||
? str("revanced_ryd_enable_summary_on")
|
||||
: str("revanced_ryd_enable_summary_off"));
|
||||
|
||||
percentagePreference.setSummary(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean()
|
||||
? str("revanced_ryd_dislike_percentage_summary_on")
|
||||
: str("revanced_ryd_dislike_percentage_summary_off"));
|
||||
percentagePreference.setEnabled(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.isAvailable());
|
||||
|
||||
compactLayoutPreference.setSummary(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getBoolean()
|
||||
? str("revanced_ryd_compact_layout_summary_on")
|
||||
: str("revanced_ryd_compact_layout_summary_off"));
|
||||
compactLayoutPreference.setEnabled(SettingsEnum.RYD_USE_COMPACT_LAYOUT.isAvailable());
|
||||
}
|
||||
|
||||
@@ -59,9 +43,11 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context);
|
||||
setPreferenceScreen(preferenceScreen);
|
||||
|
||||
enabledPreference = new SwitchPreference(context);
|
||||
SwitchPreference enabledPreference = new SwitchPreference(context);
|
||||
enabledPreference.setChecked(SettingsEnum.RYD_ENABLED.getBoolean());
|
||||
enabledPreference.setTitle(str("revanced_ryd_enable_title"));
|
||||
enabledPreference.setSummaryOn(str("revanced_ryd_enable_summary_on"));
|
||||
enabledPreference.setSummaryOff(str("revanced_ryd_enable_summary_off"));
|
||||
enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
final boolean rydIsEnabled = (Boolean) newValue;
|
||||
SettingsEnum.RYD_ENABLED.saveValue(rydIsEnabled);
|
||||
@@ -75,6 +61,8 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
percentagePreference = new SwitchPreference(context);
|
||||
percentagePreference.setChecked(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean());
|
||||
percentagePreference.setTitle(str("revanced_ryd_dislike_percentage_title"));
|
||||
percentagePreference.setSummaryOn(str("revanced_ryd_dislike_percentage_summary_on"));
|
||||
percentagePreference.setSummaryOff(str("revanced_ryd_dislike_percentage_summary_off"));
|
||||
percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.saveValue(newValue);
|
||||
ReturnYouTubeDislike.clearCache();
|
||||
@@ -86,6 +74,8 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
compactLayoutPreference = new SwitchPreference(context);
|
||||
compactLayoutPreference.setChecked(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getBoolean());
|
||||
compactLayoutPreference.setTitle(str("revanced_ryd_compact_layout_title"));
|
||||
compactLayoutPreference.setSummaryOn(str("revanced_ryd_compact_layout_summary_on"));
|
||||
compactLayoutPreference.setSummaryOff(str("revanced_ryd_compact_layout_summary_off"));
|
||||
compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||
SettingsEnum.RYD_USE_COMPACT_LAYOUT.saveValue(newValue);
|
||||
ReturnYouTubeDislike.clearCache();
|
||||
@@ -185,7 +175,7 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
private String createSummaryText(int value, String summaryStringZeroKey, String summaryStringOneOrMoreKey) {
|
||||
private static String createSummaryText(int value, String summaryStringZeroKey, String summaryStringOneOrMoreKey) {
|
||||
if (value == 0) {
|
||||
return str(summaryStringZeroKey);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,6 @@ import java.lang.ref.WeakReference;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
@@ -157,13 +156,13 @@ public class SponsorBlockUtils {
|
||||
private static final DialogInterface.OnClickListener segmentVoteClickListener = (dialog, which) -> {
|
||||
try {
|
||||
final Context context = ((AlertDialog) dialog).getContext();
|
||||
SponsorSegment[] currentSegments = SegmentPlaybackController.getSegmentsOfCurrentVideo();
|
||||
if (currentSegments == null || currentSegments.length == 0) {
|
||||
SponsorSegment[] segments = SegmentPlaybackController.getSegments();
|
||||
if (segments == null || segments.length == 0) {
|
||||
// should never be reached
|
||||
LogHelper.printException(() -> "Segment is no longer available on the client");
|
||||
return;
|
||||
}
|
||||
SponsorSegment segment = currentSegments[which];
|
||||
SponsorSegment segment = segments[which];
|
||||
|
||||
SegmentVote[] voteOptions = (segment.category == SegmentCategory.HIGHLIGHT)
|
||||
? SegmentVote.voteTypesWithoutCategoryChange // highlight segments cannot change category
|
||||
@@ -218,8 +217,8 @@ public class SponsorBlockUtils {
|
||||
final String uuid = SettingsEnum.SB_UUID.getString();
|
||||
final long start = newSponsorSegmentStartMillis;
|
||||
final long end = newSponsorSegmentEndMillis;
|
||||
final String videoId = VideoInformation.getCurrentVideoId();
|
||||
final long videoLength = VideoInformation.getCurrentVideoLength();
|
||||
final String videoId = VideoInformation.getVideoId();
|
||||
final long videoLength = VideoInformation.getVideoLength();
|
||||
final SegmentCategory segmentCategory = newUserCreatedSegmentCategory;
|
||||
if (start < 0 || end < 0 || start >= end || videoLength <= 0 || videoId.isEmpty()
|
||||
|| segmentCategory == null || uuid.isEmpty()) {
|
||||
@@ -287,33 +286,33 @@ public class SponsorBlockUtils {
|
||||
public static void onVotingClicked(@NonNull Context context) {
|
||||
try {
|
||||
ReVancedUtils.verifyOnMainThread();
|
||||
SponsorSegment[] currentSegments = SegmentPlaybackController.getSegmentsOfCurrentVideo();
|
||||
if (currentSegments == null || currentSegments.length == 0) {
|
||||
// button is hidden if no segments exist.
|
||||
SponsorSegment[] segments = SegmentPlaybackController.getSegments();
|
||||
if (segments == null || segments.length == 0) {
|
||||
// Button is hidden if no segments exist.
|
||||
// But if prior video had segments, and current video does not,
|
||||
// then the button persists until the overlay fades out (this is intentional, as abruptly hiding the button is jarring)
|
||||
// then the button persists until the overlay fades out (this is intentional, as abruptly hiding the button is jarring).
|
||||
ReVancedUtils.showToastShort(str("sb_vote_no_segments"));
|
||||
return;
|
||||
}
|
||||
|
||||
// use same time formatting as shown in the video player
|
||||
final long currentVideoLength = VideoInformation.getCurrentVideoLength();
|
||||
final long videoLength = VideoInformation.getVideoLength();
|
||||
final String formatPattern;
|
||||
if (currentVideoLength < (10 * 60 * 1000)) {
|
||||
formatPattern = "m:ss"; // less than 10 minutes
|
||||
} else if (currentVideoLength < (60 * 60 * 1000)) {
|
||||
formatPattern = "mm:ss"; // less than 1 hour
|
||||
} else if (currentVideoLength < (10 * 60 * 60 * 1000)) {
|
||||
formatPattern = "H:mm:ss"; // less than 10 hours
|
||||
if (videoLength < (10 * 60 * 1000)) {
|
||||
formatPattern = "m:ss.SSS"; // less than 10 minutes
|
||||
} else if (videoLength < (60 * 60 * 1000)) {
|
||||
formatPattern = "mm:ss.SSS"; // less than 1 hour
|
||||
} else if (videoLength < (10 * 60 * 60 * 1000)) {
|
||||
formatPattern = "H:mm:ss.SSS"; // less than 10 hours
|
||||
} else {
|
||||
formatPattern = "HH:mm:ss"; // why is this on YouTube
|
||||
formatPattern = "HH:mm:ss.SSS"; // why is this on YouTube
|
||||
}
|
||||
voteSegmentTimeFormatter.applyPattern(formatPattern);
|
||||
|
||||
final int numberOfSegments = currentSegments.length;
|
||||
final int numberOfSegments = segments.length;
|
||||
CharSequence[] titles = new CharSequence[numberOfSegments];
|
||||
for (int i = 0; i < numberOfSegments; i++) {
|
||||
SponsorSegment segment = currentSegments[i];
|
||||
SponsorSegment segment = segments[i];
|
||||
if (segment.category == SegmentCategory.UNSUBMITTED) {
|
||||
continue;
|
||||
}
|
||||
@@ -364,14 +363,11 @@ public class SponsorBlockUtils {
|
||||
} else if (newSponsorSegmentStartMillis >= newSponsorSegmentEndMillis) {
|
||||
ReVancedUtils.showToastShort(str("sb_new_segment_start_is_before_end"));
|
||||
} else {
|
||||
SegmentPlaybackController.removeUnsubmittedSegments(); // If user hits preview more than once before playing.
|
||||
SegmentPlaybackController.addUnsubmittedSegment(
|
||||
new SponsorSegment(SegmentCategory.UNSUBMITTED, null,
|
||||
newSponsorSegmentStartMillis, newSponsorSegmentEndMillis, false));
|
||||
VideoInformation.seekTo(newSponsorSegmentStartMillis - 2500);
|
||||
final SponsorSegment[] original = SegmentPlaybackController.getSegmentsOfCurrentVideo();
|
||||
final SponsorSegment[] segments = original == null ? new SponsorSegment[1] : Arrays.copyOf(original, original.length + 1);
|
||||
|
||||
segments[segments.length - 1] = new SponsorSegment(SegmentCategory.UNSUBMITTED, null,
|
||||
newSponsorSegmentStartMillis, newSponsorSegmentEndMillis, false);
|
||||
|
||||
SegmentPlaybackController.setSegmentsOfCurrentVideo(segments);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printException(() -> "onPreviewClicked failure", ex);
|
||||
|
||||
@@ -300,7 +300,7 @@ public enum SegmentCategory {
|
||||
*/
|
||||
@NonNull
|
||||
StringRef getSkipButtonText(long segmentStartTime, long videoLength) {
|
||||
if (SettingsEnum.SB_USE_COMPACT_SKIPBUTTON.getBoolean()) {
|
||||
if (SettingsEnum.SB_USE_COMPACT_SKIP_BUTTON.getBoolean()) {
|
||||
return (this == SegmentCategory.HIGHLIGHT)
|
||||
? skipSponsorTextCompactHighlight
|
||||
: skipSponsorTextCompact;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package app.revanced.integrations.sponsorblock.objects;
|
||||
|
||||
import static app.revanced.integrations.utils.StringRef.sf;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.integrations.patches.VideoInformation;
|
||||
import app.revanced.integrations.utils.StringRef;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static app.revanced.integrations.utils.StringRef.sf;
|
||||
|
||||
public class SponsorSegment implements Comparable<SponsorSegment> {
|
||||
public enum SegmentVote {
|
||||
UPVOTE(sf("sb_vote_upvote"), 1,false),
|
||||
@@ -99,7 +100,7 @@ public class SponsorSegment implements Comparable<SponsorSegment> {
|
||||
*/
|
||||
@NonNull
|
||||
public String getSkipButtonText() {
|
||||
return category.getSkipButtonText(start, VideoInformation.getCurrentVideoLength()).toString();
|
||||
return category.getSkipButtonText(start, VideoInformation.getVideoLength()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,12 +108,30 @@ public class SponsorSegment implements Comparable<SponsorSegment> {
|
||||
*/
|
||||
@NonNull
|
||||
public String getSkippedToastText() {
|
||||
return category.getSkippedToastText(start, VideoInformation.getCurrentVideoLength()).toString();
|
||||
return category.getSkippedToastText(start, VideoInformation.getVideoLength()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(SponsorSegment o) {
|
||||
return (int) (this.start - o.start);
|
||||
// If both segments start at the same time, then sort with the longer segment first.
|
||||
// This keeps the seekbar drawing correct since it draws the segments using the sorted order.
|
||||
return start == o.start ? Long.compare(o.length(), length()) : Long.compare(start, o.start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SponsorSegment)) return false;
|
||||
SponsorSegment other = (SponsorSegment) o;
|
||||
return Objects.equals(UUID, other.UUID)
|
||||
&& category == other.category
|
||||
&& start == other.start
|
||||
&& end == other.end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(UUID);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user