mirror of
https://github.com/revanced/revanced-integrations.git
synced 2025-02-11 11:36:47 +01:00
chore: Merge branch dev
to main
(#658)
This commit is contained in:
commit
1aba976b28
29
CHANGELOG.md
29
CHANGELOG.md
@ -1,3 +1,32 @@
|
|||||||
|
## [1.11.1-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.3...v1.11.1-dev.4) (2024-07-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - SponsorBlock:** Skip segments when casting ([#655](https://github.com/ReVanced/revanced-integrations/issues/655)) ([5ce16ee](https://github.com/ReVanced/revanced-integrations/commit/5ce16eedc6e27560b97ab982408ac697146105e9))
|
||||||
|
|
||||||
|
## [1.11.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.2...v1.11.1-dev.3) (2024-07-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Hide ads:** Hide new types of home feed button ads ([#662](https://github.com/ReVanced/revanced-integrations/issues/662)) ([ff2637c](https://github.com/ReVanced/revanced-integrations/commit/ff2637cb4c9c396f626cd7ee912953b22525baef))
|
||||||
|
* **YouTube - Settings:** Move some settings to different menus, adjust default setting values ([#661](https://github.com/ReVanced/revanced-integrations/issues/661)) ([77533cf](https://github.com/ReVanced/revanced-integrations/commit/77533cf3d68b9c748e1d4f3a85cd0544afc7ce48))
|
||||||
|
|
||||||
|
## [1.11.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1-dev.1...v1.11.1-dev.2) (2024-06-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Hide layout components:** Hide new kind of community post ([#659](https://github.com/ReVanced/revanced-integrations/issues/659)) ([c237e3c](https://github.com/ReVanced/revanced-integrations/commit/c237e3c02c971fb1801663cb662096d319c04928))
|
||||||
|
|
||||||
|
## [1.11.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.0...v1.11.1-dev.1) (2024-06-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Hide layout components:** Detect if a keyword filter hides all videos ([#657](https://github.com/ReVanced/revanced-integrations/issues/657)) ([3a3ceec](https://github.com/ReVanced/revanced-integrations/commit/3a3ceec4b596354dcccbf3516ef1634bd8819b90))
|
||||||
|
|
||||||
# [1.11.0](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0...v1.11.0) (2024-06-23)
|
# [1.11.0](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0...v1.11.0) (2024-06-23)
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ public class Utils {
|
|||||||
*
|
*
|
||||||
* @return The manifest 'Version' entry of the patches.jar used during patching.
|
* @return The manifest 'Version' entry of the patches.jar used during patching.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("SameReturnValue")
|
||||||
public static String getPatchesReleaseVersion() {
|
public static String getPatchesReleaseVersion() {
|
||||||
return ""; // Value is replaced during patching.
|
return ""; // Value is replaced during patching.
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ public class ThemeHelper {
|
|||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("SameReturnValue")
|
||||||
private static String darkThemeResourceName() {
|
private static String darkThemeResourceName() {
|
||||||
// Value is changed by Theme patch, if included.
|
// Value is changed by Theme patch, if included.
|
||||||
return "@color/yt_black3";
|
return "@color/yt_black3";
|
||||||
@ -58,6 +59,7 @@ public class ThemeHelper {
|
|||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("SameReturnValue")
|
||||||
private static String lightThemeResourceName() {
|
private static String lightThemeResourceName() {
|
||||||
// Value is changed by Theme patch, if included.
|
// Value is changed by Theme patch, if included.
|
||||||
return "@color/yt_white1";
|
return "@color/yt_white1";
|
||||||
|
@ -380,7 +380,7 @@ public abstract class TrieSearch<T> {
|
|||||||
throw new IllegalArgumentException("endIndex: " + endIndex
|
throw new IllegalArgumentException("endIndex: " + endIndex
|
||||||
+ " is greater than texToSearchLength: " + textToSearchLength);
|
+ " is greater than texToSearchLength: " + textToSearchLength);
|
||||||
}
|
}
|
||||||
if (patterns.size() == 0) {
|
if (patterns.isEmpty()) {
|
||||||
return false; // No patterns were added.
|
return false; // No patterns were added.
|
||||||
}
|
}
|
||||||
for (int i = startIndex; i < endIndex; i++) {
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
@ -393,7 +393,7 @@ public abstract class TrieSearch<T> {
|
|||||||
* @return Estimated memory size (in kilobytes) of this instance.
|
* @return Estimated memory size (in kilobytes) of this instance.
|
||||||
*/
|
*/
|
||||||
public int getEstimatedMemorySize() {
|
public int getEstimatedMemorySize() {
|
||||||
if (patterns.size() == 0) {
|
if (patterns.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Assume the device has less than 32GB of ram (and can use pointer compression),
|
// Assume the device has less than 32GB of ram (and can use pointer compression),
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
package app.revanced.integrations.youtube.patches;
|
package app.revanced.integrations.youtube.patches;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.ViewTreeObserver;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import app.revanced.integrations.shared.Logger;
|
|
||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
|
|
||||||
/** @noinspection unused*/
|
/** @noinspection unused*/
|
||||||
|
@ -2,8 +2,6 @@ package app.revanced.integrations.youtube.patches;
|
|||||||
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import app.revanced.integrations.youtube.shared.PlayerOverlays;
|
import app.revanced.integrations.youtube.shared.PlayerOverlays;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@ -23,7 +23,9 @@ public final class VideoInformation {
|
|||||||
private static final String SHORTS_PLAYER_PARAMETERS = "8AEB";
|
private static final String SHORTS_PLAYER_PARAMETERS = "8AEB";
|
||||||
|
|
||||||
private static WeakReference<Object> playerControllerRef;
|
private static WeakReference<Object> playerControllerRef;
|
||||||
|
private static WeakReference<Object> mdxPlayerDirectorRef;
|
||||||
private static Method seekMethod;
|
private static Method seekMethod;
|
||||||
|
private static Method mdxSeekMethod;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static String videoId = "";
|
private static String videoId = "";
|
||||||
@ -59,6 +61,22 @@ public final class VideoInformation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*
|
||||||
|
* @param mdxPlayerDirector MDX player director object (casting mode).
|
||||||
|
*/
|
||||||
|
public static void initializeMdx(@NonNull Object mdxPlayerDirector) {
|
||||||
|
try {
|
||||||
|
mdxPlayerDirectorRef = new WeakReference<>(Objects.requireNonNull(mdxPlayerDirector));
|
||||||
|
|
||||||
|
mdxSeekMethod = mdxPlayerDirector.getClass().getMethod(SEEK_METHOD_NAME, Long.TYPE);
|
||||||
|
mdxSeekMethod.setAccessible(true);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "Failed to initialize MDX", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*
|
*
|
||||||
@ -178,8 +196,32 @@ public final class VideoInformation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Logger.printDebug(() -> "Seeking to " + adjustedSeekTime);
|
Logger.printDebug(() -> "Seeking to " + adjustedSeekTime);
|
||||||
//noinspection DataFlowIssue
|
|
||||||
return (Boolean) seekMethod.invoke(playerControllerRef.get(), adjustedSeekTime);
|
try {
|
||||||
|
//noinspection DataFlowIssue
|
||||||
|
if ((Boolean) seekMethod.invoke(playerControllerRef.get(), adjustedSeekTime)) {
|
||||||
|
return true;
|
||||||
|
} // Else the video is loading or changing videos, or video is casting to a different device.
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printInfo(() -> "seekTo method call failed", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try calling the seekTo method of the MDX player director (called when casting).
|
||||||
|
// The difference has to be a different second mark in order to avoid infinite skip loops
|
||||||
|
// as the Lounge API only supports seconds.
|
||||||
|
if ((adjustedSeekTime / 1000) == (videoTime / 1000)) {
|
||||||
|
Logger.printDebug(() -> "Skipping seekTo for MDX because seek time is too small ("
|
||||||
|
+ (adjustedSeekTime - videoTime) + "ms)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
//noinspection DataFlowIssue
|
||||||
|
return (Boolean) mdxSeekMethod.invoke(mdxPlayerDirectorRef.get(), adjustedSeekTime);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printInfo(() -> "seekTo (MDX) method call failed", ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "Failed to seek", ex);
|
Logger.printException(() -> "Failed to seek", ex);
|
||||||
return false;
|
return false;
|
||||||
@ -278,6 +320,7 @@ public final class VideoInformation {
|
|||||||
*
|
*
|
||||||
* @see VideoState
|
* @see VideoState
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
public static boolean isAtEndOfVideo() {
|
public static boolean isAtEndOfVideo() {
|
||||||
return videoTime >= videoLength && videoLength > 0;
|
return videoTime >= videoLength && videoLength > 0;
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,11 @@ public final class AdsFilter extends Filter {
|
|||||||
|
|
||||||
final var buttonedAd = new StringFilterGroup(
|
final var buttonedAd = new StringFilterGroup(
|
||||||
Settings.HIDE_BUTTONED_ADS,
|
Settings.HIDE_BUTTONED_ADS,
|
||||||
"_buttoned_layout",
|
|
||||||
"full_width_square_image_layout",
|
|
||||||
"_ad_with",
|
"_ad_with",
|
||||||
"text_image_button_group_layout",
|
"_buttoned_layout",
|
||||||
|
// text_image_button_group_layout, landscape_image_button_group_layout, full_width_square_image_button_group_layout
|
||||||
|
"image_button_group_layout",
|
||||||
|
"full_width_square_image_layout",
|
||||||
"video_display_button_group_layout",
|
"video_display_button_group_layout",
|
||||||
"landscape_image_wide_button_layout",
|
"landscape_image_wide_button_layout",
|
||||||
"video_display_carousel_button_group_layout"
|
"video_display_carousel_button_group_layout"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package app.revanced.integrations.youtube.patches.components;
|
package app.revanced.integrations.youtube.patches.components;
|
||||||
|
|
||||||
import static app.revanced.integrations.shared.StringRef.str;
|
import static app.revanced.integrations.shared.StringRef.str;
|
||||||
import static app.revanced.integrations.youtube.ByteTrieSearch.convertStringsToBytes;
|
|
||||||
import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton;
|
import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -10,13 +9,16 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
import app.revanced.integrations.shared.Utils;
|
import app.revanced.integrations.shared.Utils;
|
||||||
import app.revanced.integrations.youtube.ByteTrieSearch;
|
import app.revanced.integrations.youtube.ByteTrieSearch;
|
||||||
|
import app.revanced.integrations.youtube.TrieSearch;
|
||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
import app.revanced.integrations.youtube.shared.NavigationBar;
|
import app.revanced.integrations.youtube.shared.NavigationBar;
|
||||||
import app.revanced.integrations.youtube.shared.PlayerType;
|
import app.revanced.integrations.youtube.shared.PlayerType;
|
||||||
@ -65,13 +67,18 @@ final class KeywordContentFilter extends Filter {
|
|||||||
// Video decoders.
|
// Video decoders.
|
||||||
"OMX.ffmpeg.vp9.decoder",
|
"OMX.ffmpeg.vp9.decoder",
|
||||||
"OMX.Intel.sw_vd.vp9",
|
"OMX.Intel.sw_vd.vp9",
|
||||||
"OMX.sprd.av1.decoder",
|
|
||||||
"OMX.MTK.VIDEO.DECODER.SW.VP9",
|
"OMX.MTK.VIDEO.DECODER.SW.VP9",
|
||||||
|
"OMX.google.vp9.decoder",
|
||||||
|
"OMX.google.av1.decoder",
|
||||||
|
"OMX.sprd.av1.decoder",
|
||||||
"c2.android.av1.decoder",
|
"c2.android.av1.decoder",
|
||||||
|
"c2.android.av1-dav1d.decoder",
|
||||||
|
"c2.android.vp9.decoder",
|
||||||
"c2.mtk.sw.vp9.decoder",
|
"c2.mtk.sw.vp9.decoder",
|
||||||
// User analytics.
|
// User analytics.
|
||||||
"https://ad.doubleclick.net/ddm/activity/",
|
"https://ad.doubleclick.net/ddm/activity/",
|
||||||
"DEVICE_ADVERTISER_ID_FOR_CONVERSION_TRACKING",
|
"DEVICE_ADVERTISER_ID_FOR_CONVERSION_TRACKING",
|
||||||
|
"tag_for_child_directed_treatment", // Found in overflow menu such as 'Watch later'.
|
||||||
// Litho components frequently found in the buffer that belong to the path filter items.
|
// Litho components frequently found in the buffer that belong to the path filter items.
|
||||||
"metadata.eml",
|
"metadata.eml",
|
||||||
"thumbnail.eml",
|
"thumbnail.eml",
|
||||||
@ -97,6 +104,7 @@ final class KeywordContentFilter extends Filter {
|
|||||||
/**
|
/**
|
||||||
* Substrings that are never at the start of the path.
|
* Substrings that are never at the start of the path.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private final StringFilterGroup containsFilter = new StringFilterGroup(
|
private final StringFilterGroup containsFilter = new StringFilterGroup(
|
||||||
null,
|
null,
|
||||||
"modern_type_shelf_header_content.eml",
|
"modern_type_shelf_header_content.eml",
|
||||||
@ -104,6 +112,38 @@ final class KeywordContentFilter extends Filter {
|
|||||||
"video_card.eml" // Shorts that appear in a horizontal shelf.
|
"video_card.eml" // Shorts that appear in a horizontal shelf.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Threshold for {@link #filteredVideosPercentage}
|
||||||
|
* that indicates all or nearly all videos have been filtered.
|
||||||
|
* This should be close to 100% to reduce false positives.
|
||||||
|
*/
|
||||||
|
private static final float ALL_VIDEOS_FILTERED_THRESHOLD = 0.95f;
|
||||||
|
|
||||||
|
private static final float ALL_VIDEOS_FILTERED_SAMPLE_SIZE = 50;
|
||||||
|
|
||||||
|
private static final long ALL_VIDEOS_FILTERED_TIMEOUT_MILLISECONDS = 60 * 1000; // 60 seconds
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rolling average of how many videos were filtered by a keyword.
|
||||||
|
* Used to detect if a keyword passes the initial check against {@link #STRINGS_IN_EVERY_BUFFER}
|
||||||
|
* but a keyword is still hiding all videos.
|
||||||
|
*
|
||||||
|
* This check can still fail if some extra UI elements pass the keywords,
|
||||||
|
* such as the video chapter preview or any other elements.
|
||||||
|
*
|
||||||
|
* To test this, add a filter that appears in all videos (such as 'ovd='),
|
||||||
|
* and open the subscription feed. In practice this does not always identify problems
|
||||||
|
* in the home feed and search, because the home feed has a finite amount of content and
|
||||||
|
* search results have a lot of extra video junk that is not hidden and interferes with the detection.
|
||||||
|
*/
|
||||||
|
private volatile float filteredVideosPercentage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If filtering is temporarily turned off, the time to resume filtering.
|
||||||
|
* Field is zero if no timeout is in effect.
|
||||||
|
*/
|
||||||
|
private volatile long timeToResumeFiltering;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last value of {@link Settings#HIDE_KEYWORD_CONTENT_PHRASES}
|
* The last value of {@link Settings#HIDE_KEYWORD_CONTENT_PHRASES}
|
||||||
* parsed and loaded into {@link #bufferSearch}.
|
* parsed and loaded into {@link #bufferSearch}.
|
||||||
@ -113,39 +153,6 @@ final class KeywordContentFilter extends Filter {
|
|||||||
|
|
||||||
private volatile ByteTrieSearch bufferSearch;
|
private volatile ByteTrieSearch bufferSearch;
|
||||||
|
|
||||||
private static boolean hideKeywordSettingIsActive() {
|
|
||||||
// Must check player type first, as search bar can be active behind the player.
|
|
||||||
if (PlayerType.getCurrent().isMaximizedOrFullscreen()) {
|
|
||||||
// For now, consider the under video results the same as the home feed.
|
|
||||||
return Settings.HIDE_KEYWORD_CONTENT_HOME.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must check second, as search can be from any tab.
|
|
||||||
if (NavigationBar.isSearchBarActive()) {
|
|
||||||
return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid checking navigation button status if all other settings are off.
|
|
||||||
final boolean hideHome = Settings.HIDE_KEYWORD_CONTENT_HOME.get();
|
|
||||||
final boolean hideSubscriptions = Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS.get();
|
|
||||||
if (!hideHome && !hideSubscriptions) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton();
|
|
||||||
if (selectedNavButton == null) {
|
|
||||||
return hideHome; // Unknown tab, treat the same as home.
|
|
||||||
}
|
|
||||||
if (selectedNavButton == NavigationButton.HOME) {
|
|
||||||
return hideHome;
|
|
||||||
}
|
|
||||||
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) {
|
|
||||||
return hideSubscriptions;
|
|
||||||
}
|
|
||||||
// User is in the Library or Notifications tab.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change first letter of the first word to use title case.
|
* Change first letter of the first word to use title case.
|
||||||
*/
|
*/
|
||||||
@ -247,11 +254,26 @@ final class KeywordContentFilter extends Filter {
|
|||||||
keywords.addAll(Arrays.asList(phraseVariations));
|
keywords.addAll(Arrays.asList(phraseVariations));
|
||||||
}
|
}
|
||||||
|
|
||||||
search.addPatterns(convertStringsToBytes(keywords.toArray(new String[0])));
|
for (String keyword : keywords) {
|
||||||
|
// Use a callback to get the keyword that matched.
|
||||||
|
// TrieSearch could have this built in, but that's slightly more complicated since
|
||||||
|
// the strings are stored as a byte array and embedded in the search tree.
|
||||||
|
TrieSearch.TriePatternMatchedCallback<byte[]> callback =
|
||||||
|
(textSearched, matchedStartIndex, matchedLength, callbackParameter) -> {
|
||||||
|
// noinspection unchecked
|
||||||
|
((MutableReference<String>) callbackParameter).value = keyword;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
byte[] stringBytes = keyword.getBytes(StandardCharsets.UTF_8);
|
||||||
|
search.addPattern(stringBytes, callback);
|
||||||
|
}
|
||||||
|
|
||||||
Logger.printDebug(() -> "Search using: (" + search.getEstimatedMemorySize() + " KB) keywords: " + keywords);
|
Logger.printDebug(() -> "Search using: (" + search.getEstimatedMemorySize() + " KB) keywords: " + keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferSearch = search;
|
bufferSearch = search;
|
||||||
|
timeToResumeFiltering = 0;
|
||||||
|
filteredVideosPercentage = 0;
|
||||||
lastKeywordPhrasesParsed = rawKeywords; // Must set last.
|
lastKeywordPhrasesParsed = rawKeywords; // Must set last.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +282,69 @@ final class KeywordContentFilter extends Filter {
|
|||||||
addPathCallbacks(startsWithFilter, containsFilter);
|
addPathCallbacks(startsWithFilter, containsFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hideKeywordSettingIsActive() {
|
||||||
|
if (timeToResumeFiltering != 0) {
|
||||||
|
if (System.currentTimeMillis() < timeToResumeFiltering) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeToResumeFiltering = 0;
|
||||||
|
filteredVideosPercentage = 0;
|
||||||
|
Logger.printDebug(() -> "Resuming keyword filtering");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must check player type first, as search bar can be active behind the player.
|
||||||
|
if (PlayerType.getCurrent().isMaximizedOrFullscreen()) {
|
||||||
|
// For now, consider the under video results the same as the home feed.
|
||||||
|
return Settings.HIDE_KEYWORD_CONTENT_HOME.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must check second, as search can be from any tab.
|
||||||
|
if (NavigationBar.isSearchBarActive()) {
|
||||||
|
return Settings.HIDE_KEYWORD_CONTENT_SEARCH.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid checking navigation button status if all other settings are off.
|
||||||
|
final boolean hideHome = Settings.HIDE_KEYWORD_CONTENT_HOME.get();
|
||||||
|
final boolean hideSubscriptions = Settings.HIDE_KEYWORD_CONTENT_SUBSCRIPTIONS.get();
|
||||||
|
if (!hideHome && !hideSubscriptions) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationButton selectedNavButton = NavigationButton.getSelectedNavigationButton();
|
||||||
|
if (selectedNavButton == null) {
|
||||||
|
return hideHome; // Unknown tab, treat the same as home.
|
||||||
|
}
|
||||||
|
if (selectedNavButton == NavigationButton.HOME) {
|
||||||
|
return hideHome;
|
||||||
|
}
|
||||||
|
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) {
|
||||||
|
return hideSubscriptions;
|
||||||
|
}
|
||||||
|
// User is in the Library or Notifications tab.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStats(boolean videoWasHidden, @Nullable String keyword) {
|
||||||
|
float updatedAverage = filteredVideosPercentage
|
||||||
|
* ((ALL_VIDEOS_FILTERED_SAMPLE_SIZE - 1) / ALL_VIDEOS_FILTERED_SAMPLE_SIZE);
|
||||||
|
if (videoWasHidden) {
|
||||||
|
updatedAverage += 1 / ALL_VIDEOS_FILTERED_SAMPLE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedAverage <= ALL_VIDEOS_FILTERED_THRESHOLD) {
|
||||||
|
filteredVideosPercentage = updatedAverage;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A keyword is hiding everything.
|
||||||
|
// Inform the user, and temporarily turn off filtering.
|
||||||
|
timeToResumeFiltering = System.currentTimeMillis() + ALL_VIDEOS_FILTERED_TIMEOUT_MILLISECONDS;
|
||||||
|
|
||||||
|
Logger.printDebug(() -> "Temporarily turning off filtering due to excessively broad filter: " + keyword);
|
||||||
|
Utils.showToastLong(str("revanced_hide_keyword_toast_invalid_broad", keyword));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||||
@ -267,8 +352,6 @@ final class KeywordContentFilter extends Filter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hideKeywordSettingIsActive()) return false;
|
|
||||||
|
|
||||||
// Field is intentionally compared using reference equality.
|
// Field is intentionally compared using reference equality.
|
||||||
//noinspection StringEquality
|
//noinspection StringEquality
|
||||||
if (Settings.HIDE_KEYWORD_CONTENT_PHRASES.get() != lastKeywordPhrasesParsed) {
|
if (Settings.HIDE_KEYWORD_CONTENT_PHRASES.get() != lastKeywordPhrasesParsed) {
|
||||||
@ -276,11 +359,22 @@ final class KeywordContentFilter extends Filter {
|
|||||||
parseKeywords();
|
parseKeywords();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bufferSearch.matches(protobufBufferArray)) {
|
if (!hideKeywordSettingIsActive()) return false;
|
||||||
return false;
|
|
||||||
|
MutableReference<String> matchRef = new MutableReference<>();
|
||||||
|
if (bufferSearch.matches(protobufBufferArray, matchRef)) {
|
||||||
|
updateStats(true, matchRef.value);
|
||||||
|
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
updateStats(false, null);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple non-atomic wrapper since {@link AtomicReference#setPlain(Object)} is not available with Android 8.0.
|
||||||
|
*/
|
||||||
|
final class MutableReference<T> {
|
||||||
|
T value;
|
||||||
}
|
}
|
@ -80,7 +80,8 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
final var communityPosts = new StringFilterGroup(
|
final var communityPosts = new StringFilterGroup(
|
||||||
Settings.HIDE_COMMUNITY_POSTS,
|
Settings.HIDE_COMMUNITY_POSTS,
|
||||||
"post_base_wrapper",
|
"post_base_wrapper",
|
||||||
"image_post_root.eml"
|
"image_post_root.eml",
|
||||||
|
"text_post_root.eml"
|
||||||
);
|
);
|
||||||
|
|
||||||
final var communityGuidelines = new StringFilterGroup(
|
final var communityGuidelines = new StringFilterGroup(
|
||||||
@ -163,11 +164,6 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
"inline_expander"
|
"inline_expander"
|
||||||
);
|
);
|
||||||
|
|
||||||
final var videoQualityMenuFooter = new StringFilterGroup(
|
|
||||||
Settings.HIDE_VIDEO_QUALITY_MENU_FOOTER,
|
|
||||||
"quality_sheet_footer"
|
|
||||||
);
|
|
||||||
|
|
||||||
final var channelBar = new StringFilterGroup(
|
final var channelBar = new StringFilterGroup(
|
||||||
Settings.HIDE_CHANNEL_BAR,
|
Settings.HIDE_CHANNEL_BAR,
|
||||||
"channel_bar"
|
"channel_bar"
|
||||||
@ -275,7 +271,6 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
compactBanner,
|
compactBanner,
|
||||||
compactChannelBarInner,
|
compactChannelBarInner,
|
||||||
medicalPanel,
|
medicalPanel,
|
||||||
videoQualityMenuFooter,
|
|
||||||
infoPanel,
|
infoPanel,
|
||||||
emergencyBox,
|
emergencyBox,
|
||||||
subscribersCommunityGuidelines,
|
subscribersCommunityGuidelines,
|
||||||
|
@ -96,6 +96,7 @@ abstract class FilterGroup<T> {
|
|||||||
* @return If {@link FilterGroupList} should include this group when searching.
|
* @return If {@link FilterGroupList} should include this group when searching.
|
||||||
* By default, all filters are included except non enabled settings that require reboot.
|
* By default, all filters are included except non enabled settings that require reboot.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
public boolean includeInSearch() {
|
public boolean includeInSearch() {
|
||||||
return isEnabled() || !setting.rebootApp;
|
return isEnabled() || !setting.rebootApp;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
|
|||||||
private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList();
|
private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList();
|
||||||
|
|
||||||
private final ByteArrayFilterGroup exception;
|
private final ByteArrayFilterGroup exception;
|
||||||
|
private final StringFilterGroup videoQualityMenuFooter;
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
public PlayerFlyoutMenuItemsFilter() {
|
public PlayerFlyoutMenuItemsFilter() {
|
||||||
@ -23,8 +24,13 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
|
|||||||
"quality_sheet"
|
"quality_sheet"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Using pathFilterGroupList due to new flyout panel(A/B)
|
videoQualityMenuFooter = new StringFilterGroup(
|
||||||
|
Settings.HIDE_VIDEO_QUALITY_MENU_FOOTER,
|
||||||
|
"quality_sheet_footer"
|
||||||
|
);
|
||||||
|
|
||||||
addPathCallbacks(
|
addPathCallbacks(
|
||||||
|
videoQualityMenuFooter,
|
||||||
new StringFilterGroup(null, "overflow_menu_item.eml|")
|
new StringFilterGroup(null, "overflow_menu_item.eml|")
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -75,7 +81,10 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
|
|||||||
@Override
|
@Override
|
||||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||||
// Only 1 path callback was added, so the matched group must be the overflow menu.
|
if (matchedGroup == videoQualityMenuFooter) {
|
||||||
|
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
if (contentIndex != 0) {
|
if (contentIndex != 0) {
|
||||||
return false; // Overflow menu is always the start of the path.
|
return false; // Overflow menu is always the start of the path.
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,10 @@ import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings;
|
|||||||
public class Settings extends BaseSettings {
|
public class Settings extends BaseSettings {
|
||||||
// Video
|
// Video
|
||||||
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||||
public static final BooleanSetting HIDE_VIDEO_QUALITY_MENU_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", TRUE);
|
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", TRUE);
|
|
||||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
|
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
|
||||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
|
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
|
||||||
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", TRUE);
|
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE);
|
||||||
public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", 1.0f);
|
public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", 1.0f);
|
||||||
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
|
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
|
||||||
"0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true);
|
"0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true);
|
||||||
@ -55,6 +54,7 @@ public class Settings extends BaseSettings {
|
|||||||
// Feed
|
// Feed
|
||||||
public static final BooleanSetting HIDE_ALBUM_CARDS = new BooleanSetting("revanced_hide_album_cards", FALSE, true);
|
public static final BooleanSetting HIDE_ALBUM_CARDS = new BooleanSetting("revanced_hide_album_cards", FALSE, true);
|
||||||
public static final BooleanSetting HIDE_ARTIST_CARDS = new BooleanSetting("revanced_hide_artist_cards", FALSE);
|
public static final BooleanSetting HIDE_ARTIST_CARDS = new BooleanSetting("revanced_hide_artist_cards", FALSE);
|
||||||
|
public static final BooleanSetting HIDE_EXPANDABLE_CHIP = new BooleanSetting("revanced_hide_expandable_chip", TRUE);
|
||||||
|
|
||||||
// Alternative thumbnails
|
// Alternative thumbnails
|
||||||
public static final EnumSetting<ThumbnailOption> ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL);
|
public static final EnumSetting<ThumbnailOption> ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL);
|
||||||
@ -89,8 +89,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true);
|
public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true);
|
||||||
@Deprecated public static final BooleanSetting HIDE_EMAIL_ADDRESS = new BooleanSetting("revanced_hide_email_address", FALSE);
|
@Deprecated public static final BooleanSetting HIDE_EMAIL_ADDRESS = new BooleanSetting("revanced_hide_email_address", FALSE);
|
||||||
public static final BooleanSetting HIDE_EMERGENCY_BOX = new BooleanSetting("revanced_hide_emergency_box", TRUE);
|
public static final BooleanSetting HIDE_EMERGENCY_BOX = new BooleanSetting("revanced_hide_emergency_box", TRUE);
|
||||||
public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", TRUE);
|
public static final BooleanSetting HIDE_ENDSCREEN_CARDS = new BooleanSetting("revanced_hide_endscreen_cards", FALSE);
|
||||||
public static final BooleanSetting HIDE_EXPANDABLE_CHIP = new BooleanSetting("revanced_hide_expandable_chip", TRUE);
|
|
||||||
public static final BooleanSetting HIDE_FEED_SURVEY = new BooleanSetting("revanced_hide_feed_survey", TRUE);
|
public static final BooleanSetting HIDE_FEED_SURVEY = new BooleanSetting("revanced_hide_feed_survey", TRUE);
|
||||||
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true);
|
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true);
|
||||||
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS = new BooleanSetting("revanced_hide_filter_bar_feed_in_related_videos", FALSE, true);
|
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS = new BooleanSetting("revanced_hide_filter_bar_feed_in_related_videos", FALSE, true);
|
||||||
@ -101,7 +100,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_HIDE_CHANNEL_GUIDELINES = new BooleanSetting("revanced_hide_channel_guidelines", TRUE);
|
public static final BooleanSetting HIDE_HIDE_CHANNEL_GUIDELINES = new BooleanSetting("revanced_hide_channel_guidelines", TRUE);
|
||||||
public static final BooleanSetting HIDE_HIDE_INFO_PANELS = new BooleanSetting("revanced_hide_info_panels", TRUE);
|
public static final BooleanSetting HIDE_HIDE_INFO_PANELS = new BooleanSetting("revanced_hide_info_panels", TRUE);
|
||||||
public static final BooleanSetting HIDE_IMAGE_SHELF = new BooleanSetting("revanced_hide_image_shelf", TRUE);
|
public static final BooleanSetting HIDE_IMAGE_SHELF = new BooleanSetting("revanced_hide_image_shelf", TRUE);
|
||||||
public static final BooleanSetting HIDE_INFO_CARDS = new BooleanSetting("revanced_hide_info_cards", TRUE);
|
public static final BooleanSetting HIDE_INFO_CARDS = new BooleanSetting("revanced_hide_info_cards", FALSE);
|
||||||
public static final BooleanSetting HIDE_JOIN_MEMBERSHIP_BUTTON = new BooleanSetting("revanced_hide_join_membership_button", TRUE);
|
public static final BooleanSetting HIDE_JOIN_MEMBERSHIP_BUTTON = new BooleanSetting("revanced_hide_join_membership_button", TRUE);
|
||||||
@Deprecated public static final BooleanSetting HIDE_LOAD_MORE_BUTTON = new BooleanSetting("revanced_hide_load_more_button", TRUE);
|
@Deprecated public static final BooleanSetting HIDE_LOAD_MORE_BUTTON = new BooleanSetting("revanced_hide_load_more_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true);
|
public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true);
|
||||||
@ -182,6 +181,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_LOCK_SCREEN_MENU = new BooleanSetting("revanced_hide_player_flyout_lock_screen", FALSE);
|
public static final BooleanSetting HIDE_LOCK_SCREEN_MENU = new BooleanSetting("revanced_hide_player_flyout_lock_screen", FALSE);
|
||||||
public static final BooleanSetting HIDE_AUDIO_TRACK_MENU = new BooleanSetting("revanced_hide_player_flyout_audio_track", FALSE);
|
public static final BooleanSetting HIDE_AUDIO_TRACK_MENU = new BooleanSetting("revanced_hide_player_flyout_audio_track", FALSE);
|
||||||
public static final BooleanSetting HIDE_WATCH_IN_VR_MENU = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
|
public static final BooleanSetting HIDE_WATCH_IN_VR_MENU = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
|
||||||
|
public static final BooleanSetting HIDE_VIDEO_QUALITY_MENU_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE);
|
||||||
|
|
||||||
// General layout
|
// General layout
|
||||||
public static final StringSetting START_PAGE = new StringSetting("revanced_start_page", "");
|
public static final StringSetting START_PAGE = new StringSetting("revanced_start_page", "");
|
||||||
@ -215,6 +215,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_TAGGED_PRODUCTS = new BooleanSetting("revanced_hide_shorts_tagged_products", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_TAGGED_PRODUCTS = new BooleanSetting("revanced_hide_shorts_tagged_products", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE);
|
||||||
|
// Save sound to playlist and Search suggestions may have been A/B tests that were abandoned by YT, and it's not clear if these are still used.
|
||||||
public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SUPER_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_super_thanks_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_SUPER_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_super_thanks_button", TRUE);
|
||||||
|
@ -3,13 +3,11 @@ package app.revanced.integrations.youtube.settings.preference;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
import app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment;
|
import app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment;
|
||||||
import app.revanced.integrations.youtube.patches.DownloadsPatch;
|
|
||||||
import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
version = 1.11.0
|
version = 1.11.1-dev.4
|
||||||
|
Loading…
x
Reference in New Issue
Block a user