mirror of
https://github.com/revanced/revanced-integrations.git
synced 2024-12-01 00:02:55 +01:00
chore: merge branch dev
to main
(#373)
This commit is contained in:
commit
e774be0f05
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.
|
63
CHANGELOG.md
63
CHANGELOG.md
@ -1,3 +1,66 @@
|
|||||||
|
# [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)
|
# [0.105.0](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.105.0) (2023-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(project(mapOf("path" to ":dummy")))
|
compileOnly(project(mapOf("path" to ":dummy")))
|
||||||
compileOnly("androidx.annotation:annotation:1.6.0")
|
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.okhttp3:okhttp:5.0.0-alpha.11")
|
||||||
compileOnly("com.squareup.retrofit2:retrofit:2.9.0")
|
compileOnly("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
}
|
}
|
||||||
|
@ -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 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 audioTrackButton = new BlockRule(SettingsEnum.HIDE_AUDIO_TRACK_BUTTON, "multi_feed_icon_button");
|
||||||
var artistCard = new BlockRule(SettingsEnum.HIDE_ARTIST_CARDS, "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", "macro_markers_carousel");
|
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",
|
"carousel_footered_layout",
|
||||||
"text_image_button_layout",
|
"text_image_button_layout",
|
||||||
"primetime_promo",
|
"primetime_promo",
|
||||||
"feature_grid_interstitial",
|
|
||||||
"product_details",
|
"product_details",
|
||||||
|
"full_width_portrait_image_layout",
|
||||||
"brand_video_shelf"
|
"brand_video_shelf"
|
||||||
);
|
);
|
||||||
var movieAds = new BlockRule(
|
var movieAds = new BlockRule(
|
||||||
@ -97,6 +98,7 @@ public final class GeneralAdsPatch extends Filter {
|
|||||||
merchandise,
|
merchandise,
|
||||||
infoPanel,
|
infoPanel,
|
||||||
channelGuidelines,
|
channelGuidelines,
|
||||||
|
audioTrackButton,
|
||||||
artistCard,
|
artistCard,
|
||||||
selfSponsor,
|
selfSponsor,
|
||||||
webLinkPanel,
|
webLinkPanel,
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package app.revanced.integrations.patches;
|
|||||||
|
|
||||||
import static app.revanced.integrations.utils.StringRef.str;
|
import static app.revanced.integrations.utils.StringRef.str;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
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;
|
||||||
@ -28,6 +29,7 @@ public class MicroGSupport {
|
|||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(26)
|
||||||
public static void checkAvailability() {
|
public static void checkAvailability() {
|
||||||
var context = Objects.requireNonNull(ReVancedUtils.getContext());
|
var context = Objects.requireNonNull(ReVancedUtils.getContext());
|
||||||
|
|
||||||
@ -41,10 +43,11 @@ public class MicroGSupport {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try (var client = context.getContentResolver().acquireContentProviderClient(VANCED_MICROG_PROVIDER)) {
|
try (var client = context.getContentResolver().acquireContentProviderClient(VANCED_MICROG_PROVIDER)) {
|
||||||
if (client != null) return;
|
if (client != null) return;
|
||||||
LogHelper.printInfo(() -> "Vanced MicroG is not running in the background");
|
LogHelper.printInfo(() -> "Vanced MicroG is not running in the background");
|
||||||
startIntent(context, DONT_KILL_MY_APP_LINK, str("microg_not_running_warning"));
|
startIntent(context, DONT_KILL_MY_APP_LINK, str("microg_not_running_warning"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,23 +2,110 @@ package app.revanced.integrations.patches;
|
|||||||
|
|
||||||
import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote;
|
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.Spanned;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
import app.revanced.integrations.shared.PlayerType;
|
||||||
import app.revanced.integrations.utils.LogHelper;
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
import app.revanced.integrations.utils.ReVancedUtils;
|
||||||
|
|
||||||
public class ReturnYouTubeDislikePatch {
|
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.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static void newVideoLoaded(String videoId) {
|
public static void newVideoLoaded(@NonNull String videoId) {
|
||||||
try {
|
try {
|
||||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) return;
|
if (!SettingsEnum.RYD_ENABLED.getBoolean()) return;
|
||||||
ReturnYouTubeDislike.newVideoLoaded(videoId);
|
ReturnYouTubeDislike.newVideoLoaded(videoId);
|
||||||
@ -47,14 +134,23 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
@NonNull AtomicReference<CharSequence> textRef,
|
@NonNull AtomicReference<CharSequence> textRef,
|
||||||
@NonNull CharSequence original) {
|
@NonNull CharSequence original) {
|
||||||
try {
|
try {
|
||||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
|
if (!SettingsEnum.RYD_ENABLED.getBoolean() || PlayerType.getCurrent().isNoneOrHidden()) {
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
SpannableString replacement = ReturnYouTubeDislike.getDislikeSpanForContext(conversionContext, original);
|
|
||||||
if (replacement != null) {
|
String conversionContextString = conversionContext.toString();
|
||||||
textRef.set(replacement);
|
final boolean isSegmentedButton;
|
||||||
return replacement;
|
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) {
|
} catch (Exception ex) {
|
||||||
LogHelper.printException(() -> "onLithoTextLoaded failure", ex);
|
LogHelper.printException(() -> "onLithoTextLoaded failure", ex);
|
||||||
}
|
}
|
||||||
@ -71,10 +167,7 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
|
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
SpannableString replacement = ReturnYouTubeDislike.getDislikeSpanForShort(original);
|
return ReturnYouTubeDislike.getDislikeSpanForShort(original);
|
||||||
if (replacement != null) {
|
|
||||||
return replacement;
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LogHelper.printException(() -> "onShortsComponentCreated failure", ex);
|
LogHelper.printException(() -> "onShortsComponentCreated failure", ex);
|
||||||
}
|
}
|
||||||
@ -97,6 +190,7 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
for (Vote v : Vote.values()) {
|
for (Vote v : Vote.values()) {
|
||||||
if (v.value == vote) {
|
if (v.value == vote) {
|
||||||
ReturnYouTubeDislike.sendVote(v);
|
ReturnYouTubeDislike.sendVote(v);
|
||||||
|
updateOldUIDislikesTextView();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,8 @@ import app.revanced.integrations.settings.SettingsEnum;
|
|||||||
public class SpoofAppVersionPatch {
|
public class SpoofAppVersionPatch {
|
||||||
|
|
||||||
public static String getYouTubeVersionOverride(String version) {
|
public static String getYouTubeVersionOverride(String version) {
|
||||||
if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()){
|
if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()) {
|
||||||
// Override with the most recent version that does not show the new UI player layout.
|
return SettingsEnum.SPOOF_APP_VERSION_TARGET.getString();
|
||||||
// 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";
|
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,27 @@ public class SpoofSignatureVerificationPatch {
|
|||||||
"SAFg" // Autoplay in scrim
|
"SAFg" // Autoplay in scrim
|
||||||
};
|
};
|
||||||
|
|
||||||
@Nullable
|
/**
|
||||||
private static String currentVideoId;
|
* 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If any of the subtitles settings encountered from the current video have been non default values.
|
* The number of non default subtitle settings encountered for the current video.
|
||||||
*/
|
*/
|
||||||
private static boolean nonDefaultSubtitlesEncountered;
|
private static int numberOfNonDefaultSettingsObserved;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String currentVideoId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
@ -137,15 +151,19 @@ public class SpoofSignatureVerificationPatch {
|
|||||||
// then this will incorrectly replace the 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
|
// 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).
|
// and do not replace any window settings for the video (regardless if they match a shorts default).
|
||||||
if (signatureSpoofing && !nonDefaultSubtitlesEncountered && !PlayerType.getCurrent().isNoneOrHidden()) {
|
if (signatureSpoofing && !PlayerType.getCurrent().isNoneOrHidden()
|
||||||
|
&& numberOfNonDefaultSettingsObserved < NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU) {
|
||||||
for (SubtitleWindowReplacementSettings setting : SubtitleWindowReplacementSettings.values()) {
|
for (SubtitleWindowReplacementSettings setting : SubtitleWindowReplacementSettings.values()) {
|
||||||
if (setting.match(ap, ah, av, vs, sd)) {
|
if (setting.match(ap, ah, av, vs, sd)) {
|
||||||
return setting.replacementSetting();
|
return setting.replacementSetting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Settings appear to be custom subtitles.
|
|
||||||
nonDefaultSubtitlesEncountered = true;
|
numberOfNonDefaultSettingsObserved++;
|
||||||
LogHelper.printDebug(() -> "Non default subtitles found. Using existing settings without replacement.");
|
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new int[]{ap, ah, av};
|
return new int[]{ap, ah, av};
|
||||||
@ -160,7 +178,7 @@ public class SpoofSignatureVerificationPatch {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentVideoId = videoId;
|
currentVideoId = videoId;
|
||||||
nonDefaultSubtitlesEncountered = false;
|
numberOfNonDefaultSettingsObserved = 0;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LogHelper.printException(() -> "setCurrentVideoId failure", ex);
|
LogHelper.printException(() -> "setCurrentVideoId failure", ex);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ public class ReturnYouTubeDislike {
|
|||||||
/**
|
/**
|
||||||
* If {@link #currentVideoId} and the RYD data is for the last shorts loaded.
|
* 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.
|
* Stores the results of the vote api fetch, and used as a barrier to wait until fetch completes.
|
||||||
@ -141,7 +141,7 @@ public class ReturnYouTubeDislike {
|
|||||||
LogHelper.printDebug(() -> "Clearing data");
|
LogHelper.printDebug(() -> "Clearing data");
|
||||||
}
|
}
|
||||||
currentVideoId = videoId;
|
currentVideoId = videoId;
|
||||||
lastVideoLoadedWasShort = false;
|
dislikeDataIsShort = false;
|
||||||
voteFetchFuture = null;
|
voteFetchFuture = null;
|
||||||
originalDislikeSpan = null;
|
originalDislikeSpan = null;
|
||||||
replacementLikeDislikeSpan = null;
|
replacementLikeDislikeSpan = null;
|
||||||
@ -198,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.
|
// 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
|
// 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.
|
// 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,
|
// No need to wrap the call in a try/catch,
|
||||||
// as any exceptions are propagated out in the later Future#Get call.
|
// as any exceptions are propagated out in the later Future#Get call.
|
||||||
@ -207,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
|
@NonNull
|
||||||
public static SpannableString getDislikeSpanForContext(@NonNull Object conversionContext, @NonNull CharSequence original) {
|
public static Spanned getDislikesSpanForRegularVideo(@NonNull Spanned original, boolean isSegmentedButton) {
|
||||||
if (PlayerType.getCurrent().isNoneOrHidden()) {
|
if (dislikeDataIsShort) {
|
||||||
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) {
|
|
||||||
// user:
|
// user:
|
||||||
// 1, opened a video
|
// 1, opened a video
|
||||||
// 2. opened a short (without closing the regular video)
|
// 2. opened a short (without closing the regular video)
|
||||||
// 3. closed the short
|
// 3. closed the short
|
||||||
// 4. regular video is now present, but the videoId and RYD data is still for 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");
|
LogHelper.printDebug(() -> "Ignoring getDislikeSpanForContext(), as data loaded is for prior short");
|
||||||
return null;
|
return original;
|
||||||
}
|
}
|
||||||
|
return waitForFetchAndUpdateReplacementSpan(original, isSegmentedButton);
|
||||||
return waitForFetchAndUpdateReplacementSpan((Spannable) original, isSegmentedButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a Shorts dislike Spannable is created.
|
* Called when a Shorts dislike Spannable is created.
|
||||||
*/
|
*/
|
||||||
public static SpannableString getDislikeSpanForShort(@NonNull Spanned original) {
|
@NonNull
|
||||||
lastVideoLoadedWasShort = true; // it's now certain the video and data are a short
|
public static Spanned getDislikeSpanForShort(@NonNull Spanned original) {
|
||||||
|
dislikeDataIsShort = true; // it's now certain the video and data are a short
|
||||||
return waitForFetchAndUpdateReplacementSpan(original, false);
|
return waitForFetchAndUpdateReplacementSpan(original, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,17 +237,14 @@ public class ReturnYouTubeDislike {
|
|||||||
return span.toString().indexOf(MIDDLE_SEPARATOR_CHARACTER) != -1;
|
return span.toString().indexOf(MIDDLE_SEPARATOR_CHARACTER) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@NonNull
|
||||||
* @return NULL if the span does not need changing or if RYD is not available.
|
private static Spanned waitForFetchAndUpdateReplacementSpan(@NonNull Spanned oldSpannable, boolean isSegmentedButton) {
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private static SpannableString waitForFetchAndUpdateReplacementSpan(@NonNull Spanned oldSpannable, boolean isSegmentedButton) {
|
|
||||||
try {
|
try {
|
||||||
synchronized (videoIdLockObject) {
|
synchronized (videoIdLockObject) {
|
||||||
if (replacementLikeDislikeSpan != null) {
|
if (replacementLikeDislikeSpan != null) {
|
||||||
if (spansHaveEqualTextAndColor(replacementLikeDislikeSpan, oldSpannable)) {
|
if (spansHaveEqualTextAndColor(replacementLikeDislikeSpan, oldSpannable)) {
|
||||||
LogHelper.printDebug(() -> "Ignoring previously created dislikes span");
|
LogHelper.printDebug(() -> "Ignoring previously created dislikes span");
|
||||||
return null;
|
return oldSpannable;
|
||||||
}
|
}
|
||||||
if (spansHaveEqualTextAndColor(Objects.requireNonNull(originalDislikeSpan), oldSpannable)) {
|
if (spansHaveEqualTextAndColor(Objects.requireNonNull(originalDislikeSpan), oldSpannable)) {
|
||||||
LogHelper.printDebug(() -> "Replacing span with previously created dislike span");
|
LogHelper.printDebug(() -> "Replacing span with previously created dislike span");
|
||||||
@ -269,11 +253,11 @@ public class ReturnYouTubeDislike {
|
|||||||
}
|
}
|
||||||
if (isSegmentedButton && isPreviouslyCreatedSegmentedSpan(oldSpannable)) {
|
if (isSegmentedButton && isPreviouslyCreatedSegmentedSpan(oldSpannable)) {
|
||||||
// need to recreate using original, as oldSpannable has prior outdated dislike values
|
// need to recreate using original, as oldSpannable has prior outdated dislike values
|
||||||
oldSpannable = originalDislikeSpan;
|
if (originalDislikeSpan == null) {
|
||||||
if (oldSpannable == null) {
|
|
||||||
LogHelper.printDebug(() -> "Cannot add dislikes - original span is null"); // should never happen
|
LogHelper.printDebug(() -> "Cannot add dislikes - original span is null"); // should never happen
|
||||||
return null;
|
return oldSpannable;
|
||||||
}
|
}
|
||||||
|
oldSpannable = originalDislikeSpan;
|
||||||
} else {
|
} else {
|
||||||
originalDislikeSpan = oldSpannable; // most up to date original
|
originalDislikeSpan = oldSpannable; // most up to date original
|
||||||
}
|
}
|
||||||
@ -284,12 +268,12 @@ public class ReturnYouTubeDislike {
|
|||||||
Future<RYDVoteData> fetchFuture = getVoteFetchFuture();
|
Future<RYDVoteData> fetchFuture = getVoteFetchFuture();
|
||||||
if (fetchFuture == null) {
|
if (fetchFuture == null) {
|
||||||
LogHelper.printDebug(() -> "fetch future not available (user enabled RYD while video was playing?)");
|
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);
|
RYDVoteData votingData = fetchFuture.get(MAX_MILLISECONDS_TO_BLOCK_UI_WHILE_WAITING_FOR_FETCH_VOTES_TO_COMPLETE, TimeUnit.MILLISECONDS);
|
||||||
if (votingData == null) {
|
if (votingData == null) {
|
||||||
LogHelper.printDebug(() -> "Cannot add dislike to UI (RYD data not available)");
|
LogHelper.printDebug(() -> "Cannot add dislike to UI (RYD data not available)");
|
||||||
return null;
|
return oldSpannable;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpannableString replacement = createDislikeSpan(oldSpannable, isSegmentedButton, votingData);
|
SpannableString replacement = createDislikeSpan(oldSpannable, isSegmentedButton, votingData);
|
||||||
@ -304,7 +288,7 @@ public class ReturnYouTubeDislike {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogHelper.printException(() -> "waitForFetchAndUpdateReplacementSpan failure", e); // should never happen
|
LogHelper.printException(() -> "waitForFetchAndUpdateReplacementSpan failure", e); // should never happen
|
||||||
}
|
}
|
||||||
return null;
|
return oldSpannable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendVote(@NonNull Vote vote) {
|
public static void sendVote(@NonNull Vote vote) {
|
||||||
@ -313,7 +297,7 @@ public class ReturnYouTubeDislike {
|
|||||||
try {
|
try {
|
||||||
// Must make a local copy of videoId, since it may change between now and when the vote thread runs.
|
// Must make a local copy of videoId, since it may change between now and when the vote thread runs.
|
||||||
String videoIdToVoteFor = getCurrentVideoId();
|
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.
|
// User enabled RYD after starting playback of a video.
|
||||||
// Or shorts was loaded with regular video present, then shorts was closed,
|
// Or shorts was loaded with regular video present, then shorts was closed,
|
||||||
// and then user voted on the now visible original video.
|
// and then user voted on the now visible original video.
|
||||||
|
@ -136,21 +136,20 @@ public class ReturnYouTubeDislikeApi {
|
|||||||
/**
|
/**
|
||||||
* Simulates a slow response by doing meaningless calculations.
|
* Simulates a slow response by doing meaningless calculations.
|
||||||
* Used to debug the app UI and verify UI timeout logic works
|
* Used to debug the app UI and verify UI timeout logic works
|
||||||
*
|
|
||||||
* @param maximumTimeToWait maximum time to wait
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
@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
|
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) {
|
||||||
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();
|
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;
|
long meaninglessValue = 0;
|
||||||
while (System.currentTimeMillis() - timeCalculationStarted < amountOfTimeToWaste) {
|
while (System.currentTimeMillis() - timeCalculationStarted < amountOfTimeToWaste) {
|
||||||
// could do a thread sleep, but that will trigger an exception if the thread is interrupted
|
// 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,
|
// 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
|
// 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.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
|
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();
|
final int responseCode = connection.getResponseCode();
|
||||||
if (checkIfRateLimitWasHit(responseCode)) {
|
if (checkIfRateLimitWasHit(responseCode)) {
|
||||||
|
@ -19,13 +19,12 @@ import app.revanced.integrations.utils.StringRef;
|
|||||||
|
|
||||||
public enum SettingsEnum {
|
public enum SettingsEnum {
|
||||||
//Download Settings
|
//Download Settings
|
||||||
// TODO: DOWNLOAD_PATH("revanced_download_path", STRING, Environment.getExternalStorageDirectory().getPath() + "/Download"),
|
DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE),
|
||||||
DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE, true),
|
|
||||||
DOWNLOADS_PACKAGE_NAME("revanced_downloads_package_name", STRING, "org.schabi.newpipe" /* NewPipe */, parents(DOWNLOADS_BUTTON_SHOWN)),
|
DOWNLOADS_PACKAGE_NAME("revanced_downloads_package_name", STRING, "org.schabi.newpipe" /* NewPipe */, parents(DOWNLOADS_BUTTON_SHOWN)),
|
||||||
|
|
||||||
// Copy video URL settings
|
// Copy video URL settings
|
||||||
COPY_VIDEO_URL_BUTTON_SHOWN("revanced_copy_video_url_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, true),
|
COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE),
|
||||||
|
|
||||||
// Video settings
|
// Video settings
|
||||||
OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS("revanced_use_old_style_quality_settings", BOOLEAN, TRUE),
|
OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS("revanced_use_old_style_quality_settings", BOOLEAN, TRUE),
|
||||||
@ -81,6 +80,7 @@ public enum SettingsEnum {
|
|||||||
DISABLE_STARTUP_SHORTS_PLAYER("revanced_startup_shorts_player_enabled", BOOLEAN, FALSE),
|
DISABLE_STARTUP_SHORTS_PLAYER("revanced_startup_shorts_player_enabled", BOOLEAN, FALSE),
|
||||||
HIDE_ALBUM_CARDS("revanced_hide_album_cards", BOOLEAN, FALSE, true),
|
HIDE_ALBUM_CARDS("revanced_hide_album_cards", BOOLEAN, FALSE, true),
|
||||||
HIDE_ARTIST_CARDS("revanced_hide_artist_cards", BOOLEAN, FALSE),
|
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_AUTOPLAY_BUTTON("revanced_hide_autoplay_button", BOOLEAN, TRUE, true),
|
||||||
HIDE_BREAKING_NEWS("revanced_hide_breaking_news", BOOLEAN, TRUE, true),
|
HIDE_BREAKING_NEWS("revanced_hide_breaking_news", BOOLEAN, TRUE, true),
|
||||||
HIDE_CAPTIONS_BUTTON("revanced_hide_captions_button", BOOLEAN, FALSE),
|
HIDE_CAPTIONS_BUTTON("revanced_hide_captions_button", BOOLEAN, FALSE),
|
||||||
@ -92,6 +92,7 @@ public enum SettingsEnum {
|
|||||||
HIDE_ENDSCREEN_CARDS("revanced_hide_endscreen_cards", BOOLEAN, TRUE),
|
HIDE_ENDSCREEN_CARDS("revanced_hide_endscreen_cards", BOOLEAN, TRUE),
|
||||||
HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", BOOLEAN, TRUE, true),
|
HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", BOOLEAN, TRUE, true),
|
||||||
HIDE_FULLSCREEN_PANELS("revanced_hide_fullscreen_panels", BOOLEAN, 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_INFO_CARDS("revanced_hide_infocards", BOOLEAN, TRUE),
|
||||||
HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE),
|
HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE),
|
||||||
HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true),
|
HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true),
|
||||||
@ -103,6 +104,7 @@ public enum SettingsEnum {
|
|||||||
HIDE_WATCH_IN_VR("revanced_hide_watch_in_vr", BOOLEAN, FALSE, true),
|
HIDE_WATCH_IN_VR("revanced_hide_watch_in_vr", BOOLEAN, FALSE, true),
|
||||||
PLAYER_POPUP_PANELS("revanced_player_popup_panels_enabled", BOOLEAN, FALSE),
|
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("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),
|
USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true),
|
||||||
WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true),
|
WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true),
|
||||||
|
|
||||||
|
@ -20,33 +20,17 @@ import app.revanced.integrations.settings.SharedPrefCategory;
|
|||||||
public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If ReturnYouTubeDislike is enabled
|
* If dislikes are shown as percentage.
|
||||||
*/
|
|
||||||
private SwitchPreference enabledPreference;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If dislikes are shown as percentage
|
|
||||||
*/
|
*/
|
||||||
private SwitchPreference percentagePreference;
|
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 SwitchPreference compactLayoutPreference;
|
||||||
|
|
||||||
private void updateUIState() {
|
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());
|
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());
|
compactLayoutPreference.setEnabled(SettingsEnum.RYD_USE_COMPACT_LAYOUT.isAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,9 +43,11 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
|||||||
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context);
|
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context);
|
||||||
setPreferenceScreen(preferenceScreen);
|
setPreferenceScreen(preferenceScreen);
|
||||||
|
|
||||||
enabledPreference = new SwitchPreference(context);
|
SwitchPreference enabledPreference = new SwitchPreference(context);
|
||||||
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.setSummaryOn(str("revanced_ryd_enable_summary_on"));
|
||||||
|
enabledPreference.setSummaryOff(str("revanced_ryd_enable_summary_off"));
|
||||||
enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
enabledPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
final boolean rydIsEnabled = (Boolean) newValue;
|
final boolean rydIsEnabled = (Boolean) newValue;
|
||||||
SettingsEnum.RYD_ENABLED.saveValue(rydIsEnabled);
|
SettingsEnum.RYD_ENABLED.saveValue(rydIsEnabled);
|
||||||
@ -75,6 +61,8 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
|||||||
percentagePreference = new SwitchPreference(context);
|
percentagePreference = new SwitchPreference(context);
|
||||||
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.setSummaryOn(str("revanced_ryd_dislike_percentage_summary_on"));
|
||||||
|
percentagePreference.setSummaryOff(str("revanced_ryd_dislike_percentage_summary_off"));
|
||||||
percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
percentagePreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.saveValue(newValue);
|
SettingsEnum.RYD_SHOW_DISLIKE_PERCENTAGE.saveValue(newValue);
|
||||||
ReturnYouTubeDislike.clearCache();
|
ReturnYouTubeDislike.clearCache();
|
||||||
@ -86,6 +74,8 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
|
|||||||
compactLayoutPreference = new SwitchPreference(context);
|
compactLayoutPreference = new SwitchPreference(context);
|
||||||
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.setSummaryOn(str("revanced_ryd_compact_layout_summary_on"));
|
||||||
|
compactLayoutPreference.setSummaryOff(str("revanced_ryd_compact_layout_summary_off"));
|
||||||
compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
compactLayoutPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
SettingsEnum.RYD_USE_COMPACT_LAYOUT.saveValue(newValue);
|
SettingsEnum.RYD_USE_COMPACT_LAYOUT.saveValue(newValue);
|
||||||
ReturnYouTubeDislike.clearCache();
|
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) {
|
if (value == 0) {
|
||||||
return str(summaryStringZeroKey);
|
return str(summaryStringZeroKey);
|
||||||
}
|
}
|
||||||
|
@ -1,66 +1,64 @@
|
|||||||
package app.revanced.integrations.videoplayer;
|
package app.revanced.integrations.videoplayer;
|
||||||
|
|
||||||
import android.support.constraint.ConstraintLayout;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import java.lang.ref.WeakReference;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
|
||||||
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.lang.ref.WeakReference;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class BottomControlButton {
|
public abstract class BottomControlButton {
|
||||||
WeakReference<ImageView> button = new WeakReference<>(null);
|
private static final Animation fadeIn = ReVancedUtils.getResourceAnimation("fade_in");
|
||||||
ConstraintLayout constraintLayout;
|
private static final Animation fadeOut = ReVancedUtils.getResourceAnimation("fade_out");
|
||||||
Boolean isButtonEnabled;
|
private final WeakReference<ImageView> buttonRef;
|
||||||
Boolean isShowing;
|
private final SettingsEnum setting;
|
||||||
|
protected boolean isVisible;
|
||||||
|
|
||||||
private Animation fadeIn;
|
static {
|
||||||
private Animation fadeOut;
|
// TODO: check if these durations are correct.
|
||||||
|
fadeIn.setDuration(ReVancedUtils.getResourceInteger("fade_duration_fast"));
|
||||||
public BottomControlButton(Object obj, String viewId, Boolean isEnabled, View.OnClickListener onClickListener) {
|
fadeOut.setDuration(ReVancedUtils.getResourceInteger("fade_duration_scheduled"));
|
||||||
try {
|
|
||||||
LogHelper.printDebug(() -> "Initializing button with id: " + viewId);
|
|
||||||
constraintLayout = (ConstraintLayout) obj;
|
|
||||||
isButtonEnabled = isEnabled;
|
|
||||||
|
|
||||||
ImageView imageView = constraintLayout.findViewById(ReVancedUtils.getResourceIdentifier(viewId, "id"));
|
|
||||||
if (imageView == null) {
|
|
||||||
LogHelper.printException(() -> "Couldn't find ImageView with id: " + viewId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
imageView.setOnClickListener(onClickListener);
|
|
||||||
button = new WeakReference<>(imageView);
|
|
||||||
|
|
||||||
fadeIn = ReVancedUtils.getResourceAnimation("fade_in");
|
|
||||||
fadeOut = ReVancedUtils.getResourceAnimation("fade_out");
|
|
||||||
fadeIn.setDuration(ReVancedUtils.getResourceInteger("fade_duration_fast"));
|
|
||||||
fadeOut.setDuration(ReVancedUtils.getResourceInteger("fade_duration_scheduled"));
|
|
||||||
|
|
||||||
isShowing = true;
|
|
||||||
setVisibility(false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogHelper.printException(() -> "Failed to initialize button with id: " + viewId, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVisibility(boolean showing) {
|
public BottomControlButton(@NonNull ViewGroup bottomControlsViewGroup, @NonNull String imageViewButtonId,
|
||||||
if (isShowing == showing) return;
|
@NonNull SettingsEnum booleanSetting, @NonNull View.OnClickListener onClickListener) {
|
||||||
|
LogHelper.printDebug(() -> "Initializing button: " + imageViewButtonId);
|
||||||
|
|
||||||
isShowing = showing;
|
if (booleanSetting.returnType != SettingsEnum.ReturnType.BOOLEAN) {
|
||||||
ImageView imageView = button.get();
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
if (constraintLayout == null || imageView == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (showing && isButtonEnabled) {
|
|
||||||
LogHelper.printDebug(() -> "Fading in");
|
|
||||||
imageView.setVisibility(View.VISIBLE);
|
|
||||||
imageView.startAnimation(fadeIn);
|
|
||||||
}
|
}
|
||||||
else if (imageView.getVisibility() == View.VISIBLE) {
|
|
||||||
LogHelper.printDebug(() -> "Fading out");
|
setting = booleanSetting;
|
||||||
|
|
||||||
|
// Create the button.
|
||||||
|
ImageView imageView = Objects.requireNonNull(bottomControlsViewGroup.findViewById(
|
||||||
|
ReVancedUtils.getResourceIdentifier(imageViewButtonId, "id")
|
||||||
|
));
|
||||||
|
imageView.setOnClickListener(onClickListener);
|
||||||
|
imageView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
buttonRef = new WeakReference<>(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibility(boolean visible) {
|
||||||
|
if (isVisible == visible) return;
|
||||||
|
isVisible = visible;
|
||||||
|
|
||||||
|
ImageView imageView = buttonRef.get();
|
||||||
|
if (imageView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageView.clearAnimation();
|
||||||
|
if (visible && setting.getBoolean()) {
|
||||||
|
imageView.startAnimation(fadeIn);
|
||||||
|
imageView.setVisibility(View.VISIBLE);
|
||||||
|
} else if (imageView.getVisibility() == View.VISIBLE) {
|
||||||
imageView.startAnimation(fadeOut);
|
imageView.startAnimation(fadeOut);
|
||||||
imageView.setVisibility(View.GONE);
|
imageView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,40 @@
|
|||||||
package app.revanced.integrations.videoplayer;
|
package app.revanced.integrations.videoplayer;
|
||||||
|
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import app.revanced.integrations.patches.CopyVideoUrlPatch;
|
import app.revanced.integrations.patches.CopyVideoUrlPatch;
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
|
||||||
public class CopyVideoUrlButton extends BottomControlButton {
|
public class CopyVideoUrlButton extends BottomControlButton {
|
||||||
public static CopyVideoUrlButton instance;
|
@Nullable
|
||||||
|
private static CopyVideoUrlButton instance;
|
||||||
|
|
||||||
public CopyVideoUrlButton(Object obj) {
|
public CopyVideoUrlButton(ViewGroup viewGroup) {
|
||||||
super(
|
super(
|
||||||
obj,
|
viewGroup,
|
||||||
"copy_video_url_button",
|
"copy_video_url_button",
|
||||||
SettingsEnum.COPY_VIDEO_URL_BUTTON_SHOWN.getBoolean(),
|
SettingsEnum.COPY_VIDEO_URL_BUTTON_SHOWN,
|
||||||
view -> CopyVideoUrlPatch.copyUrl(false)
|
view -> CopyVideoUrlPatch.copyUrl(false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
public static void initializeButton(Object obj) {
|
public static void initializeButton(Object obj) {
|
||||||
instance = new CopyVideoUrlButton(obj);
|
try {
|
||||||
|
instance = new CopyVideoUrlButton((ViewGroup) obj);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.printException(() -> "initializeButton failure", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibility(boolean showing) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibility(showing);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,40 @@
|
|||||||
package app.revanced.integrations.videoplayer;
|
package app.revanced.integrations.videoplayer;
|
||||||
|
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import app.revanced.integrations.patches.CopyVideoUrlPatch;
|
import app.revanced.integrations.patches.CopyVideoUrlPatch;
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
|
||||||
public class CopyVideoUrlTimestampButton extends BottomControlButton {
|
public class CopyVideoUrlTimestampButton extends BottomControlButton {
|
||||||
public static CopyVideoUrlTimestampButton instance;
|
@Nullable
|
||||||
|
private static CopyVideoUrlTimestampButton instance;
|
||||||
|
|
||||||
public CopyVideoUrlTimestampButton(Object obj) {
|
public CopyVideoUrlTimestampButton(ViewGroup bottomControlsViewGroup) {
|
||||||
super(
|
super(
|
||||||
obj,
|
bottomControlsViewGroup,
|
||||||
"copy_video_url_timestamp_button",
|
"copy_video_url_timestamp_button",
|
||||||
SettingsEnum.COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN.getBoolean(),
|
SettingsEnum.COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN,
|
||||||
view -> CopyVideoUrlPatch.copyUrl(true)
|
view -> CopyVideoUrlPatch.copyUrl(true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initializeButton(Object obj) {
|
/**
|
||||||
instance = new CopyVideoUrlTimestampButton(obj);
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static void initializeButton(Object bottomControlsViewGroup) {
|
||||||
|
try {
|
||||||
|
instance = new CopyVideoUrlTimestampButton((ViewGroup) bottomControlsViewGroup);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.printException(() -> "initializeButton failure", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibility(boolean showing) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibility(showing);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@ package app.revanced.integrations.videoplayer;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import app.revanced.integrations.patches.VideoInformation;
|
import app.revanced.integrations.patches.VideoInformation;
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
@ -11,21 +14,32 @@ import app.revanced.integrations.utils.ReVancedUtils;
|
|||||||
import app.revanced.integrations.utils.StringRef;
|
import app.revanced.integrations.utils.StringRef;
|
||||||
|
|
||||||
public class DownloadButton extends BottomControlButton {
|
public class DownloadButton extends BottomControlButton {
|
||||||
public static DownloadButton instance;
|
@Nullable
|
||||||
|
private static DownloadButton instance;
|
||||||
|
|
||||||
public DownloadButton(Object obj) {
|
public DownloadButton(ViewGroup viewGroup) {
|
||||||
super(
|
super(
|
||||||
obj,
|
viewGroup,
|
||||||
"download_button",
|
"download_button",
|
||||||
SettingsEnum.DOWNLOADS_BUTTON_SHOWN.getBoolean(),
|
SettingsEnum.DOWNLOADS_BUTTON_SHOWN,
|
||||||
DownloadButton::onDownloadClick
|
DownloadButton::onDownloadClick
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
public static void initializeButton(Object obj) {
|
public static void initializeButton(Object obj) {
|
||||||
instance = new DownloadButton(obj);
|
try {
|
||||||
|
instance = new DownloadButton((ViewGroup) obj);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.printException(() -> "initializeButton failure", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibility(boolean showing) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibility(showing);
|
||||||
}
|
}
|
||||||
@ -38,7 +52,6 @@ public class DownloadButton extends BottomControlButton {
|
|||||||
|
|
||||||
boolean packageEnabled = false;
|
boolean packageEnabled = false;
|
||||||
try {
|
try {
|
||||||
assert context != null;
|
|
||||||
packageEnabled = context.getPackageManager().getApplicationInfo(downloaderPackageName, 0).enabled;
|
packageEnabled = context.getPackageManager().getApplicationInfo(downloaderPackageName, 0).enabled;
|
||||||
} catch (PackageManager.NameNotFoundException error) {
|
} catch (PackageManager.NameNotFoundException error) {
|
||||||
LogHelper.printDebug(() -> "Downloader could not be found: " + error);
|
LogHelper.printDebug(() -> "Downloader could not be found: " + error);
|
||||||
|
@ -5,7 +5,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:7.3.1")
|
classpath("com.android.tools.build:gradle:8.0.0")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
org.gradle.jvmargs = -Xmx2048m
|
org.gradle.jvmargs = -Xmx2048m
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
version = 0.105.0
|
version = 0.106.0-dev.7
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
Loading…
Reference in New Issue
Block a user