You've already forked revanced-integrations
mirror of
https://github.com/revanced/revanced-integrations
synced 2025-11-21 18:35:37 +01:00
Compare commits
119 Commits
v0.94.0
...
v0.101.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8301fa07fd | ||
|
|
d16980ef2f | ||
|
|
83510e51b3 | ||
|
|
68d09305b9 | ||
|
|
dc5c1b45ba | ||
|
|
46e0272f9e | ||
|
|
69ccb5fc05 | ||
|
|
2dd14313a6 | ||
|
|
5e518855d1 | ||
|
|
52ac4acff3 | ||
|
|
a08bc53828 | ||
|
|
5d7dc94d8d | ||
|
|
1e1504d118 | ||
|
|
393d6e62f2 | ||
|
|
1361595076 | ||
|
|
2f5c839613 | ||
|
|
7e64e05709 | ||
|
|
d5919a8a2c | ||
|
|
844bc3b24f | ||
|
|
67fa87051f | ||
|
|
1f90f7b9cc | ||
|
|
0c725218fd | ||
|
|
416c695837 | ||
|
|
919f2855ed | ||
|
|
040ba24640 | ||
|
|
a1d4fabaaf | ||
|
|
66bcf12dc6 | ||
|
|
7dc6bb4428 | ||
|
|
24162934ba | ||
|
|
cb77e96da9 | ||
|
|
519c2bd511 | ||
|
|
8a8924ab09 | ||
|
|
0b3508bd8d | ||
|
|
db60d983e5 | ||
|
|
f31e3a02a0 | ||
|
|
f758b09676 | ||
|
|
3c00e58c13 | ||
|
|
0b83be989b | ||
|
|
db6ce55477 | ||
|
|
0b1b6b3682 | ||
|
|
b612cbf2c0 | ||
|
|
10fff6a0b8 | ||
|
|
e626bd08c1 | ||
|
|
476902e9ce | ||
|
|
05bfc68907 | ||
|
|
c3364226b8 | ||
|
|
0aef5e60e2 | ||
|
|
fb1a69a7ba | ||
|
|
cfc571c12c | ||
|
|
ae862cbac6 | ||
|
|
178b90b490 | ||
|
|
4b052b19a3 | ||
|
|
dce882b128 | ||
|
|
ccb5d81d46 | ||
|
|
5ed7170018 | ||
|
|
621ef63d86 | ||
|
|
37c0cc04c4 | ||
|
|
5749a1dd65 | ||
|
|
2d73b8b29b | ||
|
|
85cae1e5d6 | ||
|
|
b5a29fdce1 | ||
|
|
1809d1bbf9 | ||
|
|
96eea3d4fc | ||
|
|
665598836a | ||
|
|
f1e6cbcdf1 | ||
|
|
24d7e47844 | ||
|
|
f6573521ba | ||
|
|
c320384066 | ||
|
|
45c3f6e774 | ||
|
|
e040b7de2f | ||
|
|
96fcc0b1c7 | ||
|
|
35c4266e8b | ||
|
|
fd975ecd2a | ||
|
|
a857b9db6f | ||
|
|
39e3d046f3 | ||
|
|
da1572c28d | ||
|
|
3f5e27d6b1 | ||
|
|
3e113b6ab0 | ||
|
|
0904f3c78a | ||
|
|
9df1e460c5 | ||
|
|
cdf43efcf2 | ||
|
|
370f331330 | ||
|
|
622aa1dcaa | ||
|
|
5071082fde | ||
|
|
71b558ba6a | ||
|
|
9cea77ac59 | ||
|
|
b47b7cbc22 | ||
|
|
25d51179cc | ||
|
|
2e0758b3c8 | ||
|
|
85bf637078 | ||
|
|
cfb7aab779 | ||
|
|
0def31b2dd | ||
|
|
7225bc3c48 | ||
|
|
7d136e550c | ||
|
|
70170e24ce | ||
|
|
1864372298 | ||
|
|
1dd84a3785 | ||
|
|
512d747ec8 | ||
|
|
e16d3a7284 | ||
|
|
4469d1f3c4 | ||
|
|
43e419e6a6 | ||
|
|
f67216ad9d | ||
|
|
2e9d3fc63f | ||
|
|
d16153408c | ||
|
|
73d5400486 | ||
|
|
e698e8c524 | ||
|
|
d5bcef2cdb | ||
|
|
5ca042a602 | ||
|
|
319a234df6 | ||
|
|
293eae4a46 | ||
|
|
dc1faa94e0 | ||
|
|
2e6c73e4b5 | ||
|
|
f50346aff2 | ||
|
|
530260e248 | ||
|
|
db2e5eec71 | ||
|
|
27d1392a73 | ||
|
|
49aedae3fc | ||
|
|
84257a7348 | ||
|
|
6679e6ee45 |
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -3,7 +3,7 @@ name: Release
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- dev
|
- dev
|
||||||
pull_request:
|
pull_request:
|
||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Cancel previou runs
|
- name: Cancel previous runs
|
||||||
uses: styfle/cancel-workflow-action@0.11.0
|
uses: styfle/cancel-workflow-action@0.11.0
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -33,11 +33,11 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "latest"
|
node-version: "18"
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
- name: Setup semantic-release
|
- name: Setup semantic-release
|
||||||
run: npm install semantic-release@19.0.5 @saithodev/semantic-release-backmerge @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin@1.7.4 -D
|
run: npm install
|
||||||
- name: Release
|
- name: Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||||
run: npx semantic-release
|
run: npm exec semantic-release
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
[
|
[
|
||||||
"@saithodev/semantic-release-backmerge",
|
"@saithodev/semantic-release-backmerge",
|
||||||
{
|
{
|
||||||
branches: [{from: "main", to: "dev"}],
|
backmergeBranches: [{"from": "main", "to": "dev"}],
|
||||||
clearWorkspace: true
|
clearWorkspace: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
349
CHANGELOG.md
349
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,3 @@
|
|||||||
import java.io.FileInputStream
|
|
||||||
import java.util.Properties
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
@@ -47,7 +44,7 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(project(mapOf("path" to ":dummy")))
|
compileOnly(project(mapOf("path" to ":dummy")))
|
||||||
compileOnly("androidx.annotation:annotation:1.5.0")
|
compileOnly("androidx.annotation:annotation:1.5.0")
|
||||||
compileOnly("androidx.appcompat:appcompat:1.5.1")
|
compileOnly("androidx.appcompat:appcompat:1.6.1")
|
||||||
compileOnly("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
|
compileOnly("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
|
||||||
compileOnly("com.squareup.retrofit2:retrofit:2.9.0")
|
compileOnly("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ final class CommentsPatch extends Filter {
|
|||||||
var comments = new BlockRule(SettingsEnum.HIDE_COMMENTS_SECTION, "video_metadata_carousel", "_comments");
|
var comments = new BlockRule(SettingsEnum.HIDE_COMMENTS_SECTION, "video_metadata_carousel", "_comments");
|
||||||
var previewComment = new BlockRule(
|
var previewComment = new BlockRule(
|
||||||
SettingsEnum.HIDE_PREVIEW_COMMENT,
|
SettingsEnum.HIDE_PREVIEW_COMMENT,
|
||||||
"carousel_item",
|
"|carousel_item",
|
||||||
"comments_entry_point_teaser",
|
"comments_entry_point_teaser",
|
||||||
"comments_entry_point_simplebox"
|
"comments_entry_point_simplebox"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
package app.revanced.integrations.patches;
|
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
|
||||||
import app.revanced.integrations.utils.LogHelper;
|
|
||||||
|
|
||||||
public final class FixPlaybackPatch {
|
|
||||||
private static Thread currentThread = null;
|
|
||||||
private static String videoId;
|
|
||||||
|
|
||||||
public static void newVideoLoaded(final String videoId) {
|
|
||||||
if (!SettingsEnum.FIX_PLAYBACK.getBoolean()) return;
|
|
||||||
|
|
||||||
if (videoId.equals(FixPlaybackPatch.videoId)) return;
|
|
||||||
else FixPlaybackPatch.videoId = videoId;
|
|
||||||
|
|
||||||
if (currentThread != null) {
|
|
||||||
currentThread.interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentThread = new Thread(() -> {
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
var currentVideoTime = VideoInformation.getVideoTime();
|
|
||||||
|
|
||||||
if (currentVideoTime > -1) {
|
|
||||||
VideoInformation.seekTo(Integer.MAX_VALUE);
|
|
||||||
VideoInformation.seekTo(currentVideoTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.sleep(10);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LogHelper.printDebug(() -> "Thread was interrupted");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
currentThread.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
package app.revanced.integrations.patches;
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
public class FullscreenPanelsRemoverPatch {
|
public class FullscreenPanelsRemoverPatch {
|
||||||
|
|
||||||
public static int getFullscreenPanelsVisibility() {
|
public static int getFullscreenPanelsVisibility() {
|
||||||
return SettingsEnum.HIDE_FULLSCREEN_PANELS.getBoolean() ? View.GONE : View.VISIBLE;
|
return SettingsEnum.HIDE_FULLSCREEN_PANELS.getBoolean() ? View.GONE : View.VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,21 +26,27 @@ public final class GeneralAdsPatch extends Filter {
|
|||||||
var subscribersCommunityGuidelines = new BlockRule(SettingsEnum.ADREMOVER_SUBSCRIBERS_COMMUNITY_GUIDELINES_REMOVAL, "sponsorships_comments_upsell");
|
var subscribersCommunityGuidelines = new BlockRule(SettingsEnum.ADREMOVER_SUBSCRIBERS_COMMUNITY_GUIDELINES_REMOVAL, "sponsorships_comments_upsell");
|
||||||
var channelMemberShelf = new BlockRule(SettingsEnum.ADREMOVER_CHANNEL_MEMBER_SHELF_REMOVAL, "member_recognition_shelf");
|
var channelMemberShelf = new BlockRule(SettingsEnum.ADREMOVER_CHANNEL_MEMBER_SHELF_REMOVAL, "member_recognition_shelf");
|
||||||
var compactBanner = new BlockRule(SettingsEnum.ADREMOVER_COMPACT_BANNER_REMOVAL, "compact_banner");
|
var compactBanner = new BlockRule(SettingsEnum.ADREMOVER_COMPACT_BANNER_REMOVAL, "compact_banner");
|
||||||
var inFeedSurvey = new BlockRule(SettingsEnum.ADREMOVER_FEED_SURVEY_REMOVAL, "in_feed_survey");
|
var inFeedSurvey = new BlockRule(SettingsEnum.ADREMOVER_FEED_SURVEY_REMOVAL, "in_feed_survey", "slimline_survey");
|
||||||
var medicalPanel = new BlockRule(SettingsEnum.ADREMOVER_MEDICAL_PANEL_REMOVAL, "medical_panel");
|
var medicalPanel = new BlockRule(SettingsEnum.ADREMOVER_MEDICAL_PANEL_REMOVAL, "medical_panel");
|
||||||
var paidContent = new BlockRule(SettingsEnum.ADREMOVER_PAID_CONTENT_REMOVAL, "paid_content_overlay");
|
var paidContent = new BlockRule(SettingsEnum.ADREMOVER_PAID_CONTENT_REMOVAL, "paid_content_overlay");
|
||||||
var merchandise = new BlockRule(SettingsEnum.ADREMOVER_MERCHANDISE_REMOVAL, "product_carousel");
|
var merchandise = new BlockRule(SettingsEnum.ADREMOVER_MERCHANDISE_REMOVAL, "product_carousel");
|
||||||
var infoPanel = new BlockRule(SettingsEnum.ADREMOVER_INFO_PANEL_REMOVAL, "publisher_transparency_panel", "single_item_information_panel");
|
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 latestPosts = new BlockRule(SettingsEnum.ADREMOVER_HIDE_LATEST_POSTS, "post_shelf");
|
||||||
var channelGuidelines = new BlockRule(SettingsEnum.ADREMOVER_HIDE_CHANNEL_GUIDELINES, "channel_guidelines_entry_banner");
|
var channelGuidelines = new BlockRule(SettingsEnum.ADREMOVER_HIDE_CHANNEL_GUIDELINES, "channel_guidelines_entry_banner");
|
||||||
var artistCard = new BlockRule(SettingsEnum.HIDE_ARTIST_CARD, "official_card");
|
var artistCard = new BlockRule(SettingsEnum.HIDE_ARTIST_CARDS, "official_card");
|
||||||
var selfSponsor = new BlockRule(SettingsEnum.ADREMOVER_SELF_SPONSOR_REMOVAL, "cta_shelf_card");
|
var selfSponsor = new BlockRule(SettingsEnum.ADREMOVER_SELF_SPONSOR_REMOVAL, "cta_shelf_card");
|
||||||
var chapterTeaser = new BlockRule(SettingsEnum.ADREMOVER_CHAPTER_TEASER_REMOVAL, "expandable_metadata");
|
var chapterTeaser = new BlockRule(SettingsEnum.ADREMOVER_CHAPTER_TEASER_REMOVAL, "expandable_metadata", "macro_markers_carousel");
|
||||||
|
var viewProducts = new BlockRule(SettingsEnum.ADREMOVER_VIEW_PRODUCTS, "product_item", "products_in_video");
|
||||||
|
var webLinkPanel = new BlockRule(SettingsEnum.ADREMOVER_WEB_SEARCH_RESULTS, "web_link_panel");
|
||||||
|
var channelBar = new BlockRule(SettingsEnum.ADREMOVER_CHANNEL_BAR, "channel_bar");
|
||||||
|
var relatedVideos = new BlockRule(SettingsEnum.ADREMOVER_RELATED_VIDEOS, "fullscreen_related_videos");
|
||||||
|
var quickActions = new BlockRule(SettingsEnum.ADREMOVER_QUICK_ACTIONS, "quick_actions");
|
||||||
|
var imageShelf = new BlockRule(SettingsEnum.ADREMOVER_IMAGE_SHELF, "image_shelf");
|
||||||
var graySeparator = new BlockRule(SettingsEnum.ADREMOVER_GRAY_SEPARATOR,
|
var graySeparator = new BlockRule(SettingsEnum.ADREMOVER_GRAY_SEPARATOR,
|
||||||
"cell_divider" // layout residue (gray line above the buttoned ad),
|
"cell_divider" // layout residue (gray line above the buttoned ad),
|
||||||
);
|
);
|
||||||
var buttonedAd = new BlockRule(SettingsEnum.ADREMOVER_BUTTONED_REMOVAL,
|
var buttonedAd = new BlockRule(SettingsEnum.ADREMOVER_BUTTONED_REMOVAL,
|
||||||
"video_display_full_buttoned_layout",
|
"_buttoned_layout",
|
||||||
"full_width_square_image_layout",
|
"full_width_square_image_layout",
|
||||||
"_ad_with",
|
"_ad_with",
|
||||||
"landscape_image_wide_button_layout"
|
"landscape_image_wide_button_layout"
|
||||||
@@ -51,7 +57,11 @@ public final class GeneralAdsPatch extends Filter {
|
|||||||
"banner_text_icon",
|
"banner_text_icon",
|
||||||
"square_image_layout",
|
"square_image_layout",
|
||||||
"watch_metadata_app_promo",
|
"watch_metadata_app_promo",
|
||||||
"video_display_full_layout"
|
"video_display_full_layout",
|
||||||
|
"hero_promo_image",
|
||||||
|
"statement_banner",
|
||||||
|
"carousel_footered_layout",
|
||||||
|
"text_image_button_layout"
|
||||||
);
|
);
|
||||||
var movieAds = new BlockRule(
|
var movieAds = new BlockRule(
|
||||||
SettingsEnum.ADREMOVER_MOVIE_REMOVAL,
|
SettingsEnum.ADREMOVER_MOVIE_REMOVAL,
|
||||||
@@ -65,20 +75,26 @@ public final class GeneralAdsPatch extends Filter {
|
|||||||
this.pathRegister.registerAll(
|
this.pathRegister.registerAll(
|
||||||
generalAds,
|
generalAds,
|
||||||
buttonedAd,
|
buttonedAd,
|
||||||
|
channelBar,
|
||||||
communityPosts,
|
communityPosts,
|
||||||
paidContent,
|
paidContent,
|
||||||
latestPosts,
|
latestPosts,
|
||||||
movieAds,
|
movieAds,
|
||||||
chapterTeaser,
|
chapterTeaser,
|
||||||
communityGuidelines,
|
communityGuidelines,
|
||||||
|
quickActions,
|
||||||
|
relatedVideos,
|
||||||
compactBanner,
|
compactBanner,
|
||||||
inFeedSurvey,
|
inFeedSurvey,
|
||||||
|
viewProducts,
|
||||||
medicalPanel,
|
medicalPanel,
|
||||||
merchandise,
|
merchandise,
|
||||||
infoPanel,
|
infoPanel,
|
||||||
channelGuidelines,
|
channelGuidelines,
|
||||||
artistCard,
|
artistCard,
|
||||||
selfSponsor,
|
selfSponsor,
|
||||||
|
webLinkPanel,
|
||||||
|
imageShelf,
|
||||||
subscribersCommunityGuidelines,
|
subscribersCommunityGuidelines,
|
||||||
channelMemberShelf
|
channelMemberShelf
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ package app.revanced.integrations.patches;
|
|||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
public class HideAutoplayButtonPatch {
|
public class HideAutoplayButtonPatch {
|
||||||
|
|
||||||
public static boolean isButtonShown() {
|
public static boolean isButtonShown() {
|
||||||
return SettingsEnum.HIDE_AUTOPLAY_BUTTON.getBoolean() == false;
|
return !SettingsEnum.HIDE_AUTOPLAY_BUTTON.getBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
|
public final class HideFloatingMicrophoneButtonPatch {
|
||||||
|
public static boolean hideFloatingMicrophoneButton(final boolean original) {
|
||||||
|
return SettingsEnum.HIDE_FLOATING_MICROPHONE_BUTTON.getBoolean() || original;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
package app.revanced.integrations.patches;
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
public class HideInfocardsPatch {
|
public class HideInfoCardsPatch {
|
||||||
public static void hideInfocardsIncognito(View view) {
|
public static void hideInfoCardsIncognito(View view) {
|
||||||
if (!SettingsEnum.HIDE_INFO_CARDS.getBoolean()) return;
|
if (!SettingsEnum.HIDE_INFO_CARDS.getBoolean()) return;
|
||||||
view.setVisibility(View.GONE);
|
view.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hideInfocardsMethodCall() {
|
public static boolean hideInfoCardsMethodCall() {
|
||||||
return SettingsEnum.HIDE_INFO_CARDS.getBoolean();
|
return SettingsEnum.HIDE_INFO_CARDS.getBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
|
|
||||||
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
|
public final class HidePlayerButtonsPatch {
|
||||||
|
|
||||||
|
public static boolean hideButtons() {
|
||||||
|
return SettingsEnum.HIDE_PLAYER_BUTTONS.getBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
|
public class HideSeekbarPatch {
|
||||||
|
public static boolean hideSeekbar() {
|
||||||
|
return SettingsEnum.HIDE_SEEKBAR.getBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package app.revanced.integrations.patches;
|
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
|
||||||
|
|
||||||
public class HideTimeAndSeekbarPatch {
|
|
||||||
//Used by app.revanced.patches.youtube.layout.hidetimeandseekbar.patch.HideTimeAndSeekbarPatch
|
|
||||||
public static boolean hideTimeAndSeekbar() {
|
|
||||||
return SettingsEnum.HIDE_TIME_AND_SEEKBAR.getBoolean();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
|
public class HideTimestampPatch {
|
||||||
|
public static boolean hideTimestamp() {
|
||||||
|
return SettingsEnum.HIDE_TIMESTAMP.getBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,8 @@ package app.revanced.integrations.patches;
|
|||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
public class HideWatchinVRPatch {
|
public class HideWatchInVRPatch {
|
||||||
//Used by app.revanced.patches.youtube.layout.watchinvr.patch.HideWatchinVRPatch
|
public static boolean hideWatchInVR() {
|
||||||
public static boolean hideWatchinVR() {
|
|
||||||
return SettingsEnum.HIDE_WATCH_IN_VR.getBoolean();
|
return SettingsEnum.HIDE_WATCH_IN_VR.getBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,23 @@
|
|||||||
package app.revanced.integrations.patches;
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
import static app.revanced.integrations.sponsorblock.StringRef.str;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import app.revanced.integrations.utils.LogHelper;
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
import app.revanced.integrations.utils.ReVancedUtils;
|
import app.revanced.integrations.utils.ReVancedUtils;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static app.revanced.integrations.sponsorblock.StringRef.str;
|
||||||
|
|
||||||
public class MicroGSupport {
|
public class MicroGSupport {
|
||||||
private static final String MICROG_VENDOR = "com.mgoogle";
|
private static final String MICROG_VENDOR = "com.mgoogle";
|
||||||
private static final String MICROG_PACKAGE_NAME = "com.mgoogle.android.gms";
|
private static final String MICROG_PACKAGE_NAME = MICROG_VENDOR + ".android.gms";
|
||||||
private static final String VANCED_MICROG_DOWNLOAD_LINK = "https://github.com/TeamVanced/VancedMicroG/releases/latest";
|
private static final String VANCED_MICROG_DOWNLOAD_LINK = "https://github.com/TeamVanced/VancedMicroG/releases/latest";
|
||||||
private static final String DONT_KILL_MY_APP_LINK = "https://dontkillmyapp.com";
|
private static final String DONT_KILL_MY_APP_LINK = "https://dontkillmyapp.com";
|
||||||
private static final Uri VANCED_MICROG_PROVIDER = Uri.parse("content://com.mgoogle.android.gsf.gservices/prefix");
|
private static final Uri VANCED_MICROG_PROVIDER = Uri.parse("content://" + MICROG_VENDOR + ".android.gsf.gservices/prefix");
|
||||||
|
|
||||||
private static void startIntent(Context context, String uriString, String message) {
|
private static void startIntent(Context context, String uriString, String message) {
|
||||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package app.revanced.integrations.patches;
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
import app.revanced.integrations.shared.PlayerType;
|
||||||
|
|
||||||
public class MinimizedPlaybackPatch {
|
public class MinimizedPlaybackPatch {
|
||||||
|
|
||||||
|
public static boolean isNotPlayingShorts(boolean isPipEnabled) {
|
||||||
|
return !PlayerType.getCurrent().isNoneOrHidden() && isPipEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isMinimizedPlaybackEnabled() {
|
public static boolean isMinimizedPlaybackEnabled() {
|
||||||
return SettingsEnum.ENABLE_MINIMIZED_PLAYBACK.getBoolean();
|
return SettingsEnum.ENABLE_MINIMIZED_PLAYBACK.getBoolean();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package app.revanced.integrations.patches;
|
|
||||||
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
|
||||||
|
|
||||||
public class OpenLinksDirectlyPatch {
|
|
||||||
|
|
||||||
public static String parseRedirectUri(String uri) {
|
|
||||||
if (SettingsEnum.OPEN_LINKS_DIRECTLY.getBoolean()) {
|
|
||||||
Matcher matcher = Pattern.compile("&q=(http.+?)&v=").matcher(uri);
|
|
||||||
return matcher.find() ? URLDecoder.decode(matcher.group(1)) : uri;
|
|
||||||
}
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,25 @@
|
|||||||
package app.revanced.integrations.patches;
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import android.text.Spanned;
|
||||||
|
|
||||||
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by app.revanced.patches.youtube.layout.returnyoutubedislike.patch.ReturnYouTubeDislikePatch
|
* Used by app.revanced.patches.youtube.layout.returnyoutubedislike.patch.ReturnYouTubeDislikePatch
|
||||||
*/
|
*/
|
||||||
public class ReturnYouTubeDislikePatch {
|
public class ReturnYouTubeDislikePatch {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the video id changes
|
* Injection point
|
||||||
*/
|
*/
|
||||||
public static void newVideoLoaded(String videoId) {
|
public static void newVideoLoaded(String videoId) {
|
||||||
ReturnYouTubeDislike.newVideoLoaded(videoId);
|
ReturnYouTubeDislike.newVideoLoaded(videoId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Injection point
|
||||||
|
*
|
||||||
* Called when a litho text component is created
|
* Called when a litho text component is created
|
||||||
*/
|
*/
|
||||||
public static void onComponentCreated(Object conversionContext, AtomicReference<Object> textRef) {
|
public static void onComponentCreated(Object conversionContext, AtomicReference<Object> textRef) {
|
||||||
@@ -24,16 +27,22 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Injection point
|
||||||
|
*
|
||||||
|
* Called when a Shorts dislike Spannable is created
|
||||||
|
*/
|
||||||
|
public static Spanned onShortsComponentCreated(Spanned dislike) {
|
||||||
|
return ReturnYouTubeDislike.onShortsComponentCreated(dislike);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point
|
||||||
|
*
|
||||||
* Called when the like/dislike button is clicked
|
* Called when the like/dislike button is clicked
|
||||||
*
|
*
|
||||||
* @param vote -1 (dislike), 0 (none) or 1 (like)
|
* @param vote -1 (dislike), 0 (none) or 1 (like)
|
||||||
*/
|
*/
|
||||||
public static void sendVote(int vote) {
|
public static void sendVote(int vote) {
|
||||||
for (ReturnYouTubeDislike.Vote v : ReturnYouTubeDislike.Vote.values()) {
|
ReturnYouTubeDislike.sendVote(vote);
|
||||||
if (v.value == vote) {
|
|
||||||
ReturnYouTubeDislike.sendVote(v);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package app.revanced.integrations.patches;
|
||||||
|
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
import app.revanced.integrations.utils.ReVancedUtils;
|
||||||
|
|
||||||
|
public class SpoofSignatureVerificationPatch {
|
||||||
|
/**
|
||||||
|
* Protobuf parameters used by the player.
|
||||||
|
* Known issue: video preview not showing when using the seekbar.
|
||||||
|
*/
|
||||||
|
private static final String PROTOBUF_PARAMETER_GENERAL = "CgIQBg";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protobuf parameter of shorts and YouTube stories.
|
||||||
|
* Known issue: captions are positioned on upper area in the player.
|
||||||
|
*/
|
||||||
|
private static final String PROTOBUF_PARAMETER_SHORTS = "8AEB"; // "8AEByAMTuAQP"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Target Protobuf parameters.
|
||||||
|
* Used by the generic player.
|
||||||
|
*/
|
||||||
|
private static final String PROTOBUF_PARAMETER_TARGET = "YADI";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*
|
||||||
|
* @param originalValue originalValue protobuf parameter
|
||||||
|
*/
|
||||||
|
public static String overrideProtobufParameter(String originalValue) {
|
||||||
|
try {
|
||||||
|
if (!SettingsEnum.SIGNATURE_SPOOFING.getBoolean()) {
|
||||||
|
return originalValue;
|
||||||
|
}
|
||||||
|
LogHelper.printDebug(() -> "Original protobuf parameter value: " + originalValue);
|
||||||
|
if (originalValue.startsWith(PROTOBUF_PARAMETER_TARGET) || originalValue.isEmpty()) {
|
||||||
|
return PROTOBUF_PARAMETER_SHORTS;
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.printException(() -> "overrideProtobufParameter failure", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point. Runs off the main thread.
|
||||||
|
* <p>
|
||||||
|
* Used to check the response code of video playback requests made by YouTube.
|
||||||
|
* Response code of interest is 403 that indicate a signature verification failure for the current request
|
||||||
|
*
|
||||||
|
* @param responseCode HTTP status code of the completed YouTube connection
|
||||||
|
*/
|
||||||
|
public static void onResponse(int responseCode) {
|
||||||
|
try {
|
||||||
|
if (responseCode < 400 || responseCode >= 500) {
|
||||||
|
return; // everything normal
|
||||||
|
}
|
||||||
|
LogHelper.printDebug(() -> "YouTube HTTP status code: " + responseCode);
|
||||||
|
|
||||||
|
if (SettingsEnum.SIGNATURE_SPOOFING.getBoolean()) {
|
||||||
|
return; // already enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsEnum.SIGNATURE_SPOOFING.saveValue(true);
|
||||||
|
ReVancedUtils.runOnMainThread(() -> {
|
||||||
|
Toast.makeText(
|
||||||
|
ReVancedUtils.getContext(),
|
||||||
|
"Spoofing app signature to prevent playback issues", Toast.LENGTH_LONG
|
||||||
|
).show();
|
||||||
|
// it would be great if the video could be forcefully reloaded, but currently there is no code to do this
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.printException(() -> "onResponse failure", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package app.revanced.integrations.patches;
|
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
|
||||||
|
|
||||||
public class VideoBufferPatch {
|
|
||||||
|
|
||||||
public static int getMaxBuffer() {
|
|
||||||
int confVal = SettingsEnum.MAX_BUFFER.getInt();
|
|
||||||
if (confVal < 1) confVal = 1;
|
|
||||||
return confVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getPlaybackBuffer() {
|
|
||||||
int confVal = SettingsEnum.PLAYBACK_MAX_BUFFER.getInt();
|
|
||||||
if (confVal < 1) confVal = 1;
|
|
||||||
return confVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getReBuffer() {
|
|
||||||
int confVal = SettingsEnum.MAX_PLAYBACK_BUFFER_AFTER_REBUFFER.getInt();
|
|
||||||
if (confVal < 1) confVal = 1;
|
|
||||||
return confVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,18 @@
|
|||||||
package app.revanced.integrations.patches.playback.quality;
|
package app.revanced.integrations.patches.playback.quality;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
import app.revanced.integrations.utils.ReVancedUtils;
|
||||||
|
import app.revanced.integrations.utils.SharedPrefHelper;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
|
||||||
import app.revanced.integrations.utils.LogHelper;
|
|
||||||
import app.revanced.integrations.utils.ReVancedUtils;
|
|
||||||
import app.revanced.integrations.utils.SharedPrefHelper;
|
|
||||||
|
|
||||||
public class RememberVideoQualityPatch {
|
public class RememberVideoQualityPatch {
|
||||||
|
|
||||||
public static int selectedQuality1 = -2;
|
public static int selectedQuality1 = -2;
|
||||||
@@ -24,38 +21,37 @@ public class RememberVideoQualityPatch {
|
|||||||
|
|
||||||
public static void changeDefaultQuality(int defaultQuality) {
|
public static void changeDefaultQuality(int defaultQuality) {
|
||||||
Context context = ReVancedUtils.getContext();
|
Context context = ReVancedUtils.getContext();
|
||||||
if (isConnectedWifi(context)) {
|
|
||||||
try {
|
var networkType = getNetworType(context);
|
||||||
SharedPrefHelper.saveString(SharedPrefHelper.SharedPrefNames.REVANCED_PREFS, "wifi_quality", defaultQuality + "");
|
|
||||||
String message = "Changing default Wi-Fi quality to: " + defaultQuality;
|
if (networkType == NetworkType.NONE) {
|
||||||
LogHelper.printDebug(() -> message);
|
|
||||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
LogHelper.printException(() -> "Failed to change default WI-FI quality", ex);
|
|
||||||
}
|
|
||||||
} else if (isConnectedMobile(context)) {
|
|
||||||
try {
|
|
||||||
SharedPrefHelper.saveString(SharedPrefHelper.SharedPrefNames.REVANCED_PREFS, "mobile_quality", defaultQuality + "");
|
|
||||||
String message = "Changing default mobile data quality to:" + defaultQuality;
|
|
||||||
LogHelper.printDebug(() -> message);
|
|
||||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
LogHelper.printException(() -> "Failed to change default mobile data quality", ex);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String message = "No internet connection.";
|
String message = "No internet connection.";
|
||||||
LogHelper.printDebug(() -> message);
|
LogHelper.printDebug(() -> message);
|
||||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
var preferenceKey = "wifi_quality";
|
||||||
|
var networkTypeMessage = "WIFI";
|
||||||
|
|
||||||
|
if (networkType == NetworkType.MOBILE) {
|
||||||
|
networkTypeMessage = "mobile";
|
||||||
|
preferenceKey = "mobile_quality";
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPrefHelper.saveString(SharedPrefHelper.SharedPrefNames.REVANCED_PREFS, preferenceKey, defaultQuality + "");
|
||||||
|
String message = "Changing default " + networkTypeMessage + " quality to: " + defaultQuality;
|
||||||
|
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
userChangedQuality = false;
|
userChangedQuality = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int setVideoQuality(Object[] qualities, int quality, Object qInterface, String qIndexMethod) {
|
public static int setVideoQuality(Object[] qualities, int quality, Object qInterface, String qIndexMethod) {
|
||||||
int preferredQuality;
|
|
||||||
Field[] fields;
|
Field[] fields;
|
||||||
|
|
||||||
if (!(newVideo || userChangedQuality) || qInterface == null) {
|
if (!(newVideo || userChangedQuality) || qInterface == null) {
|
||||||
return quality;
|
return quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> intType = Integer.TYPE;
|
Class<?> intType = Integer.TYPE;
|
||||||
ArrayList<Integer> iStreamQualities = new ArrayList<>();
|
ArrayList<Integer> iStreamQualities = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
@@ -93,51 +89,48 @@ public class RememberVideoQualityPatch {
|
|||||||
LogHelper.printException(() -> "Context is null or settings not initialized, returning quality: " + qualityToLog);
|
LogHelper.printException(() -> "Context is null or settings not initialized, returning quality: " + qualityToLog);
|
||||||
return quality;
|
return quality;
|
||||||
}
|
}
|
||||||
if (isConnectedWifi(context)) {
|
var networkType = getNetworType(context);
|
||||||
preferredQuality = SharedPrefHelper.getInt(SharedPrefHelper.SharedPrefNames.REVANCED_PREFS, "wifi_quality", -2);
|
if (networkType == NetworkType.NONE) {
|
||||||
LogHelper.printDebug(() -> "Wi-Fi connection detected, preferred quality: " + preferredQuality);
|
|
||||||
} else if (isConnectedMobile(context)) {
|
|
||||||
preferredQuality = SharedPrefHelper.getInt(SharedPrefHelper.SharedPrefNames.REVANCED_PREFS, "mobile_quality", -2);
|
|
||||||
LogHelper.printDebug(() -> "Mobile data connection detected, preferred quality: " + preferredQuality);
|
|
||||||
} else {
|
|
||||||
LogHelper.printDebug(() -> "No Internet connection!");
|
LogHelper.printDebug(() -> "No Internet connection!");
|
||||||
return quality;
|
return quality;
|
||||||
}
|
} else {
|
||||||
if (preferredQuality == -2) {
|
var preferenceKey = "wifi_quality";
|
||||||
return quality;
|
if (networkType == NetworkType.MOBILE) preferenceKey = "mobile_quality";
|
||||||
}
|
|
||||||
for (int streamQuality2 : iStreamQualities) {
|
int preferredQuality = SharedPrefHelper.getInt(SharedPrefHelper.SharedPrefNames.REVANCED_PREFS, preferenceKey, -2);
|
||||||
final int indexToLog = index;
|
if (preferredQuality == -2) return quality;
|
||||||
LogHelper.printDebug(() -> "Quality at index " + indexToLog + ": " + streamQuality2);
|
|
||||||
index++;
|
for (int streamQuality2 : iStreamQualities) {
|
||||||
}
|
final int indexToLog = index;
|
||||||
for (Integer iStreamQuality : iStreamQualities) {
|
LogHelper.printDebug(() -> "Quality at index " + indexToLog + ": " + streamQuality2);
|
||||||
int streamQuality3 = iStreamQuality;
|
index++;
|
||||||
if (streamQuality3 <= preferredQuality) {
|
}
|
||||||
quality = streamQuality3;
|
for (Integer iStreamQuality : iStreamQualities) {
|
||||||
|
int streamQuality3 = iStreamQuality;
|
||||||
|
if (streamQuality3 <= preferredQuality) {
|
||||||
|
quality = streamQuality3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (quality == -2) return quality;
|
||||||
|
|
||||||
|
int qualityIndex = iStreamQualities.indexOf(quality);
|
||||||
|
final int qualityToLog2 = quality;
|
||||||
|
LogHelper.printDebug(() -> "Index of quality " + qualityToLog2 + " is " + qualityIndex);
|
||||||
|
try {
|
||||||
|
Class<?> cl = qInterface.getClass();
|
||||||
|
Method m = cl.getMethod(qIndexMethod, Integer.TYPE);
|
||||||
|
LogHelper.printDebug(() -> "Method is: " + qIndexMethod);
|
||||||
|
m.invoke(qInterface, iStreamQualities.get(qualityIndex));
|
||||||
|
LogHelper.printDebug(() -> "Quality changed to: " + qualityIndex);
|
||||||
|
return qualityIndex;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.printException(() -> "Failed to set quality", ex);
|
||||||
|
return qualityIndex;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (quality == -2) {
|
|
||||||
return quality;
|
|
||||||
}
|
|
||||||
int qualityIndex = iStreamQualities.indexOf(quality);
|
|
||||||
final int qualityToLog2 = quality;
|
|
||||||
LogHelper.printDebug(() -> "Index of quality " + qualityToLog2 + " is " + qualityIndex);
|
|
||||||
try {
|
|
||||||
Class<?> cl = qInterface.getClass();
|
|
||||||
Method m = cl.getMethod(qIndexMethod, Integer.TYPE);
|
|
||||||
LogHelper.printDebug(() -> "Method is: " + qIndexMethod);
|
|
||||||
m.invoke(qInterface, iStreamQualities.get(qualityIndex));
|
|
||||||
LogHelper.printDebug(() -> "Quality changed to: " + qualityIndex);
|
|
||||||
return qualityIndex;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
LogHelper.printException(() -> "Failed to set quality", ex);
|
|
||||||
return qualityIndex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void userChangedQuality(int selectedQuality) {
|
public static void userChangedQuality(int selectedQuality) {
|
||||||
// Do not remember a **new** quality if REMEMBER_VIDEO_QUALITY is false
|
|
||||||
if (!SettingsEnum.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.getBoolean()) return;
|
if (!SettingsEnum.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.getBoolean()) return;
|
||||||
|
|
||||||
selectedQuality1 = selectedQuality;
|
selectedQuality1 = selectedQuality;
|
||||||
@@ -148,20 +141,23 @@ public class RememberVideoQualityPatch {
|
|||||||
newVideo = true;
|
newVideo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
private static NetworkType getNetworType(Context context) {
|
||||||
private static NetworkInfo getNetworkInfo(Context context) {
|
|
||||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
return cm.getActiveNetworkInfo();
|
var networkInfo = cm.getActiveNetworkInfo();
|
||||||
|
|
||||||
|
if (networkInfo == null || !networkInfo.isConnected()) {
|
||||||
|
return NetworkType.NONE;
|
||||||
|
} else {
|
||||||
|
var type = networkInfo.getType();
|
||||||
|
|
||||||
|
return type == ConnectivityManager.TYPE_MOBILE || type == ConnectivityManager.TYPE_BLUETOOTH ? NetworkType.MOBILE : NetworkType.OTHER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isConnectedWifi(Context context) {
|
enum NetworkType {
|
||||||
NetworkInfo info = getNetworkInfo(context);
|
MOBILE,
|
||||||
return info != null && info.isConnected() && info.getType() == 1;
|
OTHER,
|
||||||
}
|
NONE
|
||||||
|
|
||||||
private static boolean isConnectedMobile(Context context) {
|
|
||||||
NetworkInfo info = getNetworkInfo(context);
|
|
||||||
return info != null && info.isConnected() && info.getType() == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,13 @@
|
|||||||
package app.revanced.integrations.returnyoutubedislike.requests;
|
package app.revanced.integrations.returnyoutubedislike.requests;
|
||||||
|
|
||||||
|
import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.Objects;
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ReturnYouTubeDislike API estimated like/dislike/view counts.
|
* ReturnYouTubeDislike API estimated like/dislike/view counts.
|
||||||
@@ -12,7 +16,7 @@ import java.util.Objects;
|
|||||||
* So these values may lag behind what YouTube shows.
|
* So these values may lag behind what YouTube shows.
|
||||||
*/
|
*/
|
||||||
public final class RYDVoteData {
|
public final class RYDVoteData {
|
||||||
|
@NonNull
|
||||||
public final String videoId;
|
public final String videoId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,46 +24,87 @@ public final class RYDVoteData {
|
|||||||
*/
|
*/
|
||||||
public final long viewCount;
|
public final long viewCount;
|
||||||
|
|
||||||
|
private final long fetchedLikeCount;
|
||||||
|
private volatile long likeCount; // read/write from different threads
|
||||||
|
private volatile float likePercentage;
|
||||||
|
|
||||||
|
private final long fetchedDislikeCount;
|
||||||
|
private volatile long dislikeCount; // read/write from different threads
|
||||||
|
private volatile float dislikePercentage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws JSONException if JSON parse error occurs, or if the values make no sense (ie: negative values)
|
||||||
|
*/
|
||||||
|
public RYDVoteData(@NonNull JSONObject json) throws JSONException {
|
||||||
|
videoId = json.getString("id");
|
||||||
|
viewCount = json.getLong("viewCount");
|
||||||
|
fetchedLikeCount = json.getLong("likes");
|
||||||
|
fetchedDislikeCount = json.getLong("dislikes");
|
||||||
|
if (viewCount < 0 || fetchedLikeCount < 0 || fetchedDislikeCount < 0) {
|
||||||
|
throw new JSONException("Unexpected JSON values: " + json);
|
||||||
|
}
|
||||||
|
likeCount = fetchedLikeCount;
|
||||||
|
dislikeCount = fetchedDislikeCount;
|
||||||
|
updatePercentages();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimated like count
|
* Estimated like count
|
||||||
*/
|
*/
|
||||||
public final long likeCount;
|
public long getLikeCount() {
|
||||||
|
return likeCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimated dislike count
|
* Estimated dislike count
|
||||||
*/
|
*/
|
||||||
public final long dislikeCount;
|
public long getDislikeCount() {
|
||||||
|
return dislikeCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimated percentage of likes for all votes. Value has range of [0, 1]
|
* Estimated percentage of likes for all votes. Value has range of [0, 1]
|
||||||
*
|
*
|
||||||
* A video with 400 positive votes, and 100 negative votes, has a likePercentage of 0.8
|
* A video with 400 positive votes, and 100 negative votes, has a likePercentage of 0.8
|
||||||
*/
|
*/
|
||||||
public final float likePercentage;
|
public float getLikePercentage() {
|
||||||
|
return likePercentage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimated percentage of dislikes for all votes. Value has range of [0, 1]
|
* Estimated percentage of dislikes for all votes. Value has range of [0, 1]
|
||||||
*
|
*
|
||||||
* A video with 400 positive votes, and 100 negative votes, has a dislikePercentage of 0.2
|
* A video with 400 positive votes, and 100 negative votes, has a dislikePercentage of 0.2
|
||||||
*/
|
*/
|
||||||
public final float dislikePercentage;
|
public float getDislikePercentage() {
|
||||||
|
return dislikePercentage;
|
||||||
/**
|
|
||||||
* @throws JSONException if JSON parse error occurs, or if the values make no sense (ie: negative values)
|
|
||||||
*/
|
|
||||||
public RYDVoteData(JSONObject json) throws JSONException {
|
|
||||||
Objects.requireNonNull(json);
|
|
||||||
videoId = json.getString("id");
|
|
||||||
viewCount = json.getLong("viewCount");
|
|
||||||
likeCount = json.getLong("likes");
|
|
||||||
dislikeCount = json.getLong("dislikes");
|
|
||||||
if (likeCount < 0 || dislikeCount < 0 || viewCount < 0) {
|
|
||||||
throw new JSONException("Unexpected JSON values: " + json);
|
|
||||||
}
|
|
||||||
likePercentage = (likeCount == 0 ? 0 : (float)likeCount / (likeCount + dislikeCount));
|
|
||||||
dislikePercentage = (dislikeCount == 0 ? 0 : (float)dislikeCount / (likeCount + dislikeCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateUsingVote(Vote vote) {
|
||||||
|
if (vote == Vote.LIKE) {
|
||||||
|
LogHelper.printDebug(() -> "Increasing like count");
|
||||||
|
likeCount = fetchedLikeCount + 1;
|
||||||
|
dislikeCount = fetchedDislikeCount;
|
||||||
|
} else if (vote == Vote.DISLIKE) {
|
||||||
|
LogHelper.printDebug(() -> "Increasing dislike count");
|
||||||
|
likeCount = fetchedLikeCount;
|
||||||
|
dislikeCount = fetchedDislikeCount + 1;
|
||||||
|
} else if (vote == Vote.LIKE_REMOVE) {
|
||||||
|
LogHelper.printDebug(() -> "Resetting like/dislike to fetched values");
|
||||||
|
likeCount = fetchedLikeCount;
|
||||||
|
dislikeCount = fetchedDislikeCount;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
updatePercentages();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePercentages() {
|
||||||
|
likePercentage = (likeCount == 0 ? 0 : (float) likeCount / (likeCount + dislikeCount));
|
||||||
|
dislikePercentage = (dislikeCount == 0 ? 0 : (float) dislikeCount / (likeCount + dislikeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "RYDVoteData{"
|
return "RYDVoteData{"
|
||||||
@@ -73,4 +118,5 @@ public final class RYDVoteData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// equals and hashcode is not implemented (currently not needed)
|
// equals and hashcode is not implemented (currently not needed)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
package app.revanced.integrations.returnyoutubedislike.requests;
|
package app.revanced.integrations.returnyoutubedislike.requests;
|
||||||
|
|
||||||
import static app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeRoutes.getRYDConnectionFromRoute;
|
|
||||||
import static app.revanced.integrations.sponsorblock.StringRef.str;
|
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import app.revanced.integrations.requests.Requester;
|
||||||
|
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
||||||
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
import app.revanced.integrations.utils.ReVancedUtils;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import app.revanced.integrations.requests.Requester;
|
import static app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeRoutes.getRYDConnectionFromRoute;
|
||||||
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
import static app.revanced.integrations.sponsorblock.StringRef.str;
|
||||||
import app.revanced.integrations.utils.LogHelper;
|
|
||||||
import app.revanced.integrations.utils.ReVancedUtils;
|
|
||||||
|
|
||||||
public class ReturnYouTubeDislikeApi {
|
public class ReturnYouTubeDislikeApi {
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +46,13 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
/**
|
/**
|
||||||
* Response code of a successful API call
|
* Response code of a successful API call
|
||||||
*/
|
*/
|
||||||
private static final int SUCCESS_HTTP_STATUS_CODE = 200;
|
private static final int HTTP_STATUS_CODE_SUCCESS = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response code indicating the video id is not for a video that can be voted for.
|
||||||
|
* (it's not a Short or a regular video, and it's likely a YouTube Story)
|
||||||
|
*/
|
||||||
|
private static final int HTTP_STATUS_CODE_NOT_FOUND = 404;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates a client rate limit has been reached
|
* Indicates a client rate limit has been reached
|
||||||
@@ -57,9 +61,9 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* How long to wait until API calls are resumed, if a rate limit is hit.
|
* How long to wait until API calls are resumed, if a rate limit is hit.
|
||||||
* No clear guideline of how long to backoff. Using 60 seconds for now.
|
* No clear guideline of how long to backoff. Using 2 minutes for now.
|
||||||
*/
|
*/
|
||||||
private static final int RATE_LIMIT_BACKOFF_SECONDS = 60;
|
private static final int RATE_LIMIT_BACKOFF_SECONDS = 120;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last time a {@link #RATE_LIMIT_HTTP_STATUS_CODE} was reached.
|
* Last time a {@link #RATE_LIMIT_HTTP_STATUS_CODE} was reached.
|
||||||
@@ -133,6 +137,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
*
|
*
|
||||||
* @param maximumTimeToWait maximum time to wait
|
* @param maximumTimeToWait maximum time to wait
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
private static long randomlyWaitIfLocallyDebugging(long maximumTimeToWait) {
|
private static long randomlyWaitIfLocallyDebugging(long maximumTimeToWait) {
|
||||||
final boolean DEBUG_RANDOMLY_DELAY_NETWORK_CALLS = false; // set true to debug UI
|
final boolean DEBUG_RANDOMLY_DELAY_NETWORK_CALLS = false; // set true to debug UI
|
||||||
if (DEBUG_RANDOMLY_DELAY_NETWORK_CALLS) {
|
if (DEBUG_RANDOMLY_DELAY_NETWORK_CALLS) {
|
||||||
@@ -183,6 +188,8 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
|
|
||||||
if (httpResponseCode == RATE_LIMIT_HTTP_STATUS_CODE) {
|
if (httpResponseCode == RATE_LIMIT_HTTP_STATUS_CODE) {
|
||||||
lastTimeRateLimitWasHit = System.currentTimeMillis();
|
lastTimeRateLimitWasHit = System.currentTimeMillis();
|
||||||
|
//noinspection NonAtomicOperationOnVolatileField // don't care, field is used only as an estimate
|
||||||
|
numberOfRateLimitRequestsEncountered++;
|
||||||
LogHelper.printDebug(() -> "API rate limit was hit. Stopping API calls for the next "
|
LogHelper.printDebug(() -> "API rate limit was hit. Stopping API calls for the next "
|
||||||
+ RATE_LIMIT_BACKOFF_SECONDS + " seconds");
|
+ RATE_LIMIT_BACKOFF_SECONDS + " seconds");
|
||||||
ReVancedUtils.runOnMainThread(() -> { // must show toasts on main thread
|
ReVancedUtils.runOnMainThread(() -> { // must show toasts on main thread
|
||||||
@@ -208,7 +215,6 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
fetchCallNumberOfFailures++;
|
fetchCallNumberOfFailures++;
|
||||||
} else if (rateLimitHit) {
|
} else if (rateLimitHit) {
|
||||||
fetchCallResponseTimeLast = FETCH_CALL_RESPONSE_TIME_VALUE_RATE_LIMIT;
|
fetchCallResponseTimeLast = FETCH_CALL_RESPONSE_TIME_VALUE_RATE_LIMIT;
|
||||||
numberOfRateLimitRequestsEncountered++;
|
|
||||||
} else {
|
} else {
|
||||||
fetchCallResponseTimeLast = responseTimeOfFetchCall;
|
fetchCallResponseTimeLast = responseTimeOfFetchCall;
|
||||||
}
|
}
|
||||||
@@ -228,7 +234,6 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
LogHelper.printDebug(() -> "Fetching votes for: " + videoId);
|
LogHelper.printDebug(() -> "Fetching votes for: " + videoId);
|
||||||
final long timeNetworkCallStarted = System.currentTimeMillis();
|
final long timeNetworkCallStarted = System.currentTimeMillis();
|
||||||
|
|
||||||
String connectionErrorMessageStringKey = "revanced_ryd_failure_connection_timeout";
|
|
||||||
try {
|
try {
|
||||||
HttpURLConnection connection = getRYDConnectionFromRoute(ReturnYouTubeDislikeRoutes.GET_DISLIKES, videoId);
|
HttpURLConnection connection = getRYDConnectionFromRoute(ReturnYouTubeDislikeRoutes.GET_DISLIKES, videoId);
|
||||||
// request headers, as per https://returnyoutubedislike.com/docs/fetching
|
// request headers, as per https://returnyoutubedislike.com/docs/fetching
|
||||||
@@ -250,7 +255,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseCode == SUCCESS_HTTP_STATUS_CODE) {
|
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||||
final long timeNetworkCallEnded = System.currentTimeMillis(); // record end time before parsing
|
final long timeNetworkCallEnded = System.currentTimeMillis(); // record end time before parsing
|
||||||
// do not disconnect, the same server connection will likely be used again soon
|
// do not disconnect, the same server connection will likely be used again soon
|
||||||
JSONObject json = Requester.parseJSONObject(connection);
|
JSONObject json = Requester.parseJSONObject(connection);
|
||||||
@@ -263,13 +268,20 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
LogHelper.printException(() -> "Failed to parse video: " + videoId + " json: " + json, ex);
|
LogHelper.printException(() -> "Failed to parse video: " + videoId + " json: " + json, ex);
|
||||||
// fall thru to update statistics
|
// fall thru to update statistics
|
||||||
}
|
}
|
||||||
|
} else if (responseCode == HTTP_STATUS_CODE_NOT_FOUND) {
|
||||||
|
// normal response when viewing YouTube Stories (cannot vote for these)
|
||||||
|
LogHelper.printDebug(() -> "Video has no like/dislikes (video is a YouTube Story?): " + videoId);
|
||||||
|
return null; // do not updated connection statistics
|
||||||
} else {
|
} else {
|
||||||
LogHelper.printException(() -> "Failed to fetch votes for video: " + videoId
|
LogHelper.printException(() -> "Failed to fetch votes for video: " + videoId + " response code was: " + responseCode,
|
||||||
+ " response code was: " + responseCode, null, str(connectionErrorMessageStringKey));
|
null, str("revanced_ryd_failure_connection_status_code", responseCode));
|
||||||
connection.disconnect(); // something went wrong, might as well disconnect
|
connection.disconnect(); // something went wrong, might as well disconnect
|
||||||
}
|
}
|
||||||
} catch (Exception ex) { // connection timed out, response timeout, or some other network error
|
} catch (SocketTimeoutException ex) { // connection timed out, response timeout, or some other network error
|
||||||
LogHelper.printException(() -> "Failed to fetch votes", ex, str(connectionErrorMessageStringKey));
|
LogHelper.printException(() -> "Failed to fetch votes", ex, str("revanced_ryd_failure_connection_timeout"));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// should never happen
|
||||||
|
LogHelper.printException(() -> "Failed to fetch votes", ex, str("revanced_ryd_failure_generic", ex.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatistics(timeNetworkCallStarted, System.currentTimeMillis(), true, false);
|
updateStatistics(timeNetworkCallStarted, System.currentTimeMillis(), true, false);
|
||||||
@@ -299,7 +311,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
connection.disconnect(); // disconnect, as no more connections will be made for a little while
|
connection.disconnect(); // disconnect, as no more connections will be made for a little while
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (responseCode == SUCCESS_HTTP_STATUS_CODE) {
|
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||||
JSONObject json = Requester.parseJSONObject(connection);
|
JSONObject json = Requester.parseJSONObject(connection);
|
||||||
String challenge = json.getString("challenge");
|
String challenge = json.getString("challenge");
|
||||||
int difficulty = json.getInt("difficulty");
|
int difficulty = json.getInt("difficulty");
|
||||||
@@ -340,7 +352,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
connection.disconnect(); // disconnect, as no more connections will be made for a little while
|
connection.disconnect(); // disconnect, as no more connections will be made for a little while
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (responseCode == SUCCESS_HTTP_STATUS_CODE) {
|
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||||
String result = Requester.parseJson(connection);
|
String result = Requester.parseJson(connection);
|
||||||
if (result.equalsIgnoreCase("true")) {
|
if (result.equalsIgnoreCase("true")) {
|
||||||
LogHelper.printDebug(() -> "Registration confirmation successful for user: " + userId);
|
LogHelper.printDebug(() -> "Registration confirmation successful for user: " + userId);
|
||||||
@@ -387,7 +399,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
connection.disconnect(); // disconnect, as no more connections will be made for a little while
|
connection.disconnect(); // disconnect, as no more connections will be made for a little while
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (responseCode == SUCCESS_HTTP_STATUS_CODE) {
|
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||||
JSONObject json = Requester.parseJSONObject(connection);
|
JSONObject json = Requester.parseJSONObject(connection);
|
||||||
String challenge = json.getString("challenge");
|
String challenge = json.getString("challenge");
|
||||||
int difficulty = json.getInt("difficulty");
|
int difficulty = json.getInt("difficulty");
|
||||||
@@ -431,7 +443,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseCode == SUCCESS_HTTP_STATUS_CODE) {
|
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||||
String result = Requester.parseJson(connection);
|
String result = Requester.parseJson(connection);
|
||||||
if (result.equalsIgnoreCase("true")) {
|
if (result.equalsIgnoreCase("true")) {
|
||||||
LogHelper.printDebug(() -> "Vote confirm successful for video: " + videoId);
|
LogHelper.printDebug(() -> "Vote confirm successful for video: " + videoId);
|
||||||
@@ -469,9 +481,7 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
byte[] decodedChallenge = Base64.decode(challenge, Base64.NO_WRAP);
|
byte[] decodedChallenge = Base64.decode(challenge, Base64.NO_WRAP);
|
||||||
|
|
||||||
byte[] buffer = new byte[20];
|
byte[] buffer = new byte[20];
|
||||||
for (int i = 4; i < 20; i++) { // FIXME replace with System.arrayCopy
|
System.arraycopy(decodedChallenge, 0, buffer, 4, 16);
|
||||||
buffer[i] = decodedChallenge[i - 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageDigest md;
|
MessageDigest md;
|
||||||
try {
|
try {
|
||||||
@@ -513,9 +523,9 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
|
|
||||||
private static int countLeadingZeroes(byte[] uInt8View) {
|
private static int countLeadingZeroes(byte[] uInt8View) {
|
||||||
int zeroes = 0;
|
int zeroes = 0;
|
||||||
int value = 0;
|
int value;
|
||||||
for (int i = 0; i < uInt8View.length; i++) {
|
for (byte b : uInt8View) {
|
||||||
value = uInt8View[i] & 0xFF;
|
value = b & 0xFF;
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
zeroes += 8;
|
zeroes += 8;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -62,8 +62,6 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
|||||||
setPreferenceScreen(preferenceScreen);
|
setPreferenceScreen(preferenceScreen);
|
||||||
|
|
||||||
enabledPreference = new SwitchPreference(context);
|
enabledPreference = new SwitchPreference(context);
|
||||||
enabledPreference.setKey(SettingsEnum.RYD_ENABLED.getPath());
|
|
||||||
enabledPreference.setDefaultValue(SettingsEnum.RYD_ENABLED.getDefaultValue());
|
|
||||||
enabledPreference.setChecked(SettingsEnum.RYD_ENABLED.getBoolean());
|
enabledPreference.setChecked(SettingsEnum.RYD_ENABLED.getBoolean());
|
||||||
enabledPreference.setTitle(str("revanced_ryd_enable_title"));
|
enabledPreference.setTitle(str("revanced_ryd_enable_title"));
|
||||||
enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
@@ -77,8 +75,6 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
|||||||
preferenceScreen.addPreference(enabledPreference);
|
preferenceScreen.addPreference(enabledPreference);
|
||||||
|
|
||||||
percentagePreference = new SwitchPreference(context);
|
percentagePreference = new SwitchPreference(context);
|
||||||
percentagePreference.setKey(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getPath());
|
|
||||||
percentagePreference.setDefaultValue(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getDefaultValue());
|
|
||||||
percentagePreference.setChecked(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean());
|
percentagePreference.setChecked(SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.getBoolean());
|
||||||
percentagePreference.setTitle(str("revanced_ryd_dislike_percentage_title"));
|
percentagePreference.setTitle(str("revanced_ryd_dislike_percentage_title"));
|
||||||
percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
@@ -90,8 +86,6 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
|||||||
preferenceScreen.addPreference(percentagePreference);
|
preferenceScreen.addPreference(percentagePreference);
|
||||||
|
|
||||||
compactLayoutPreference = new SwitchPreference(context);
|
compactLayoutPreference = new SwitchPreference(context);
|
||||||
compactLayoutPreference.setKey(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getPath());
|
|
||||||
compactLayoutPreference.setDefaultValue(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getDefaultValue());
|
|
||||||
compactLayoutPreference.setChecked(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getBoolean());
|
compactLayoutPreference.setChecked(SettingsEnum.RYD_USE_COMPACT_LAYOUT.getBoolean());
|
||||||
compactLayoutPreference.setTitle(str("revanced_ryd_compact_layout_title"));
|
compactLayoutPreference.setTitle(str("revanced_ryd_compact_layout_title"));
|
||||||
compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
screen.addPreference(colorPreference);
|
screen.addPreference(colorPreference);
|
||||||
colorPreference.setTitle(str("color_change"));
|
colorPreference.setTitle(str("color_change"));
|
||||||
colorPreference.setSummary(str("color_change_sum"));
|
colorPreference.setSummary(str("color_change_sum"));
|
||||||
|
colorPreference.setSelectable(false);
|
||||||
preferencesToDisableWhenSBDisabled.add(colorPreference);
|
preferencesToDisableWhenSBDisabled.add(colorPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +185,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
Preference preference = new Preference(context);
|
Preference preference = new Preference(context);
|
||||||
category.addPreference(preference);
|
category.addPreference(preference);
|
||||||
preference.setTitle(str("stats_loading"));
|
preference.setTitle(str("stats_loading"));
|
||||||
|
preference.setSelectable(false);
|
||||||
|
|
||||||
SBRequester.retrieveUserStats(category, preference);
|
SBRequester.retrieveUserStats(category, preference);
|
||||||
}
|
}
|
||||||
@@ -211,6 +213,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
Preference preference = new Preference(context);
|
Preference preference = new Preference(context);
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
preference.setTitle(str("about_madeby"));
|
preference.setTitle(str("about_madeby"));
|
||||||
|
preference.setSelectable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -233,11 +236,14 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Preference preference = new SwitchPreference(context);
|
SwitchPreference preference = new SwitchPreference(context);
|
||||||
preference.setTitle(str("general_skiptoast"));
|
preference.setTitle(str("general_skiptoast"));
|
||||||
preference.setSummary(str("general_skiptoast_sum"));
|
preference.setSummary(str("general_skiptoast_sum"));
|
||||||
preference.setKey(SettingsEnum.SB_SHOW_TOAST_WHEN_SKIP.getPath());
|
preference.setChecked(SettingsEnum.SB_SHOW_TOAST_WHEN_SKIP.getBoolean());
|
||||||
preference.setDefaultValue(SettingsEnum.SB_SHOW_TOAST_WHEN_SKIP.getDefaultValue());
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
|
SettingsEnum.SB_SHOW_TOAST_WHEN_SKIP.saveValue(newValue);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
preference.setOnPreferenceClickListener(preference12 -> {
|
preference.setOnPreferenceClickListener(preference12 -> {
|
||||||
Toast.makeText(preference12.getContext(), str("skipped_sponsor"), Toast.LENGTH_SHORT).show();
|
Toast.makeText(preference12.getContext(), str("skipped_sponsor"), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
@@ -247,21 +253,28 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Preference preference = new SwitchPreference(context);
|
SwitchPreference preference = new SwitchPreference(context);
|
||||||
preference.setTitle(str("general_skipcount"));
|
preference.setTitle(str("general_skipcount"));
|
||||||
preference.setSummary(str("general_skipcount_sum"));
|
preference.setSummary(str("general_skipcount_sum"));
|
||||||
preference.setKey(SettingsEnum.SB_COUNT_SKIPS.getPath());
|
preference.setChecked(SettingsEnum.SB_COUNT_SKIPS.getBoolean());
|
||||||
preference.setDefaultValue(SettingsEnum.SB_COUNT_SKIPS.getDefaultValue());
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
|
SettingsEnum.SB_COUNT_SKIPS.saveValue(newValue);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Preference preference = new SwitchPreference(context);
|
SwitchPreference preference = new SwitchPreference(context);
|
||||||
preference.setTitle(str("general_time_without_sb"));
|
preference.setTitle(str("general_time_without_sb"));
|
||||||
preference.setSummary(str("general_time_without_sb_sum"));
|
preference.setSummary(str("general_time_without_sb_sum"));
|
||||||
preference.setKey(SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getPath());
|
preference.setChecked(SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean());
|
||||||
preference.setDefaultValue(SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getDefaultValue());
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
|
SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.saveValue(newValue);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
}
|
}
|
||||||
@@ -271,8 +284,11 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
preference.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
|
preference.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||||
preference.setTitle(str("general_adjusting"));
|
preference.setTitle(str("general_adjusting"));
|
||||||
preference.setSummary(str("general_adjusting_sum"));
|
preference.setSummary(str("general_adjusting_sum"));
|
||||||
preference.setKey(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getPath());
|
preference.setText(String.valueOf(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt()));
|
||||||
preference.setDefaultValue(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getDefaultValue() + "");
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
|
SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.saveValue(Integer.valueOf(newValue.toString()));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
}
|
}
|
||||||
@@ -282,18 +298,25 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment implements
|
|||||||
preference.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
preference.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||||
preference.setTitle(str("general_min_duration"));
|
preference.setTitle(str("general_min_duration"));
|
||||||
preference.setSummary(str("general_min_duration_sum"));
|
preference.setSummary(str("general_min_duration_sum"));
|
||||||
preference.setKey(SettingsEnum.SB_MIN_DURATION.getPath());
|
preference.setText(String.valueOf(SettingsEnum.SB_MIN_DURATION.getFloat()));
|
||||||
preference.setDefaultValue(SettingsEnum.SB_MIN_DURATION.getDefaultValue() + "");
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
|
SettingsEnum.SB_MIN_DURATION.saveValue(Float.valueOf(newValue.toString()));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Preference preference = new EditTextPreference(context);
|
EditTextPreference preference = new EditTextPreference(context);
|
||||||
preference.setTitle(str("general_uuid"));
|
preference.setTitle(str("general_uuid"));
|
||||||
preference.setSummary(str("general_uuid_sum"));
|
preference.setSummary(str("general_uuid_sum"));
|
||||||
preference.setKey(SettingsEnum.SB_UUID.getPath());
|
preference.setText(SettingsEnum.SB_UUID.getString());
|
||||||
preference.setDefaultValue(SettingsEnum.SB_UUID.getDefaultValue() + "");
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
|
SettingsEnum.SB_UUID.saveValue(newValue.toString());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import app.revanced.integrations.utils.Event
|
|||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
enum class PlayerType {
|
enum class PlayerType {
|
||||||
NONE, // this also includes when shorts are playing
|
NONE, // includes Shorts playback
|
||||||
HIDDEN,
|
HIDDEN, // also includes YouTube Shorts and Stories, if a regular video is minimized and a Short/Story is then opened
|
||||||
WATCH_WHILE_MINIMIZED,
|
WATCH_WHILE_MINIMIZED,
|
||||||
WATCH_WHILE_MAXIMIZED,
|
WATCH_WHILE_MAXIMIZED,
|
||||||
WATCH_WHILE_FULLSCREEN,
|
WATCH_WHILE_FULLSCREEN,
|
||||||
@@ -42,6 +42,7 @@ enum class PlayerType {
|
|||||||
currentPlayerType = value
|
currentPlayerType = value
|
||||||
onChange(currentPlayerType)
|
onChange(currentPlayerType)
|
||||||
}
|
}
|
||||||
|
@Volatile // value is read/write from different threads
|
||||||
private var currentPlayerType = NONE
|
private var currentPlayerType = NONE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,4 +50,13 @@ enum class PlayerType {
|
|||||||
*/
|
*/
|
||||||
val onChange = Event<PlayerType>()
|
val onChange = Event<PlayerType>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current player type is [NONE] or [HIDDEN]
|
||||||
|
*
|
||||||
|
* @return True, if nothing, a Short, or a Story is playing.
|
||||||
|
*/
|
||||||
|
fun isNoneOrHidden(): Boolean {
|
||||||
|
return this == NONE || this == HIDDEN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -193,14 +193,13 @@ public class PlayerController {
|
|||||||
SettingsEnum.SB_SKIPPED_SEGMENTS_TIME.saveValue(newSkippedTime);
|
SettingsEnum.SB_SKIPPED_SEGMENTS_TIME.saveValue(newSkippedTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new Thread(() -> { // fixme: use ReVancedUtils#runOnBackgroundThread
|
if (SettingsEnum.SB_COUNT_SKIPS.getBoolean()
|
||||||
if (SettingsEnum.SB_COUNT_SKIPS.getBoolean() &&
|
&& segment.category != SponsorBlockSettings.SegmentInfo.UNSUBMITTED
|
||||||
segment.category != SponsorBlockSettings.SegmentInfo.UNSUBMITTED &&
|
&& millis - segment.start < 2000) { // Only skips from the start should count as a view
|
||||||
millis - segment.start < 2000) {
|
ReVancedUtils.runOnBackgroundThread(() -> {
|
||||||
// Only skips from the start should count as a view
|
|
||||||
SBRequester.sendViewCountRequest(segment);
|
SBRequester.sendViewCountRequest(segment);
|
||||||
}
|
});
|
||||||
}).start();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setHighPrecisionVideoTime(final long millis) {
|
public static void setHighPrecisionVideoTime(final long millis) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user