From d3eba27c909e519eaeda072c1f995a2284007749 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:58:21 +0300 Subject: [PATCH 01/31] fix(YouTube - Old video quality menu): Fix toast error on tablet devices (#500) --- .../playback/quality/OldVideoQualityMenuPatch.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java index 0d914ab3d7..470536742a 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java @@ -27,10 +27,13 @@ public static void onFlyoutMenuCreate(RecyclerView recyclerView) { // Check if the current view is the quality menu. if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) { VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false; - ((ViewGroup) recyclerView.getParent().getParent().getParent()).setVisibility(View.GONE); - // Click the "Advanced" quality menu to show the "old" quality menu. - ((ViewGroup) recyclerView.getChildAt(0)).getChildAt(3).performClick(); + ((ViewGroup) recyclerView.getParent().getParent().getParent()).setVisibility(View.GONE); + View advancedQualityView = ((ViewGroup) recyclerView.getChildAt(0)).getChildAt(3); + if (advancedQualityView != null) { + // Click the "Advanced" quality menu to show the "old" quality menu. + advancedQualityView.performClick(); + } } } catch (Exception ex) { LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex); From bd307e475f086aa05f02a80bf250c00c2e1f7041 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 15 Oct 2023 16:02:09 +0000 Subject: [PATCH 02/31] chore(release): 0.120.0-dev.3 [skip ci] # [0.120.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.2...v0.120.0-dev.3) (2023-10-15) ### Bug Fixes * **YouTube - Old video quality menu:** Fix toast error on tablet devices ([#500](https://github.com/ReVanced/revanced-integrations/issues/500)) ([d3eba27](https://github.com/ReVanced/revanced-integrations/commit/d3eba27c909e519eaeda072c1f995a2284007749)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3efb9c6e0f..27e40ac1e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.120.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.2...v0.120.0-dev.3) (2023-10-15) + + +### Bug Fixes + +* **YouTube - Old video quality menu:** Fix toast error on tablet devices ([#500](https://github.com/ReVanced/revanced-integrations/issues/500)) ([d3eba27](https://github.com/ReVanced/revanced-integrations/commit/d3eba27c909e519eaeda072c1f995a2284007749)) + # [0.120.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.1...v0.120.0-dev.2) (2023-10-14) diff --git a/gradle.properties b/gradle.properties index 4b4fb3abb7..b5aca39f29 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0-dev.2 +version = 0.120.0-dev.3 From f5add51fa7eb620a6edd1b27f02d38618f144480 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:08:35 +0300 Subject: [PATCH 03/31] perf(YouTube): Reduce memory requirement for prefix tree searching (#501) --- .../patches/components/LithoFilterPatch.java | 8 +- .../integrations/utils/ByteTrieSearch.java | 12 +- .../integrations/utils/StringTrieSearch.java | 12 +- .../integrations/utils/TrieSearch.java | 116 +++++++++++++++--- 4 files changed, 125 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index 5099a4df28..a4051c5534 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -425,15 +425,15 @@ private static void findAsciiStrings(StringBuilder builder, byte[] buffer) { static { for (Filter filter : filters) { - filterGroupLists(pathSearchTree, filter, filter.pathFilterGroupList); filterGroupLists(identifierSearchTree, filter, filter.identifierFilterGroupList); + filterGroupLists(pathSearchTree, filter, filter.pathFilterGroupList); } LogHelper.printDebug(() -> "Using: " - + pathSearchTree.numberOfPatterns() + " path filters" - + " (" + pathSearchTree.getEstimatedMemorySize() + " KB), " + identifierSearchTree.numberOfPatterns() + " identifier filters" - + " (" + identifierSearchTree.getEstimatedMemorySize() + " KB)"); + + " (" + identifierSearchTree.getEstimatedMemorySize() + " KB), " + + pathSearchTree.numberOfPatterns() + " path filters" + + " (" + pathSearchTree.getEstimatedMemorySize() + " KB)"); } private static void filterGroupLists(TrieSearch pathSearchTree, diff --git a/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java b/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java index 807f3f8add..02a1ff705c 100644 --- a/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java @@ -8,9 +8,17 @@ public final class ByteTrieSearch extends TrieSearch { private static final class ByteTrieNode extends TrieNode { - TrieNode createNode() { - return new ByteTrieNode(); + ByteTrieNode() { + super(); } + ByteTrieNode(char nodeCharacterValue) { + super(nodeCharacterValue); + } + @Override + TrieNode createNode(char nodeCharacterValue) { + return new ByteTrieNode(nodeCharacterValue); + } + @Override char getCharValue(byte[] text, int index) { return (char) text[index]; } diff --git a/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java b/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java index 1a1a0a9ea1..28d960cf98 100644 --- a/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java @@ -11,9 +11,17 @@ public final class StringTrieSearch extends TrieSearch { private static final class StringTrieNode extends TrieNode { - TrieNode createNode() { - return new StringTrieNode(); + StringTrieNode() { + super(); } + StringTrieNode(char nodeCharacterValue) { + super(nodeCharacterValue); + } + @Override + TrieNode createNode(char nodeValue) { + return new StringTrieNode(nodeValue); + } + @Override char getCharValue(String text, int index) { return text.charAt(index); } diff --git a/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java b/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java index 8b9fecb8f4..d42c305c94 100644 --- a/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java @@ -71,15 +71,31 @@ boolean matches(TrieNode enclosingNode, // Used only for the get character me } static abstract class TrieNode { + /** + * Dummy value used for root node. Value can be anything as it's never referenced. + */ + private static final char ROOT_NODE_CHARACTER_VALUE = 0; // ASCII null character. + // Support only ASCII letters/numbers/symbols and filter out all control characters. private static final char MIN_VALID_CHAR = 32; // Space character. private static final char MAX_VALID_CHAR = 126; // 127 = delete character. - private static final int NUMBER_OF_CHILDREN = MAX_VALID_CHAR - MIN_VALID_CHAR + 1; + + /** + * How much to expand the children array when resizing. + */ + private static final int CHILDREN_ARRAY_INCREASE_SIZE_INCREMENT = 2; + private static final int CHILDREN_ARRAY_MAX_SIZE = MAX_VALID_CHAR - MIN_VALID_CHAR + 1; private static boolean isInvalidRange(char character) { return character < MIN_VALID_CHAR || character > MAX_VALID_CHAR; } + /** + * Character this node represents. + * This field is ignored for the root node (which does not represent any character). + */ + private final char nodeValue; + /** * A compressed graph path that represents the remaining pattern characters of a single child node. * @@ -91,6 +107,24 @@ private static boolean isInvalidRange(char character) { /** * All child nodes. Only present if no compressed leaf exist. + * + * Array is dynamically increased in size as needed, + * and uses perfect hashing for the elements it contains. + * + * So if the array contains a given character, + * the character will always map to the node with index: (character % arraySize). + * + * Elements not contained can collide with elements the array does contain, + * so must compare the nodes character value. + * + * Alternatively this array could be a sorted and densely packed array, + * and lookup is done using binary search. + * That would save a small amount of memory because there's no null children entries, + * but would give a worst case search of O(nlog(m)) where n is the number of + * characters in the searched text and m is the maximum size of the sorted character arrays. + * Using a hash table array always gives O(n) search time. + * The memory usage here is very small (all Litho filters use ~10KB of memory), + * so the more performant hash implementation is chosen. */ @Nullable private TrieNode[] children; @@ -101,6 +135,13 @@ private static boolean isInvalidRange(char character) { @Nullable private List> endOfPatternCallback; + TrieNode() { + this.nodeValue = ROOT_NODE_CHARACTER_VALUE; + } + TrieNode(char nodeCharacterValue) { + this.nodeValue = nodeCharacterValue; + } + /** * @param pattern Pattern to add. * @param patternLength Length of the pattern. @@ -121,7 +162,7 @@ private void addPattern(@NonNull T pattern, int patternLength, int patternIndex, // Recursively call back into this method and push the existing leaf down 1 level. if (children != null) throw new IllegalStateException(); //noinspection unchecked - children = new TrieNode[NUMBER_OF_CHILDREN]; + children = new TrieNode[1]; TrieCompressedPath temp = leaf; leaf = null; addPattern(temp.pattern, temp.patternLength, temp.patternStartIndex, temp.callback); @@ -130,19 +171,65 @@ private void addPattern(@NonNull T pattern, int patternLength, int patternIndex, leaf = new TrieCompressedPath<>(pattern, patternLength, patternIndex, callback); return; } - char character = getCharValue(pattern, patternIndex); + final char character = getCharValue(pattern, patternIndex); if (isInvalidRange(character)) { throw new IllegalArgumentException("invalid character at index " + patternIndex + ": " + pattern); } - character -= MIN_VALID_CHAR; // Adjust to the array range. - TrieNode child = children[character]; + final int arrayIndex = hashIndexForTableSize(children.length, character); + TrieNode child = children[arrayIndex]; if (child == null) { - child = createNode(); - children[character] = child; + child = createNode(character); + children[arrayIndex] = child; + } else if (child.nodeValue != character) { + // Hash collision. Resize the table until perfect hashing is found. + child = createNode(character); + expandChildArray(child); } child.addPattern(pattern, patternLength, patternIndex + 1, callback); } + /** + * Resizes the children table until all nodes hash to exactly one array index. + * Worse case, this will resize the array to {@link #CHILDREN_ARRAY_MAX_SIZE} elements. + */ + private void expandChildArray(TrieNode child) { + int replacementArraySize = Objects.requireNonNull(children).length; + while (true) { + replacementArraySize += CHILDREN_ARRAY_INCREASE_SIZE_INCREMENT; + //noinspection unchecked + TrieNode[] replacement = new TrieNode[replacementArraySize]; + addNodeToArray(replacement, child); + boolean collision = false; + for (TrieNode existingChild : children) { + if (existingChild != null) { + if (!addNodeToArray(replacement, existingChild)) { + collision = true; + break; + } + } + } + if (collision) { + if (replacementArraySize > CHILDREN_ARRAY_MAX_SIZE) throw new IllegalStateException(); + continue; + } + children = replacement; + return; + } + } + + private static boolean addNodeToArray(TrieNode[] array, TrieNode childToAdd) { + final int insertIndex = hashIndexForTableSize(array.length, childToAdd.nodeValue); + if (array[insertIndex] != null ) { + return false; // Collision. + } + array[insertIndex] = childToAdd; + return true; + } + + private static int hashIndexForTableSize(int arraySize, char nodeValue) { + return (nodeValue - MIN_VALID_CHAR) % arraySize; + } + /** * @param searchText Text to search for patterns in. * @param searchTextLength Length of the search text. @@ -170,18 +257,17 @@ private boolean matches(T searchText, int searchTextLength, int searchTextIndex, if (children == null) { return false; // Reached a graph end point and there's no further patterns to search. } - if (searchTextIndex == searchTextLength) { return false; // Reached end of the search text and found no matches. } - char character = getCharValue(searchText, searchTextIndex); + final char character = getCharValue(searchText, searchTextIndex); if (isInvalidRange(character)) { return false; // Not an ASCII letter/number/symbol. } - character -= MIN_VALID_CHAR; // Adjust to the array range. - TrieNode child = children[character]; - if (child == null) { + final int arrayIndex = hashIndexForTableSize(children.length, character); + TrieNode child = children[arrayIndex]; + if (child == null || child.nodeValue != character) { return false; } return child.matches(searchText, searchTextLength, searchTextIndex + 1, @@ -194,7 +280,7 @@ private boolean matches(T searchText, int searchTextLength, int searchTextIndex, * @return Estimated number of memory pointers used, starting from this node and including all children. */ private int estimatedNumberOfPointersUsed() { - int numberOfPointers = 3; // Number of fields in this class. + int numberOfPointers = 4; // Number of fields in this class. if (leaf != null) { numberOfPointers += 4; // Number of fields in leaf node. } @@ -202,7 +288,7 @@ private int estimatedNumberOfPointersUsed() { numberOfPointers += endOfPatternCallback.size(); } if (children != null) { - numberOfPointers += NUMBER_OF_CHILDREN; + numberOfPointers += children.length; for (TrieNode child : children) { if (child != null) { numberOfPointers += child.estimatedNumberOfPointersUsed(); @@ -212,7 +298,7 @@ private int estimatedNumberOfPointersUsed() { return numberOfPointers; } - abstract TrieNode createNode(); + abstract TrieNode createNode(char nodeValue); abstract char getCharValue(T text, int index); } From c47fcde24295cd76ab414896edb80387a58a5c21 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 17 Oct 2023 10:12:54 +0000 Subject: [PATCH 04/31] chore(release): 0.120.0-dev.4 [skip ci] # [0.120.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.3...v0.120.0-dev.4) (2023-10-17) ### Performance Improvements * **YouTube:** Reduce memory requirement for prefix tree searching ([#501](https://github.com/ReVanced/revanced-integrations/issues/501)) ([f5add51](https://github.com/ReVanced/revanced-integrations/commit/f5add51fa7eb620a6edd1b27f02d38618f144480)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27e40ac1e9..a9a025e782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.120.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.3...v0.120.0-dev.4) (2023-10-17) + + +### Performance Improvements + +* **YouTube:** Reduce memory requirement for prefix tree searching ([#501](https://github.com/ReVanced/revanced-integrations/issues/501)) ([f5add51](https://github.com/ReVanced/revanced-integrations/commit/f5add51fa7eb620a6edd1b27f02d38618f144480)) + # [0.120.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.2...v0.120.0-dev.3) (2023-10-15) diff --git a/gradle.properties b/gradle.properties index b5aca39f29..0c704bfbe7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0-dev.3 +version = 0.120.0-dev.4 From 16f1163a346fef0a87ca9384c9bf6aea977dc8fb Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 19 Oct 2023 03:06:57 +0200 Subject: [PATCH 05/31] feat(YouTube): Add `Spoof device dimensions` patch --- .../patches/spoof/SpoofDeviceDimensionsPatch.java | 14 ++++++++++++++ .../integrations/settings/SettingsEnum.java | 1 + 2 files changed, 15 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/spoof/SpoofDeviceDimensionsPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofDeviceDimensionsPatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofDeviceDimensionsPatch.java new file mode 100644 index 0000000000..5ac5355cf0 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofDeviceDimensionsPatch.java @@ -0,0 +1,14 @@ +package app.revanced.integrations.patches.spoof; + +import app.revanced.integrations.settings.SettingsEnum; + +public class SpoofDeviceDimensionsPatch { + private static final boolean SPOOF = SettingsEnum.SPOOF_DEVICE_DIMENSIONS.getBoolean(); + public static int getMinHeightOrWidth(int minHeightOrWidth) { + return SPOOF ? 64 : minHeightOrWidth; + } + + public static int getMaxHeightOrWidth(int maxHeightOrWidth) { + return SPOOF ? 4096 : maxHeightOrWidth; + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 6b8c18a386..ac1605af31 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -177,6 +177,7 @@ public enum SettingsEnum { "revanced_spoof_signature_verification_enabled_user_dialog_message"), SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false, parents(SPOOF_SIGNATURE)), + SPOOF_DEVICE_DIMENSIONS("revanced_spoof_device_dimensions", BOOLEAN, FALSE, true), BYPASS_URL_REDIRECTS("revanced_bypass_url_redirects", BOOLEAN, TRUE), // Swipe controls From cd6ba256a5b6f3edb9f384a9198890fd51ce6a26 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 19 Oct 2023 01:11:38 +0000 Subject: [PATCH 06/31] chore(release): 0.120.0-dev.5 [skip ci] # [0.120.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.4...v0.120.0-dev.5) (2023-10-19) ### Features * **YouTube:** Add `Spoof device dimensions` patch ([16f1163](https://github.com/ReVanced/revanced-integrations/commit/16f1163a346fef0a87ca9384c9bf6aea977dc8fb)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9a025e782..fa57020b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.120.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.4...v0.120.0-dev.5) (2023-10-19) + + +### Features + +* **YouTube:** Add `Spoof device dimensions` patch ([16f1163](https://github.com/ReVanced/revanced-integrations/commit/16f1163a346fef0a87ca9384c9bf6aea977dc8fb)) + # [0.120.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.3...v0.120.0-dev.4) (2023-10-17) diff --git a/gradle.properties b/gradle.properties index 0c704bfbe7..37d52fa936 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0-dev.4 +version = 0.120.0-dev.5 From 59687f1a39768ab71b2680a5c49df5aaae0d3b4c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Fri, 20 Oct 2023 03:13:37 +0200 Subject: [PATCH 07/31] feat(YouTube): Add `Announcements` patch (#503) --- .../announcements/AnnouncementsPatch.java | 151 ++++++++++++++++++ .../requests/AnnouncementsRoutes.java | 23 +++ .../patches/spoof/requests/PlayerRoutes.java | 8 +- .../integrations/requests/Requester.java | 3 +- .../integrations/settings/SettingsEnum.java | 9 +- .../integrations/utils/ReVancedUtils.java | 30 ++++ 6 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/app/revanced/integrations/patches/announcements/AnnouncementsPatch.java create mode 100644 app/src/main/java/app/revanced/integrations/patches/announcements/requests/AnnouncementsRoutes.java diff --git a/app/src/main/java/app/revanced/integrations/patches/announcements/AnnouncementsPatch.java b/app/src/main/java/app/revanced/integrations/patches/announcements/AnnouncementsPatch.java new file mode 100644 index 0000000000..e68d10c174 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/announcements/AnnouncementsPatch.java @@ -0,0 +1,151 @@ +package app.revanced.integrations.patches.announcements; + +import android.app.Activity; +import android.os.Build; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.widget.TextView; +import androidx.annotation.RequiresApi; +import app.revanced.integrations.patches.announcements.requests.AnnouncementsRoutes; +import app.revanced.integrations.requests.Requester; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; +import org.json.JSONObject; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.UUID; + +import static android.text.Html.FROM_HTML_MODE_COMPACT; +import static app.revanced.integrations.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENT; + +public final class AnnouncementsPatch { + private final static String CONSUMER = getOrSetConsumer(); + + private AnnouncementsPatch() { + } + + @RequiresApi(api = Build.VERSION_CODES.O) + public static void showAnnouncement(final Activity context) { + if (!SettingsEnum.ANNOUNCEMENTS.getBoolean()) return; + + ReVancedUtils.runOnBackgroundThread(() -> { + try { + HttpURLConnection connection = AnnouncementsRoutes.getAnnouncementsConnectionFromRoute(GET_LATEST_ANNOUNCEMENT, CONSUMER); + + LogHelper.printDebug(() -> "Get latest announcement route connection url: " + connection.getURL().toString()); + + try { + // Do not show the announcement if the request failed. + if (connection.getResponseCode() != 200) { + if (SettingsEnum.ANNOUNCEMENT_LAST_HASH.getString().isEmpty()) return; + + SettingsEnum.ANNOUNCEMENT_LAST_HASH.saveValue(""); + ReVancedUtils.showToastLong("Failed to get announcement"); + + return; + } + } catch (IOException ex) { + final var message = "Failed connecting to announcements provider"; + + LogHelper.printException(() -> message, ex); + return; + } + + var jsonString = Requester.parseInputStreamAndClose(connection.getInputStream(), false); + + // Do not show the announcement if it is older or the same as the last one. + final byte[] hashBytes = MessageDigest.getInstance("SHA-256").digest(jsonString.getBytes(StandardCharsets.UTF_8)); + final var hash = java.util.Base64.getEncoder().encodeToString(hashBytes); + if (hash.equals(SettingsEnum.ANNOUNCEMENT_LAST_HASH.getString())) return; + + // Parse the announcement. Fall-back to raw string if it fails. + String title; + String message; + Level level = Level.INFO; + try { + final var announcement = new JSONObject(jsonString); + + title = announcement.getString("title"); + message = announcement.getJSONObject("content").getString("message"); + + if (!announcement.isNull("level")) level = Level.fromInt(announcement.getInt("level")); + } catch (Throwable ex) { + LogHelper.printException(() -> "Failed to parse announcement. Fall-backing to raw string", ex); + + title = "Announcement"; + message = jsonString; + } + + final var finalTitle = title; + final var finalMessage = Html.fromHtml(message, FROM_HTML_MODE_COMPACT); + final Level finalLevel = level; + + ReVancedUtils.runOnMainThread(() -> { + // Show the announcement. + var alertDialog = new android.app.AlertDialog.Builder(context) + .setTitle(finalTitle) + .setMessage(finalMessage) + .setIcon(finalLevel.icon) + .setPositiveButton("Ok", (dialog, which) -> { + SettingsEnum.ANNOUNCEMENT_LAST_HASH.saveValue(hash); + dialog.dismiss(); + }).setNegativeButton("Dismiss", (dialog, which) -> { + dialog.dismiss(); + }) + .setCancelable(false) + .show(); + + // Make links clickable. + ((TextView)alertDialog.findViewById(android.R.id.message)) + .setMovementMethod(LinkMovementMethod.getInstance()); + }); + } catch (Exception e) { + final var message = "Failed to get announcement"; + + LogHelper.printException(() -> message, e); + } + }); + } + + /** + * Clears the last announcement hash if it is not empty. + * + * @return true if the last announcement hash was empty. + */ + private static boolean emptyLastAnnouncementHash() { + if (SettingsEnum.ANNOUNCEMENT_LAST_HASH.getString().isEmpty()) return true; + SettingsEnum.ANNOUNCEMENT_LAST_HASH.saveValue(""); + + return false; + } + + private static String getOrSetConsumer() { + final var consumer = SettingsEnum.ANNOUNCEMENT_CONSUMER.getString(); + if (!consumer.isEmpty()) return consumer; + + final var uuid = UUID.randomUUID().toString(); + SettingsEnum.ANNOUNCEMENT_CONSUMER.saveValue(uuid); + return uuid; + } + + // TODO: Use better icons. + private enum Level { + INFO(android.R.drawable.ic_dialog_info), + WARNING(android.R.drawable.ic_dialog_alert), + SEVERE(android.R.drawable.ic_dialog_alert); + + public final int icon; + + Level(int icon) { + this.icon = icon; + } + + public static Level fromInt(int value) { + return values()[Math.min(value, values().length - 1)]; + } + } +} diff --git a/app/src/main/java/app/revanced/integrations/patches/announcements/requests/AnnouncementsRoutes.java b/app/src/main/java/app/revanced/integrations/patches/announcements/requests/AnnouncementsRoutes.java new file mode 100644 index 0000000000..fc39090b2d --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/announcements/requests/AnnouncementsRoutes.java @@ -0,0 +1,23 @@ +package app.revanced.integrations.patches.announcements.requests; + +import app.revanced.integrations.requests.Requester; +import app.revanced.integrations.requests.Route; + +import java.io.IOException; +import java.net.HttpURLConnection; + +import static app.revanced.integrations.requests.Route.Method.GET; + +public class AnnouncementsRoutes { + private static final String ANNOUNCEMENTS_PROVIDER = "https://api.revanced.app/v2"; + + + public static final Route GET_LATEST_ANNOUNCEMENT = new Route(GET, "/announcements/youtube/latest?consumer={consumer}"); + + private AnnouncementsRoutes() { + } + + public static HttpURLConnection getAnnouncementsConnectionFromRoute(Route route, String... params) throws IOException { + return Requester.getConnectionFromRoute(ANNOUNCEMENTS_PROVIDER, route, params); + } +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java index db3971ba6a..a37dd6f3e8 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java @@ -3,6 +3,7 @@ import app.revanced.integrations.requests.Requester; import app.revanced.integrations.requests.Route; import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; import org.json.JSONException; import org.json.JSONObject; @@ -75,7 +76,12 @@ private PlayerRoutes() { /** @noinspection SameParameterValue*/ static HttpURLConnection getPlayerResponseConnectionFromRoute(Route.CompiledRoute route) throws IOException { var connection = Requester.getConnectionFromCompiledRoute(YT_API_URL, route); - connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip"); + + connection.setRequestProperty( + "User-Agent", "com.google.android.youtube/" + + ReVancedUtils.getVersionName() + + " (Linux; U; Android 12; GB) gzip" + ); connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); connection.setRequestProperty("Content-Type", "application/json"); diff --git a/app/src/main/java/app/revanced/integrations/requests/Requester.java b/app/src/main/java/app/revanced/integrations/requests/Requester.java index c756dfe855..0a49ecacb2 100644 --- a/app/src/main/java/app/revanced/integrations/requests/Requester.java +++ b/app/src/main/java/app/revanced/integrations/requests/Requester.java @@ -1,5 +1,6 @@ package app.revanced.integrations.requests; +import app.revanced.integrations.utils.ReVancedUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -23,7 +24,7 @@ public static HttpURLConnection getConnectionFromCompiledRoute(String apiUrl, Ro String url = apiUrl + route.getCompiledRoute(); HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod(route.getMethod().name()); - connection.setRequestProperty("User-agent", System.getProperty("http.agent") + ";revanced"); + connection.setRequestProperty("User-Agent", System.getProperty("http.agent") + "; ReVanced/" + ReVancedUtils.getVersionName()); return connection; } diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index ac1605af31..a6f47755c6 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -10,10 +10,7 @@ import org.json.JSONException; import org.json.JSONObject; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; import static app.revanced.integrations.settings.SettingsEnum.ReturnType.*; import static app.revanced.integrations.settings.SharedPrefCategory.RETURN_YOUTUBE_DISLIKE; @@ -179,6 +176,9 @@ public enum SettingsEnum { parents(SPOOF_SIGNATURE)), SPOOF_DEVICE_DIMENSIONS("revanced_spoof_device_dimensions", BOOLEAN, FALSE, true), BYPASS_URL_REDIRECTS("revanced_bypass_url_redirects", BOOLEAN, TRUE), + ANNOUNCEMENTS("revanced_announcements", BOOLEAN, TRUE), + ANNOUNCEMENT_CONSUMER("revanced_announcement_consumer", STRING, ""), + ANNOUNCEMENT_LAST_HASH("revanced_announcement_last_hash", STRING, ""), // Swipe controls SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE), @@ -555,6 +555,7 @@ public Object getObjectValue() { private boolean includeWithImportExport() { switch (this) { case RYD_USER_ID: // Not useful to export, no reason to include it. + case ANNOUNCEMENT_CONSUMER: // Not useful to export, no reason to include it. case SB_LAST_VIP_CHECK: case SB_HIDE_EXPORT_WARNING: case SB_SEEN_GUIDELINES: diff --git a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java index 286a03bf23..918d55b7f3 100644 --- a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java +++ b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java @@ -2,8 +2,11 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.view.View; @@ -25,9 +28,36 @@ public class ReVancedUtils { @SuppressLint("StaticFieldLeak") public static Context context; + private static String versionName; + private ReVancedUtils() { } // utility class + public static String getVersionName() { + if (versionName != null) return versionName; + + PackageInfo packageInfo; + try { + final var packageName = Objects.requireNonNull(getContext()).getPackageName(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) + packageInfo = context.getPackageManager().getPackageInfo( + packageName, + PackageManager.PackageInfoFlags.of(0) + ); + else + packageInfo = context.getPackageManager().getPackageInfo( + packageName, + 0 + ); + } catch (PackageManager.NameNotFoundException e) { + LogHelper.printException(() -> "Failed to get package info", e); + return null; + } + + return versionName = packageInfo.versionName; + } + /** * Hide a view by setting its layout height and width to 1dp. * From 2bcd3b4ae50c37071b739562fb03a452fd1ef903 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 20 Oct 2023 01:17:20 +0000 Subject: [PATCH 08/31] chore(release): 0.120.0-dev.6 [skip ci] # [0.120.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.5...v0.120.0-dev.6) (2023-10-20) ### Features * **YouTube:** Add `Announcements` patch ([#503](https://github.com/ReVanced/revanced-integrations/issues/503)) ([59687f1](https://github.com/ReVanced/revanced-integrations/commit/59687f1a39768ab71b2680a5c49df5aaae0d3b4c)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa57020b2d..bbab41ca4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.120.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.5...v0.120.0-dev.6) (2023-10-20) + + +### Features + +* **YouTube:** Add `Announcements` patch ([#503](https://github.com/ReVanced/revanced-integrations/issues/503)) ([59687f1](https://github.com/ReVanced/revanced-integrations/commit/59687f1a39768ab71b2680a5c49df5aaae0d3b4c)) + # [0.120.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.4...v0.120.0-dev.5) (2023-10-19) diff --git a/gradle.properties b/gradle.properties index 37d52fa936..143e2e8b8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0-dev.5 +version = 0.120.0-dev.6 From 650a5e06ee5bcceee9455230a6f6aa6444311cc2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 20 Oct 2023 01:26:34 +0000 Subject: [PATCH 09/31] chore(release): 0.120.0 [skip ci] # [0.120.0](https://github.com/ReVanced/revanced-integrations/compare/v0.119.2...v0.120.0) (2023-10-20) ### Bug Fixes * **YouTube - Hide Layout components:** Exempt expandable chips from exceptions ([#498](https://github.com/ReVanced/revanced-integrations/issues/498)) ([6f79746](https://github.com/ReVanced/revanced-integrations/commit/6f79746d788f196f3aa63b8e7c24b7f15ecd3f50)) * **YouTube - Hide layout components:** Hide new channel watermark component ([9670bd3](https://github.com/ReVanced/revanced-integrations/commit/9670bd305b3b9bbbc900af3b64152aaac125ec14)) * **YouTube - Minimized playback:** Fix pip incorrectly showing if app is minimized immediately after opening a Short ([7d02774](https://github.com/ReVanced/revanced-integrations/commit/7d02774ea192510e692e90ae55a86e25ee321926)) * **YouTube - Old video quality menu:** Fix toast error on tablet devices ([#500](https://github.com/ReVanced/revanced-integrations/issues/500)) ([d3eba27](https://github.com/ReVanced/revanced-integrations/commit/d3eba27c909e519eaeda072c1f995a2284007749)) ### Features * **YouTube - Theme:** Disable gradient loading screen ([fd09e46](https://github.com/ReVanced/revanced-integrations/commit/fd09e46d01c820632cfe440dac34f5cd957e793d)) * **YouTube:** Add `Announcements` patch ([#503](https://github.com/ReVanced/revanced-integrations/issues/503)) ([59687f1](https://github.com/ReVanced/revanced-integrations/commit/59687f1a39768ab71b2680a5c49df5aaae0d3b4c)) * **YouTube:** Add `Spoof device dimensions` patch ([16f1163](https://github.com/ReVanced/revanced-integrations/commit/16f1163a346fef0a87ca9384c9bf6aea977dc8fb)) ### Performance Improvements * **YouTube:** Reduce memory requirement for prefix tree searching ([#501](https://github.com/ReVanced/revanced-integrations/issues/501)) ([f5add51](https://github.com/ReVanced/revanced-integrations/commit/f5add51fa7eb620a6edd1b27f02d38618f144480)) --- CHANGELOG.md | 22 ++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbab41ca4f..4b8fcbec96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +# [0.120.0](https://github.com/ReVanced/revanced-integrations/compare/v0.119.2...v0.120.0) (2023-10-20) + + +### Bug Fixes + +* **YouTube - Hide Layout components:** Exempt expandable chips from exceptions ([#498](https://github.com/ReVanced/revanced-integrations/issues/498)) ([6f79746](https://github.com/ReVanced/revanced-integrations/commit/6f79746d788f196f3aa63b8e7c24b7f15ecd3f50)) +* **YouTube - Hide layout components:** Hide new channel watermark component ([9670bd3](https://github.com/ReVanced/revanced-integrations/commit/9670bd305b3b9bbbc900af3b64152aaac125ec14)) +* **YouTube - Minimized playback:** Fix pip incorrectly showing if app is minimized immediately after opening a Short ([7d02774](https://github.com/ReVanced/revanced-integrations/commit/7d02774ea192510e692e90ae55a86e25ee321926)) +* **YouTube - Old video quality menu:** Fix toast error on tablet devices ([#500](https://github.com/ReVanced/revanced-integrations/issues/500)) ([d3eba27](https://github.com/ReVanced/revanced-integrations/commit/d3eba27c909e519eaeda072c1f995a2284007749)) + + +### Features + +* **YouTube - Theme:** Disable gradient loading screen ([fd09e46](https://github.com/ReVanced/revanced-integrations/commit/fd09e46d01c820632cfe440dac34f5cd957e793d)) +* **YouTube:** Add `Announcements` patch ([#503](https://github.com/ReVanced/revanced-integrations/issues/503)) ([59687f1](https://github.com/ReVanced/revanced-integrations/commit/59687f1a39768ab71b2680a5c49df5aaae0d3b4c)) +* **YouTube:** Add `Spoof device dimensions` patch ([16f1163](https://github.com/ReVanced/revanced-integrations/commit/16f1163a346fef0a87ca9384c9bf6aea977dc8fb)) + + +### Performance Improvements + +* **YouTube:** Reduce memory requirement for prefix tree searching ([#501](https://github.com/ReVanced/revanced-integrations/issues/501)) ([f5add51](https://github.com/ReVanced/revanced-integrations/commit/f5add51fa7eb620a6edd1b27f02d38618f144480)) + # [0.120.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0-dev.5...v0.120.0-dev.6) (2023-10-20) diff --git a/gradle.properties b/gradle.properties index 143e2e8b8d..8a6d6c2054 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0-dev.6 +version = 0.120.0 From 6d5a5c8281fc13d02ed42f6b93f08932da0d2a56 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:18:02 +0300 Subject: [PATCH 10/31] fix(YouTube - Minimized playback): Fix pip incorrectly showing for Short playback (#504) --- .../integrations/patches/MinimizedPlaybackPatch.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java b/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java index 6fcae6bfc5..b30b15544c 100644 --- a/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java @@ -4,10 +4,16 @@ public class MinimizedPlaybackPatch { - public static boolean isPlaybackNotShort() { + /** + * Injection point. + */ + public static boolean videoSupportsMinimizedPlayback() { return !PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized(); } + /** + * Injection point. + */ public static boolean overrideMinimizedPlaybackAvailable() { // This could be done entirely in the patch, // but having a unique method to search for makes manually inspecting the patched apk much easier. From f19f122fee622cd981dce5ca6d26ba098ebb96d4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 20 Oct 2023 10:22:43 +0000 Subject: [PATCH 11/31] chore(release): 0.120.1-dev.1 [skip ci] ## [0.120.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0...v0.120.1-dev.1) (2023-10-20) ### Bug Fixes * **YouTube - Minimized playback:** Fix pip incorrectly showing for Short playback ([#504](https://github.com/ReVanced/revanced-integrations/issues/504)) ([6d5a5c8](https://github.com/ReVanced/revanced-integrations/commit/6d5a5c8281fc13d02ed42f6b93f08932da0d2a56)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8fcbec96..0b22b90ab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.120.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0...v0.120.1-dev.1) (2023-10-20) + + +### Bug Fixes + +* **YouTube - Minimized playback:** Fix pip incorrectly showing for Short playback ([#504](https://github.com/ReVanced/revanced-integrations/issues/504)) ([6d5a5c8](https://github.com/ReVanced/revanced-integrations/commit/6d5a5c8281fc13d02ed42f6b93f08932da0d2a56)) + # [0.120.0](https://github.com/ReVanced/revanced-integrations/compare/v0.119.2...v0.120.0) (2023-10-20) diff --git a/gradle.properties b/gradle.properties index 8a6d6c2054..37ca1135c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0 +version = 0.120.1-dev.1 From e68f558e9ccac4c6e0d9113b3f134e89edd2233f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:35:14 +0300 Subject: [PATCH 12/31] Revert "chore(release): 0.120.1-dev.1 [skip ci]" This reverts commit f19f122fee622cd981dce5ca6d26ba098ebb96d4. --- CHANGELOG.md | 7 ------- gradle.properties | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b22b90ab0..4b8fcbec96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,3 @@ -## [0.120.1-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.120.0...v0.120.1-dev.1) (2023-10-20) - - -### Bug Fixes - -* **YouTube - Minimized playback:** Fix pip incorrectly showing for Short playback ([#504](https://github.com/ReVanced/revanced-integrations/issues/504)) ([6d5a5c8](https://github.com/ReVanced/revanced-integrations/commit/6d5a5c8281fc13d02ed42f6b93f08932da0d2a56)) - # [0.120.0](https://github.com/ReVanced/revanced-integrations/compare/v0.119.2...v0.120.0) (2023-10-20) diff --git a/gradle.properties b/gradle.properties index 37ca1135c2..8a6d6c2054 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.1-dev.1 +version = 0.120.0 From c1c7e3b5964394de6af39f6fb83d667eba174f0a Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 20 Oct 2023 13:35:14 +0300 Subject: [PATCH 13/31] Revert "fix(YouTube - Minimized playback): Fix pip incorrectly showing for Short playback (#504)" This reverts commit 6d5a5c8281fc13d02ed42f6b93f08932da0d2a56. --- .../integrations/patches/MinimizedPlaybackPatch.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java b/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java index b30b15544c..6fcae6bfc5 100644 --- a/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/MinimizedPlaybackPatch.java @@ -4,16 +4,10 @@ public class MinimizedPlaybackPatch { - /** - * Injection point. - */ - public static boolean videoSupportsMinimizedPlayback() { + public static boolean isPlaybackNotShort() { return !PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized(); } - /** - * Injection point. - */ public static boolean overrideMinimizedPlaybackAvailable() { // This could be done entirely in the patch, // but having a unique method to search for makes manually inspecting the patched apk much easier. From e68646d4f78038616b2cd08759b7a3a2718313d0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 20 Oct 2023 10:40:29 +0000 Subject: [PATCH 14/31] chore(release): 0.120.1-dev.2 [skip ci] ## [0.120.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.1...v0.120.1-dev.2) (2023-10-20) ### Reverts * Revert "fix(YouTube - Minimized playback): Fix pip incorrectly showing for Short playback (#504)" ([c1c7e3b](https://github.com/ReVanced/revanced-integrations/commit/c1c7e3b5964394de6af39f6fb83d667eba174f0a)), closes [#504](https://github.com/ReVanced/revanced-integrations/issues/504) * Revert "chore(release): 0.120.1-dev.1 [skip ci]" ([e68f558](https://github.com/ReVanced/revanced-integrations/commit/e68f558e9ccac4c6e0d9113b3f134e89edd2233f)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8fcbec96..5df2a3a02c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [0.120.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.1...v0.120.1-dev.2) (2023-10-20) + + +### Reverts + +* Revert "fix(YouTube - Minimized playback): Fix pip incorrectly showing for Short playback (#504)" ([c1c7e3b](https://github.com/ReVanced/revanced-integrations/commit/c1c7e3b5964394de6af39f6fb83d667eba174f0a)), closes [#504](https://github.com/ReVanced/revanced-integrations/issues/504) +* Revert "chore(release): 0.120.1-dev.1 [skip ci]" ([e68f558](https://github.com/ReVanced/revanced-integrations/commit/e68f558e9ccac4c6e0d9113b3f134e89edd2233f)) + # [0.120.0](https://github.com/ReVanced/revanced-integrations/compare/v0.119.2...v0.120.0) (2023-10-20) diff --git a/gradle.properties b/gradle.properties index 8a6d6c2054..4816d52dff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.0 +version = 0.120.1-dev.2 From debd0a2e1101e543161390fd3ced6bda19030155 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 21 Oct 2023 15:18:00 +0300 Subject: [PATCH 15/31] fix(YouTube - Custom filter): Fix app crash if invalid character is used in custom filter (#506) --- .../patches/components/LithoFilterPatch.java | 16 +++- .../integrations/utils/ByteTrieSearch.java | 47 ++++------ .../integrations/utils/StringTrieSearch.java | 46 ++++----- .../integrations/utils/TrieSearch.java | 93 +++++++++++-------- 4 files changed, 98 insertions(+), 104 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index a4051c5534..5213025d0e 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -128,8 +128,20 @@ public FilterGroupResult check(final String string) { final class CustomFilterGroup extends StringFilterGroup { - public CustomFilterGroup(final SettingsEnum setting, final SettingsEnum filter) { - super(setting, filter.getString().split("\\s+")); + private static String[] getFilterPatterns(SettingsEnum setting) { + String[] patterns = setting.getString().split("\\s+"); + for (String pattern : patterns) { + if (!StringTrieSearch.isValidPattern(pattern)) { + ReVancedUtils.showToastLong("Invalid custom filter, resetting to default"); + setting.saveValue(setting.defaultValue); + return getFilterPatterns(setting); + } + } + return patterns; + } + + public CustomFilterGroup(SettingsEnum setting, SettingsEnum filter) { + super(setting, getFilterPatterns(filter)); } } diff --git a/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java b/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java index 02a1ff705c..4e47d5551b 100644 --- a/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/utils/ByteTrieSearch.java @@ -1,10 +1,5 @@ package app.revanced.integrations.utils; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.Objects; - public final class ByteTrieSearch extends TrieSearch { private static final class ByteTrieNode extends TrieNode { @@ -22,35 +17,25 @@ TrieNode createNode(char nodeCharacterValue) { char getCharValue(byte[] text, int index) { return (char) text[index]; } + @Override + int getTextLength(byte[] text) { + return text.length; + } } - public ByteTrieSearch() { - super(new ByteTrieNode()); - } - - @Override - public void addPattern(@NonNull byte[] pattern) { - super.addPattern(pattern, pattern.length, null); - } - - @Override - public void addPattern(@NonNull byte[] pattern, @NonNull TriePatternMatchedCallback callback) { - super.addPattern(pattern, pattern.length, Objects.requireNonNull(callback)); - } - - @Override - public boolean matches(@NonNull byte[] textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) { - return super.matches(textToSearch, textToSearch.length, startIndex, endIndex, callbackParameter); - } - - @Override - public boolean matches(@NonNull byte[] textToSearch, int startIndex) { - return matches(textToSearch, startIndex, textToSearch.length, null); + /** + * @return If the pattern is valid to add to this instance. + */ + public static boolean isValidPattern(byte[] pattern) { + for (byte b : pattern) { + if (TrieNode.isInvalidRange((char) b)) { + return false; + } + } + return true; } - @Override - public boolean matches(@NonNull byte[] textToSearch, @Nullable Object callbackParameter) { - return matches(textToSearch,0, textToSearch.length, callbackParameter); + public ByteTrieSearch() { + super(new ByteTrieNode()); } - } diff --git a/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java b/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java index 28d960cf98..8c7aeeb103 100644 --- a/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/utils/StringTrieSearch.java @@ -1,10 +1,5 @@ package app.revanced.integrations.utils; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.Objects; - /** * Text pattern searching using a prefix tree (trie). */ @@ -25,34 +20,25 @@ TrieNode createNode(char nodeValue) { char getCharValue(String text, int index) { return text.charAt(index); } + @Override + int getTextLength(String text) { + return text.length(); + } } - public StringTrieSearch() { - super(new StringTrieNode()); - } - - @Override - public void addPattern(@NonNull String pattern) { - super.addPattern(pattern, pattern.length(), null); - } - - @Override - public void addPattern(@NonNull String pattern, @NonNull TriePatternMatchedCallback callback) { - super.addPattern(pattern, pattern.length(), Objects.requireNonNull(callback)); - } - - @Override - public boolean matches(@NonNull String textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) { - return super.matches(textToSearch, textToSearch.length(), startIndex, endIndex, callbackParameter); - } - - @Override - public boolean matches(@NonNull String textToSearch, @Nullable Object callbackParameter) { - return matches(textToSearch, 0, textToSearch.length(), callbackParameter); + /** + * @return If the pattern is valid to add to this instance. + */ + public static boolean isValidPattern(String pattern) { + for (int i = 0, length = pattern.length(); i < length; i++) { + if (TrieNode.isInvalidRange(pattern.charAt(i))) { + return false; + } + } + return true; } - @Override - public boolean matches(@NonNull String textToSearch, int startIndex) { - return matches(textToSearch, startIndex, textToSearch.length(), null); + public StringTrieSearch() { + super(new StringTrieNode()); } } diff --git a/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java b/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java index d42c305c94..437c791604 100644 --- a/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java +++ b/app/src/main/java/app/revanced/integrations/utils/TrieSearch.java @@ -86,7 +86,7 @@ static abstract class TrieNode { private static final int CHILDREN_ARRAY_INCREASE_SIZE_INCREMENT = 2; private static final int CHILDREN_ARRAY_MAX_SIZE = MAX_VALID_CHAR - MIN_VALID_CHAR + 1; - private static boolean isInvalidRange(char character) { + static boolean isInvalidRange(char character) { return character < MIN_VALID_CHAR || character > MAX_VALID_CHAR; } @@ -227,7 +227,7 @@ private static boolean addNodeToArray(TrieNode[] array, TrieNode child } private static int hashIndexForTableSize(int arraySize, char nodeValue) { - return (nodeValue - MIN_VALID_CHAR) % arraySize; + return nodeValue % arraySize; } /** @@ -300,6 +300,7 @@ private int estimatedNumberOfPointersUsed() { abstract TrieNode createNode(char nodeValue); abstract char getCharValue(T text, int index); + abstract int getTextLength(T text); } /** @@ -323,6 +324,23 @@ public final void addPatterns(@NonNull T... patterns) { } } + /** + * Adds a pattern that will always return a positive match if found. + * + * @param pattern Pattern to add. Calling this with a zero length pattern does nothing. + */ + public void addPattern(@NonNull T pattern) { + addPattern(pattern, root.getTextLength(pattern), null); + } + + /** + * @param pattern Pattern to add. Calling this with a zero length pattern does nothing. + * @param callback Callback to determine if searching should halt when a match is found. + */ + public void addPattern(@NonNull T pattern, @NonNull TriePatternMatchedCallback callback) { + addPattern(pattern, root.getTextLength(pattern), Objects.requireNonNull(callback)); + } + void addPattern(@NonNull T pattern, int patternLength, @Nullable TriePatternMatchedCallback callback) { if (patternLength == 0) return; // Nothing to match @@ -330,8 +348,38 @@ void addPattern(@NonNull T pattern, int patternLength, @Nullable TriePatternMatc root.addPattern(pattern, patternLength, 0, callback); } - final boolean matches(@NonNull T textToSearch, int textToSearchLength, int startIndex, int endIndex, - @Nullable Object callbackParameter) { + public final boolean matches(@NonNull T textToSearch) { + return matches(textToSearch, 0); + } + + public boolean matches(@NonNull T textToSearch, @NonNull Object callbackParameter) { + return matches(textToSearch, 0, root.getTextLength(textToSearch), + Objects.requireNonNull(callbackParameter)); + } + + public boolean matches(@NonNull T textToSearch, int startIndex) { + return matches(textToSearch, startIndex, root.getTextLength(textToSearch)); + } + + public final boolean matches(@NonNull T textToSearch, int startIndex, int endIndex) { + return matches(textToSearch, startIndex, endIndex, null); + } + + /** + * Searches through text, looking for any substring that matches any pattern in this tree. + * + * @param textToSearch Text to search through. + * @param startIndex Index to start searching, inclusive value. + * @param endIndex Index to stop matching, exclusive value. + * @param callbackParameter Optional parameter passed to the callbacks. + * @return If any pattern matched, and it's callback halted searching. + */ + public boolean matches(@NonNull T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) { + return matches(textToSearch, root.getTextLength(textToSearch), startIndex, endIndex, callbackParameter); + } + + private boolean matches(@NonNull T textToSearch, int textToSearchLength, int startIndex, int endIndex, + @Nullable Object callbackParameter) { if (endIndex > textToSearchLength) { throw new IllegalArgumentException("endIndex: " + endIndex + " is greater than texToSearchLength: " + textToSearchLength); @@ -365,41 +413,4 @@ public int numberOfPatterns() { public List getPatterns() { return Collections.unmodifiableList(patterns); } - - /** - * Adds a pattern that will always return a positive match if found. - * - * @param pattern Pattern to add. Calling this with a zero length pattern does nothing. - */ - public abstract void addPattern(@NonNull T pattern); - - /** - * @param pattern Pattern to add. Calling this with a zero length pattern does nothing. - * @param callback Callback to determine if searching should halt when a match is found. - */ - public abstract void addPattern(@NonNull T pattern, @NonNull TriePatternMatchedCallback callback); - - - /** - * Searches through text, looking for any substring that matches any pattern in this tree. - * - * @param textToSearch Text to search through. - * @param startIndex Index to start searching, inclusive value. - * @param endIndex Index to stop matching, exclusive value. - * @param callbackParameter Optional parameter passed to the callbacks. - * @return If any pattern matched, and it's callback halted searching. - */ - public abstract boolean matches(@NonNull T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter); - - public abstract boolean matches(@NonNull T textToSearch, int startIndex); - - public abstract boolean matches(@NonNull T textToSearch, @Nullable Object callbackParameter); - - public final boolean matches(@NonNull T textToSearch, int startIndex, int endIndex) { - return matches(textToSearch, startIndex, endIndex, null); - } - - public final boolean matches(@NonNull T textToSearch) { - return matches(textToSearch, 0); - } } From 3e08847dcecb2c3a50226683670ba182a170dfef Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 21 Oct 2023 12:21:57 +0000 Subject: [PATCH 16/31] chore(release): 0.120.1-dev.3 [skip ci] ## [0.120.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.2...v0.120.1-dev.3) (2023-10-21) ### Bug Fixes * **YouTube - Custom filter:** Fix app crash if invalid character is used in custom filter ([#506](https://github.com/ReVanced/revanced-integrations/issues/506)) ([debd0a2](https://github.com/ReVanced/revanced-integrations/commit/debd0a2e1101e543161390fd3ced6bda19030155)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5df2a3a02c..d405f7dee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.120.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.2...v0.120.1-dev.3) (2023-10-21) + + +### Bug Fixes + +* **YouTube - Custom filter:** Fix app crash if invalid character is used in custom filter ([#506](https://github.com/ReVanced/revanced-integrations/issues/506)) ([debd0a2](https://github.com/ReVanced/revanced-integrations/commit/debd0a2e1101e543161390fd3ced6bda19030155)) + ## [0.120.1-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.1...v0.120.1-dev.2) (2023-10-20) diff --git a/gradle.properties b/gradle.properties index 4816d52dff..13ba035bc6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.1-dev.2 +version = 0.120.1-dev.3 From 04608d32e88d184e4662a71498d7a49c1fbbdb25 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 23 Oct 2023 21:46:38 +0200 Subject: [PATCH 17/31] feat(YouTube - Hide layout components): Hide video quality menu footer --- .../patches/components/LayoutComponentsFilter.java | 6 ++++++ .../app/revanced/integrations/settings/SettingsEnum.java | 1 + 2 files changed, 7 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index a5882d2210..21134ae792 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -120,6 +120,11 @@ public LayoutComponentsFilter() { "inline_expander" ); + final var videoQualityMenuFooter = new StringFilterGroup( + SettingsEnum.HIDE_VIDEO_QUALITY_MENU_FOOTER, + "quality_sheet_footer" + ); + final var chapters = new StringFilterGroup( SettingsEnum.HIDE_CHAPTERS, "macro_markers_carousel" @@ -196,6 +201,7 @@ public LayoutComponentsFilter() { joinMembership, medicalPanel, notifyMe, + videoQualityMenuFooter, infoPanel, subscribersCommunityGuidelines, channelGuidelines, diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index a6f47755c6..cec7408497 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -55,6 +55,7 @@ public enum SettingsEnum { HIDE_CHANNEL_BAR("revanced_hide_channel_bar", BOOLEAN, FALSE), HIDE_CHANNEL_MEMBER_SHELF("revanced_hide_channel_member_shelf", BOOLEAN, TRUE), HIDE_EXPANDABLE_CHIP("revanced_hide_expandable_chip", BOOLEAN, TRUE), + HIDE_VIDEO_QUALITY_MENU_FOOTER("revanced_hide_video_quality_menu_footer", BOOLEAN, TRUE), HIDE_CHAPTERS("revanced_hide_chapters", BOOLEAN, TRUE), HIDE_COMMUNITY_GUIDELINES("revanced_hide_community_guidelines", BOOLEAN, TRUE), HIDE_COMMUNITY_POSTS("revanced_hide_community_posts", BOOLEAN, FALSE), From 959ae4f3be2878a84b08b32ac940fce8164ab4ac Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 23 Oct 2023 19:51:04 +0000 Subject: [PATCH 18/31] chore(release): 0.121.0-dev.1 [skip ci] # [0.121.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.3...v0.121.0-dev.1) (2023-10-23) ### Features * **YouTube - Hide layout components:** Hide video quality menu footer ([04608d3](https://github.com/ReVanced/revanced-integrations/commit/04608d32e88d184e4662a71498d7a49c1fbbdb25)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d405f7dee5..3c03dfff62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.121.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.3...v0.121.0-dev.1) (2023-10-23) + + +### Features + +* **YouTube - Hide layout components:** Hide video quality menu footer ([04608d3](https://github.com/ReVanced/revanced-integrations/commit/04608d32e88d184e4662a71498d7a49c1fbbdb25)) + ## [0.120.1-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.2...v0.120.1-dev.3) (2023-10-21) diff --git a/gradle.properties b/gradle.properties index 13ba035bc6..6dc11eb796 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.120.1-dev.3 +version = 0.121.0-dev.1 From 98c91af130b57322aa98a3e66ec0acad26bfc7d6 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 24 Oct 2023 23:34:13 +0300 Subject: [PATCH 19/31] fix(YouTube - ReturnYouTubeDislike): Fix RYD prefetching home feed Shorts (#508) --- .../patches/ReturnYouTubeDislikePatch.java | 14 +++++++++----- .../integrations/patches/VideoInformation.java | 2 +- .../ReturnYouTubeDislikeFilterPatch.java | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index 7bbcb8b852..cd5ef761bf 100644 --- a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -404,11 +404,14 @@ private static boolean isShortTextViewOnScreen(@NonNull View view) { /** * Injection point. Uses 'playback response' video id hook to preload RYD. */ - public static void preloadVideoId(@NonNull String videoId) { - if (!SettingsEnum.RYD_ENABLED.getBoolean()) { + public static void preloadVideoId(@NonNull String videoId, boolean videoIsOpeningOrPlaying) { + // Shorts shelf in home and subscription feed causes player response hook to be called, + // and the 'is opening/playing' parameter will be false. + // This hook will be called again when the Short is actually opened. + if (!videoIsOpeningOrPlaying || !SettingsEnum.RYD_ENABLED.getBoolean()) { return; } - if (!SettingsEnum.RYD_SHORTS.getBoolean() && PlayerType.getCurrent().isNoneOrHidden()) { + if (!SettingsEnum.RYD_SHORTS.getBoolean() && PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized()) { return; } if (videoId.equals(lastPrefetchedVideoId)) { @@ -471,12 +474,13 @@ public static void newVideoLoaded(@Nullable String videoId, boolean isShortsLith if (videoIdIsSame(currentVideoData, videoId)) { return; } - currentVideoData = ReturnYouTubeDislike.getFetchForVideoId(videoId); + ReturnYouTubeDislike data = ReturnYouTubeDislike.getFetchForVideoId(videoId); // Pre-emptively set the data to short status. // Required to prevent Shorts data from being used on a minimized video in incognito mode. if (isNoneHiddenOrSlidingMinimized) { - currentVideoData.setVideoIdIsShort(true); + data.setVideoIdIsShort(true); } + currentVideoData = data; } LogHelper.printDebug(() -> "New video id: " + videoId + " playerType: " + currentPlayerType diff --git a/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java b/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java index ee9034b0b3..9d18190588 100644 --- a/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java +++ b/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java @@ -69,7 +69,7 @@ public static void setVideoId(@NonNull String newlyLoadedVideoId) { * * @param videoId The id of the last video loaded. */ - public static void setPlayerResponseVideoId(@NonNull String videoId) { + public static void setPlayerResponseVideoId(@NonNull String videoId, boolean videoIsOpeningOrPlaying) { if (!playerResponseVideoId.equals(videoId)) { LogHelper.printDebug(() -> "New player response video id: " + videoId); playerResponseVideoId = videoId; diff --git a/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java index b52fd486fc..b1ff2d2e18 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/ReturnYouTubeDislikeFilterPatch.java @@ -53,9 +53,9 @@ protected boolean removeEldestEntry(Map.Entry eldest) { /** * Injection point. */ - public static void newPlayerResponseVideoId(String videoId) { + public static void newPlayerResponseVideoId(String videoId, boolean videoIsOpeningOrPlaying) { try { - if (!SettingsEnum.RYD_SHORTS.getBoolean()) { + if (!videoIsOpeningOrPlaying || !SettingsEnum.RYD_SHORTS.getBoolean()) { return; } synchronized (lastVideoIds) { From 8cbb50b8ed0a49e52036521759c649175ee63221 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 24 Oct 2023 20:39:24 +0000 Subject: [PATCH 20/31] chore(release): 0.121.0-dev.2 [skip ci] # [0.121.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.1...v0.121.0-dev.2) (2023-10-24) ### Bug Fixes * **YouTube - ReturnYouTubeDislike:** Fix RYD prefetching home feed Shorts ([#508](https://github.com/ReVanced/revanced-integrations/issues/508)) ([98c91af](https://github.com/ReVanced/revanced-integrations/commit/98c91af130b57322aa98a3e66ec0acad26bfc7d6)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c03dfff62..d646c03d8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.121.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.1...v0.121.0-dev.2) (2023-10-24) + + +### Bug Fixes + +* **YouTube - ReturnYouTubeDislike:** Fix RYD prefetching home feed Shorts ([#508](https://github.com/ReVanced/revanced-integrations/issues/508)) ([98c91af](https://github.com/ReVanced/revanced-integrations/commit/98c91af130b57322aa98a3e66ec0acad26bfc7d6)) + # [0.121.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.120.1-dev.3...v0.121.0-dev.1) (2023-10-23) diff --git a/gradle.properties b/gradle.properties index 6dc11eb796..ffafb6bacf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.0-dev.1 +version = 0.121.0-dev.2 From bf5071107b8bc88ac6562d45bfa28bdab8e566c7 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 25 Oct 2023 01:46:44 +0200 Subject: [PATCH 21/31] feat(YouTube): Add `Disable fullscreen ambient mode` patch --- .../patches/DisableFullscreenAmbientModePatch.java | 10 ++++++++++ .../revanced/integrations/settings/SettingsEnum.java | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/app/revanced/integrations/patches/DisableFullscreenAmbientModePatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableFullscreenAmbientModePatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableFullscreenAmbientModePatch.java new file mode 100644 index 0000000000..546880bf8e --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/DisableFullscreenAmbientModePatch.java @@ -0,0 +1,10 @@ +package app.revanced.integrations.patches; + +import app.revanced.integrations.settings.SettingsEnum; + +/** @noinspection unused*/ +public final class DisableFullscreenAmbientModePatch { + public static boolean enableFullScreenAmbientMode() { + return !SettingsEnum.DISABLE_FULLSCREEN_AMBIENT_MODE.getBoolean(); + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index cec7408497..2d1c21ac34 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -147,7 +147,7 @@ public enum SettingsEnum { HIDE_SHORTS_CHANNEL_BAR("revanced_hide_shorts_channel_bar", BOOLEAN, FALSE), HIDE_SHORTS_NAVIGATION_BAR("revanced_hide_shorts_navigation_bar", BOOLEAN, TRUE, true), HIDE_SHORTS("revanced_hide_shorts", BOOLEAN, FALSE, true), - + DISABLE_FULLSCREEN_AMBIENT_MODE("revanced_disable_fullscreen_ambient_mode", BOOLEAN, TRUE, true), ALT_THUMBNAIL("revanced_alt_thumbnail", BOOLEAN, FALSE), ALT_THUMBNAIL_TYPE("revanced_alt_thumbnail_type", INTEGER, 2, parents(ALT_THUMBNAIL)), ALT_THUMBNAIL_FAST_QUALITY("revanced_alt_thumbnail_fast_quality", BOOLEAN, FALSE, parents(ALT_THUMBNAIL)), From 6bd5aae9772e80809dbee9f8fffc1247364a9a13 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 25 Oct 2023 01:47:03 +0200 Subject: [PATCH 22/31] feat(YouTube): Add `Disable suggested video end screen` patch --- .../DisableSuggestedVideoEndScreenPatch.java | 13 +++++++++++++ .../integrations/settings/SettingsEnum.java | 1 + 2 files changed, 14 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java new file mode 100644 index 0000000000..9f43581883 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java @@ -0,0 +1,13 @@ +package app.revanced.integrations.patches; + +import android.widget.ImageView; +import app.revanced.integrations.settings.SettingsEnum; + +/** @noinspection unused*/ +public final class DisableSuggestedVideoEndScreenPatch { + public static void closeEndScreen(ImageView imageView) { + if (!SettingsEnum.DISABLE_SUGGESTED_VIDEO_END_SCREEN.getBoolean()) return; + + imageView.performClick(); + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 2d1c21ac34..873d1490b3 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -147,6 +147,7 @@ public enum SettingsEnum { HIDE_SHORTS_CHANNEL_BAR("revanced_hide_shorts_channel_bar", BOOLEAN, FALSE), HIDE_SHORTS_NAVIGATION_BAR("revanced_hide_shorts_navigation_bar", BOOLEAN, TRUE, true), HIDE_SHORTS("revanced_hide_shorts", BOOLEAN, FALSE, true), + DISABLE_SUGGESTED_VIDEO_END_SCREEN("revanced_disable_suggested_video_end_screen", BOOLEAN, TRUE), DISABLE_FULLSCREEN_AMBIENT_MODE("revanced_disable_fullscreen_ambient_mode", BOOLEAN, TRUE, true), ALT_THUMBNAIL("revanced_alt_thumbnail", BOOLEAN, FALSE), ALT_THUMBNAIL_TYPE("revanced_alt_thumbnail_type", INTEGER, 2, parents(ALT_THUMBNAIL)), From 0fbf7a34342d17c14dce02ea388ba1b7724041b3 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 24 Oct 2023 23:51:06 +0000 Subject: [PATCH 23/31] chore(release): 0.121.0-dev.3 [skip ci] # [0.121.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.2...v0.121.0-dev.3) (2023-10-24) ### Features * **YouTube:** Add `Disable fullscreen ambient mode` patch ([bf50711](https://github.com/ReVanced/revanced-integrations/commit/bf5071107b8bc88ac6562d45bfa28bdab8e566c7)) * **YouTube:** Add `Disable suggested video end screen` patch ([6bd5aae](https://github.com/ReVanced/revanced-integrations/commit/6bd5aae9772e80809dbee9f8fffc1247364a9a13)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d646c03d8c..320b523256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [0.121.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.2...v0.121.0-dev.3) (2023-10-24) + + +### Features + +* **YouTube:** Add `Disable fullscreen ambient mode` patch ([bf50711](https://github.com/ReVanced/revanced-integrations/commit/bf5071107b8bc88ac6562d45bfa28bdab8e566c7)) +* **YouTube:** Add `Disable suggested video end screen` patch ([6bd5aae](https://github.com/ReVanced/revanced-integrations/commit/6bd5aae9772e80809dbee9f8fffc1247364a9a13)) + # [0.121.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.1...v0.121.0-dev.2) (2023-10-24) diff --git a/gradle.properties b/gradle.properties index ffafb6bacf..b7d52bab03 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.0-dev.2 +version = 0.121.0-dev.3 From 40cfa1e9af2b064b464c4d03d5c28b5932621d62 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 25 Oct 2023 12:53:44 +0300 Subject: [PATCH 24/31] fix(YouTube - ReturnYouTubeDislike): Use API back off if client connection fails for any reason (#509) --- .../ReturnYouTubeDislike.java | 2 +- .../requests/ReturnYouTubeDislikeApi.java | 84 ++++++++----------- 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java index da8cd810a9..9890708622 100644 --- a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java @@ -80,7 +80,7 @@ public enum Vote { * How long to retain unsuccessful RYD fetches, * and also the minimum time before retrying again. */ - private static final long CACHE_TIMEOUT_FAILURE_MILLISECONDS = 2 * 60 * 1000; // 2 Minutes + private static final long CACHE_TIMEOUT_FAILURE_MILLISECONDS = 3 * 60 * 1000; // 3 Minutes /** * Unique placeholder character, used to detect if a segmented span already has dislikes added to it. diff --git a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java index f10ed8210f..9403ee0c2c 100644 --- a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java +++ b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/requests/ReturnYouTubeDislikeApi.java @@ -32,13 +32,13 @@ public class ReturnYouTubeDislikeApi { /** * {@link #fetchVotes(String)} TCP connection timeout */ - private static final int API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS = 2000; + private static final int API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS = 2 * 1000; // 2 Seconds. /** * {@link #fetchVotes(String)} HTTP read timeout. * To locally debug and force timeouts, change this to a very small number (ie: 100) */ - private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 5000; + private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 5 * 1000; // 5 Seconds. /** * Default connection and response timeout for voting and registration. @@ -46,7 +46,7 @@ public class ReturnYouTubeDislikeApi { * Voting and user registration runs in the background and has has no urgency * so this can be a larger value. */ - private static final int API_REGISTER_VOTE_TIMEOUT_MILLISECONDS = 90000; + private static final int API_REGISTER_VOTE_TIMEOUT_MILLISECONDS = 60 * 1000; // 60 Seconds. /** * Response code of a successful API call @@ -54,31 +54,30 @@ public class ReturnYouTubeDislikeApi { private static final int HTTP_STATUS_CODE_SUCCESS = 200; /** - * Response code indicating the video id is not for a video that can be voted for. - * (it's not a Short or a regular video, and it's likely a YouTube Story) + * Indicates a client rate limit has been reached and the client must back off. */ - private static final int HTTP_STATUS_CODE_NOT_FOUND = 404; + private static final int HTTP_STATUS_CODE_RATE_LIMIT = 429; /** - * Indicates a client rate limit has been reached + * How long to wait until API calls are resumed, if the API requested a back off. + * No clear guideline of how long to wait until resuming. */ - private static final int RATE_LIMIT_HTTP_STATUS_CODE = 429; + private static final int BACKOFF_RATE_LIMIT_MILLISECONDS = 4 * 60 * 1000; // 4 Minutes. /** - * How long to wait until API calls are resumed, if a rate limit is hit. - * No clear guideline of how long to backoff. Using 2 minutes for now. + * How long to wait until API calls are resumed, if any connection error occurs. */ - private static final int RATE_LIMIT_BACKOFF_SECONDS = 120; + private static final int BACKOFF_CONNECTION_ERROR_MILLISECONDS = 60 * 1000; // 60 Seconds. /** - * Last time a {@link #RATE_LIMIT_HTTP_STATUS_CODE} was reached. - * zero if has not been reached. + * If non zero, then the system time of when API calls can resume. */ - private static volatile long lastTimeRateLimitWasHit; // must be volatile, since different threads read/write to this + private static volatile long timeToResumeAPICalls; // must be volatile, since different threads read/write to this /** - * Number of times {@link #RATE_LIMIT_HTTP_STATUS_CODE} was requested by RYD api. - * Does not include network calls attempted while rate limit is in effect + * Number of times {@link #HTTP_STATUS_CODE_RATE_LIMIT} was requested by RYD api. + * Does not include network calls attempted while rate limit is in effect, + * and does not include rate limit imposed if a fetch fails. */ private static volatile int numberOfRateLimitRequestsEncountered; @@ -165,16 +164,16 @@ private static long randomlyWaitIfLocallyDebugging() { * @return True, if api rate limit is in effect. */ private static boolean checkIfRateLimitInEffect(String apiEndPointName) { - if (lastTimeRateLimitWasHit == 0) { + if (timeToResumeAPICalls == 0) { return false; } - final long numberOfSecondsSinceLastRateLimit = (System.currentTimeMillis() - lastTimeRateLimitWasHit) / 1000; - if (numberOfSecondsSinceLastRateLimit < RATE_LIMIT_BACKOFF_SECONDS) { - LogHelper.printDebug(() -> "Ignoring api call " + apiEndPointName + " as only " - + numberOfSecondsSinceLastRateLimit + " seconds has passed since last rate limit."); - return true; + final long now = System.currentTimeMillis(); + if (now > timeToResumeAPICalls) { + timeToResumeAPICalls = 0; + return false; } - return false; + LogHelper.printDebug(() -> "Ignoring api call " + apiEndPointName + " as rate limit is in effect"); + return true; } /** @@ -186,37 +185,33 @@ private static boolean checkIfRateLimitWasHit(int httpResponseCode) { final double RANDOM_RATE_LIMIT_PERCENTAGE = 0.2; // 20% chance of a triggering a rate limit if (Math.random() < RANDOM_RATE_LIMIT_PERCENTAGE) { LogHelper.printDebug(() -> "Artificially triggering rate limit for debug purposes"); - httpResponseCode = RATE_LIMIT_HTTP_STATUS_CODE; + httpResponseCode = HTTP_STATUS_CODE_RATE_LIMIT; } } - - if (httpResponseCode == RATE_LIMIT_HTTP_STATUS_CODE) { - lastTimeRateLimitWasHit = System.currentTimeMillis(); - //noinspection NonAtomicOperationOnVolatileField // don't care, field is used only as an estimate - numberOfRateLimitRequestsEncountered++; - LogHelper.printDebug(() -> "API rate limit was hit. Stopping API calls for the next " - + RATE_LIMIT_BACKOFF_SECONDS + " seconds"); - ReVancedUtils.showToastLong(str("revanced_ryd_failure_client_rate_limit_requested")); - return true; - } - return false; + return httpResponseCode == HTTP_STATUS_CODE_RATE_LIMIT; } - @SuppressWarnings("NonAtomicOperationOnVolatileField") // do not want to pay performance cost of full synchronization for debug fields that are only estimates anyways - private static void updateStatistics(long timeNetworkCallStarted, long timeNetworkCallEnded, boolean connectionError, boolean rateLimitHit) { + @SuppressWarnings("NonAtomicOperationOnVolatileField") // Don't care, fields are estimates. + private static void updateRateLimitAndStats(long timeNetworkCallStarted, boolean connectionError, boolean rateLimitHit) { if (connectionError && rateLimitHit) { throw new IllegalArgumentException(); } - final long responseTimeOfFetchCall = timeNetworkCallEnded - timeNetworkCallStarted; + final long responseTimeOfFetchCall = System.currentTimeMillis() - timeNetworkCallStarted; fetchCallResponseTimeTotal += responseTimeOfFetchCall; fetchCallResponseTimeMin = (fetchCallResponseTimeMin == 0) ? responseTimeOfFetchCall : Math.min(responseTimeOfFetchCall, fetchCallResponseTimeMin); fetchCallResponseTimeMax = Math.max(responseTimeOfFetchCall, fetchCallResponseTimeMax); fetchCallCount++; if (connectionError) { + timeToResumeAPICalls = System.currentTimeMillis() + BACKOFF_CONNECTION_ERROR_MILLISECONDS; fetchCallResponseTimeLast = responseTimeOfFetchCall; fetchCallNumberOfFailures++; } else if (rateLimitHit) { + LogHelper.printDebug(() -> "API rate limit was hit. Stopping API calls for the next " + + BACKOFF_RATE_LIMIT_MILLISECONDS + " seconds"); + timeToResumeAPICalls = System.currentTimeMillis() + BACKOFF_RATE_LIMIT_MILLISECONDS; + numberOfRateLimitRequestsEncountered++; fetchCallResponseTimeLast = FETCH_CALL_RESPONSE_TIME_VALUE_RATE_LIMIT; + ReVancedUtils.showToastLong(str("revanced_ryd_failure_client_rate_limit_requested")); } else { fetchCallResponseTimeLast = responseTimeOfFetchCall; } @@ -262,27 +257,22 @@ public static RYDVoteData fetchVotes(String videoId) { final int responseCode = connection.getResponseCode(); if (checkIfRateLimitWasHit(responseCode)) { connection.disconnect(); // rate limit hit, should disconnect - updateStatistics(timeNetworkCallStarted, System.currentTimeMillis(),false, true); + updateRateLimitAndStats(timeNetworkCallStarted, false, true); return null; } if (responseCode == HTTP_STATUS_CODE_SUCCESS) { - final long timeNetworkCallEnded = System.currentTimeMillis(); // record end time before parsing // do not disconnect, the same server connection will likely be used again soon JSONObject json = Requester.parseJSONObject(connection); try { RYDVoteData votingData = new RYDVoteData(json); - updateStatistics(timeNetworkCallStarted, timeNetworkCallEnded, false, false); + updateRateLimitAndStats(timeNetworkCallStarted, false, false); LogHelper.printDebug(() -> "Voting data fetched: " + votingData); return votingData; } catch (JSONException ex) { LogHelper.printException(() -> "Failed to parse video: " + videoId + " json: " + json, ex); // fall thru to update statistics } - } else if (responseCode == HTTP_STATUS_CODE_NOT_FOUND) { - // normal response when viewing YouTube Stories (cannot vote for these) - LogHelper.printDebug(() -> "Video has no like/dislikes (video is a YouTube Story?): " + videoId); - return null; // do not updated connection statistics } else { handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null); } @@ -296,7 +286,7 @@ public static RYDVoteData fetchVotes(String videoId) { LogHelper.printException(() -> "Failed to fetch votes", ex, str("revanced_ryd_failure_generic", ex.getMessage())); } - updateStatistics(timeNetworkCallStarted, System.currentTimeMillis(), true, false); + updateRateLimitAndStats(timeNetworkCallStarted, true, false); return null; } @@ -311,7 +301,7 @@ public static String registerAsNewUser() { return null; } String userId = randomString(36); - LogHelper.printDebug(() -> "Trying to register new user: " + userId); + LogHelper.printDebug(() -> "Trying to register new user"); HttpURLConnection connection = getRYDConnectionFromRoute(ReturnYouTubeDislikeRoutes.GET_REGISTRATION, userId); connection.setRequestProperty("Accept", "application/json"); From 21bccf6a99116ce435184e6588fcfa17666c0b93 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 25 Oct 2023 09:58:13 +0000 Subject: [PATCH 25/31] chore(release): 0.121.0-dev.4 [skip ci] # [0.121.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.3...v0.121.0-dev.4) (2023-10-25) ### Bug Fixes * **YouTube - ReturnYouTubeDislike:** Use API back off if client connection fails for any reason ([#509](https://github.com/ReVanced/revanced-integrations/issues/509)) ([40cfa1e](https://github.com/ReVanced/revanced-integrations/commit/40cfa1e9af2b064b464c4d03d5c28b5932621d62)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 320b523256..79993f7825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.121.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.3...v0.121.0-dev.4) (2023-10-25) + + +### Bug Fixes + +* **YouTube - ReturnYouTubeDislike:** Use API back off if client connection fails for any reason ([#509](https://github.com/ReVanced/revanced-integrations/issues/509)) ([40cfa1e](https://github.com/ReVanced/revanced-integrations/commit/40cfa1e9af2b064b464c4d03d5c28b5932621d62)) + # [0.121.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.2...v0.121.0-dev.3) (2023-10-24) diff --git a/gradle.properties b/gradle.properties index b7d52bab03..0d3760bdde 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.0-dev.3 +version = 0.121.0-dev.4 From df278222e8814612797e55e616d4ebc075cafb92 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 25 Oct 2023 18:52:23 +0200 Subject: [PATCH 26/31] fix(YouTube - Disable suggested video end screen): Hide the view once possible Previously the patch tried to hide the screen when it was not visible to begin with. --- .../DisableSuggestedVideoEndScreenPatch.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java index 9f43581883..6a5c3ca322 100644 --- a/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/DisableSuggestedVideoEndScreenPatch.java @@ -1,13 +1,26 @@ package app.revanced.integrations.patches; +import android.annotation.SuppressLint; +import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import app.revanced.integrations.settings.SettingsEnum; /** @noinspection unused*/ public final class DisableSuggestedVideoEndScreenPatch { - public static void closeEndScreen(ImageView imageView) { + @SuppressLint("StaticFieldLeak") + private static View lastView; + + public static void closeEndScreen(final ImageView imageView) { if (!SettingsEnum.DISABLE_SUGGESTED_VIDEO_END_SCREEN.getBoolean()) return; - imageView.performClick(); + // Get the view which can be listened to for layout changes. + final var parent = imageView.getParent().getParent(); + + // Prevent adding the listener multiple times. + if (lastView == parent) return; + + lastView = (ViewGroup)parent; + lastView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> imageView.performClick()); } } From 75297a52c1c5f7c2b928964d08b055380f4a08fe Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 25 Oct 2023 19:28:43 +0200 Subject: [PATCH 27/31] feat(YouTube): Add `Enable old seekbar thumbnails` patch --- .../patches/EnableOldSeekbarThumbnailsPatch.java | 9 +++++++++ .../app/revanced/integrations/settings/SettingsEnum.java | 1 + 2 files changed, 10 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java b/app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java new file mode 100644 index 0000000000..a24ba796ce --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch.java @@ -0,0 +1,9 @@ +package app.revanced.integrations.patches; + +import app.revanced.integrations.settings.SettingsEnum; + +public final class EnableOldSeekbarThumbnailsPatch { + public static boolean enableOldSeekbarThumbnails() { + return !SettingsEnum.ENABLE_OLD_SEEKBAR_THUMBNAILS.getBoolean(); + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 873d1490b3..691acea474 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -148,6 +148,7 @@ public enum SettingsEnum { HIDE_SHORTS_NAVIGATION_BAR("revanced_hide_shorts_navigation_bar", BOOLEAN, TRUE, true), HIDE_SHORTS("revanced_hide_shorts", BOOLEAN, FALSE, true), DISABLE_SUGGESTED_VIDEO_END_SCREEN("revanced_disable_suggested_video_end_screen", BOOLEAN, TRUE), + ENABLE_OLD_SEEKBAR_THUMBNAILS("revanced_enable_old_seekbar_thumbnails", BOOLEAN, TRUE), DISABLE_FULLSCREEN_AMBIENT_MODE("revanced_disable_fullscreen_ambient_mode", BOOLEAN, TRUE, true), ALT_THUMBNAIL("revanced_alt_thumbnail", BOOLEAN, FALSE), ALT_THUMBNAIL_TYPE("revanced_alt_thumbnail_type", INTEGER, 2, parents(ALT_THUMBNAIL)), From 2453d30970ac59d78647386f4fe5d904dbc145e4 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 25 Oct 2023 19:33:59 +0200 Subject: [PATCH 28/31] feat(YouTube - Disable precise seeking gesture): Use better patch name The new name now is taken from what YouTube names this feature. --- ...urePatch.java => DisablePreciseSeekingGesturePatch.java} | 6 +++--- .../app/revanced/integrations/settings/SettingsEnum.java | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) rename app/src/main/java/app/revanced/integrations/patches/{DisableFineScrubbingGesturePatch.java => DisablePreciseSeekingGesturePatch.java} (70%) diff --git a/app/src/main/java/app/revanced/integrations/patches/DisableFineScrubbingGesturePatch.java b/app/src/main/java/app/revanced/integrations/patches/DisablePreciseSeekingGesturePatch.java similarity index 70% rename from app/src/main/java/app/revanced/integrations/patches/DisableFineScrubbingGesturePatch.java rename to app/src/main/java/app/revanced/integrations/patches/DisablePreciseSeekingGesturePatch.java index 72a6859065..8043bd2114 100644 --- a/app/src/main/java/app/revanced/integrations/patches/DisableFineScrubbingGesturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/DisablePreciseSeekingGesturePatch.java @@ -4,14 +4,14 @@ import android.view.VelocityTracker; import app.revanced.integrations.settings.SettingsEnum; -public final class DisableFineScrubbingGesturePatch { +public final class DisablePreciseSeekingGesturePatch { /** - * Disables the fine scrubbing gesture. + * Disables the gesture that is used to seek precisely. * @param tracker The velocity tracker that is used to determine the gesture. * @param event The motion event that is used to determine the gesture. */ public static void disableGesture(VelocityTracker tracker, MotionEvent event) { - if (SettingsEnum.DISABLE_FINE_SCRUBBING_GESTURE.getBoolean()) return; + if (SettingsEnum.DISABLE_PRECISE_SEEKING_GESTURE.getBoolean()) return; tracker.addMovement(event); } diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 691acea474..9bb2d1b3e6 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -172,6 +172,7 @@ public enum SettingsEnum { EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true), AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE), SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE), + DISABLE_PRECISE_SEEKING_GESTURE("revanced_disable_precise_seeking_gesture", BOOLEAN, TRUE), DISABLE_FINE_SCRUBBING_GESTURE("revanced_disable_fine_scrubbing_gesture", BOOLEAN, TRUE), SPOOF_SIGNATURE("revanced_spoof_signature_verification_enabled", BOOLEAN, TRUE, true, "revanced_spoof_signature_verification_enabled_user_dialog_message"), @@ -381,6 +382,7 @@ private static void loadAllSettings() { // region Migration migrateOldSettingToNew(HIDE_VIDEO_WATERMARK, HIDE_VIDEO_CHANNEL_WATERMARK); + migrateOldSettingToNew(DISABLE_FINE_SCRUBBING_GESTURE, DISABLE_PRECISE_SEEKING_GESTURE); // Do _not_ delete this SB private user id migration property until sometime in 2024. // This is the only setting that cannot be reconfigured if lost, From 55fe1f0592ea3b3f6dc93c6c7c1b10095c49a036 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 25 Oct 2023 17:38:04 +0000 Subject: [PATCH 29/31] chore(release): 0.121.0-dev.5 [skip ci] # [0.121.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.4...v0.121.0-dev.5) (2023-10-25) ### Bug Fixes * **YouTube - Disable suggested video end screen:** Hide the view once possible ([df27822](https://github.com/ReVanced/revanced-integrations/commit/df278222e8814612797e55e616d4ebc075cafb92)) ### Features * **YouTube - Disable precise seeking gesture:** Use better patch name ([2453d30](https://github.com/ReVanced/revanced-integrations/commit/2453d30970ac59d78647386f4fe5d904dbc145e4)) * **YouTube:** Add `Enable old seekbar thumbnails` patch ([75297a5](https://github.com/ReVanced/revanced-integrations/commit/75297a52c1c5f7c2b928964d08b055380f4a08fe)) --- CHANGELOG.md | 13 +++++++++++++ gradle.properties | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79993f7825..3e930f2a4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [0.121.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.4...v0.121.0-dev.5) (2023-10-25) + + +### Bug Fixes + +* **YouTube - Disable suggested video end screen:** Hide the view once possible ([df27822](https://github.com/ReVanced/revanced-integrations/commit/df278222e8814612797e55e616d4ebc075cafb92)) + + +### Features + +* **YouTube - Disable precise seeking gesture:** Use better patch name ([2453d30](https://github.com/ReVanced/revanced-integrations/commit/2453d30970ac59d78647386f4fe5d904dbc145e4)) +* **YouTube:** Add `Enable old seekbar thumbnails` patch ([75297a5](https://github.com/ReVanced/revanced-integrations/commit/75297a52c1c5f7c2b928964d08b055380f4a08fe)) + # [0.121.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.3...v0.121.0-dev.4) (2023-10-25) diff --git a/gradle.properties b/gradle.properties index 0d3760bdde..1ae93666d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.0-dev.4 +version = 0.121.0-dev.5 From f2037316d36f99ef79ae5792e34d8616ecd31c80 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 26 Oct 2023 00:07:02 +0200 Subject: [PATCH 30/31] fix(YouTube - Client spoof): Set the client version correctly Previously the version was hardcoded. --- .../integrations/patches/spoof/requests/PlayerRoutes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java index a37dd6f3e8..7a769aa25f 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java @@ -31,7 +31,7 @@ final class PlayerRoutes { JSONObject client = new JSONObject(); client.put("clientName", "ANDROID"); - client.put("clientVersion", "18.37.36"); + client.put("clientVersion", ReVancedUtils.getVersionName()); client.put("androidSdkVersion", 34); context.put("client", client); From 1b29b7e11db83ebedb9a8f60a6172829b76bfce8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 25 Oct 2023 22:10:56 +0000 Subject: [PATCH 31/31] chore(release): 0.121.0-dev.6 [skip ci] # [0.121.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.5...v0.121.0-dev.6) (2023-10-25) ### Bug Fixes * **YouTube - Client spoof:** Set the client version correctly ([f203731](https://github.com/ReVanced/revanced-integrations/commit/f2037316d36f99ef79ae5792e34d8616ecd31c80)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e930f2a4e..feeb330e07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.121.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.5...v0.121.0-dev.6) (2023-10-25) + + +### Bug Fixes + +* **YouTube - Client spoof:** Set the client version correctly ([f203731](https://github.com/ReVanced/revanced-integrations/commit/f2037316d36f99ef79ae5792e34d8616ecd31c80)) + # [0.121.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.121.0-dev.4...v0.121.0-dev.5) (2023-10-25) diff --git a/gradle.properties b/gradle.properties index 1ae93666d7..5b9e784917 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.121.0-dev.5 +version = 0.121.0-dev.6