From 407b3a90c3bb6d58a8a44ac439560d266249935c Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 14 Jul 2023 12:35:20 +0400 Subject: [PATCH 1/7] fix(youtube/sponsorblock): fix some segments skipping slightly too late (#436) --- .../patches/VideoInformation.java | 31 ++++----- .../SegmentPlaybackController.java | 63 ++++++++++++------- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/integrations/java/app/revanced/integrations/patches/VideoInformation.java b/integrations/java/app/revanced/integrations/patches/VideoInformation.java index 2a3219537c..ad5bcd1686 100644 --- a/integrations/java/app/revanced/integrations/patches/VideoInformation.java +++ b/integrations/java/app/revanced/integrations/patches/VideoInformation.java @@ -24,7 +24,7 @@ public final class VideoInformation { @NonNull private static String videoId = ""; private static long videoLength = 0; - private static volatile long videoTime = -1; // must be volatile. Value is set off main thread from high precision patch hook + private static long videoTime = -1; /** * The current playback speed */ @@ -98,17 +98,17 @@ public static void setVideoLength(final long length) { /** * Injection point. - * Called off the main thread approximately every 50ms to 100ms + * Called on the main thread every 1000ms. * * @param currentPlaybackTime The current playback time of the video in milliseconds. */ - public static void setVideoTimeHighPrecision(final long currentPlaybackTime) { + public static void setVideoTime(final long currentPlaybackTime) { videoTime = currentPlaybackTime; } /** * Seek on the current video. - * Does not function for playback of Shorts or Stories. + * Does not function for playback of Shorts. * * Caution: If called from a videoTimeHook() callback, * this will cause a recursive call into the same videoTimeHook() callback. @@ -118,11 +118,6 @@ public static void setVideoTimeHighPrecision(final long currentPlaybackTime) { */ public static boolean seekTo(final long millisecond) { ReVancedUtils.verifyOnMainThread(); - if (seekMethod == null) { - LogHelper.printException(() -> "seekMethod was null"); - return false; - } - try { LogHelper.printDebug(() -> "Seeking to " + millisecond); return (Boolean) seekMethod.invoke(playerControllerRef.get(), millisecond); @@ -137,7 +132,7 @@ public static boolean seekToRelative(long millisecondsRelative) { } /** - * Id of the current video playing. Includes Shorts and YouTube Stories. + * Id of the current video playing. Includes Shorts. * * @return The id of the video. Empty string if not set yet. */ @@ -154,7 +149,7 @@ public static float getPlaybackSpeed() { } /** - * Length of the current video playing. Includes Shorts and YouTube Stories. + * Length of the current video playing. Includes Shorts. * * @return The length of the video in milliseconds. * If the video is not yet loaded, or if the video is playing in the background with no video visible, @@ -165,14 +160,14 @@ public static long getVideoLength() { } /** - * Playback time of the current video playing. - * Value can lag up to approximately 100ms behind the actual current video playback time. + * Playback time of the current video playing. Includes Shorts. * - * Note: Code inside a videoTimeHook patch callback - * should use the callback video time and avoid using this method - * (in situations of recursive hook callbacks, the value returned here may be outdated). + * Value will lag behind the actual playback time by a variable amount based on the playback speed. * - * Includes Shorts and YouTube Stories. + * If playback speed is 2.0x, this value may be up to 2000ms behind the actual playback time. + * If playback speed is 1.0x, this value may be up to 1000ms behind the actual playback time. + * If playback speed is 0.5x, this value may be up to 500ms behind the actual playback time. + * Etc. * * @return The time of the video in milliseconds. -1 if not set yet. */ @@ -192,7 +187,7 @@ public static long getVideoTime() { * @see VideoState */ public static boolean isAtEndOfVideo() { - return videoTime > 0 && videoLength > 0 && videoTime >= videoLength; + return videoTime >= videoLength && videoLength > 0; } } diff --git a/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java b/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java index e6bb328d60..be42a49875 100644 --- a/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java +++ b/integrations/java/app/revanced/integrations/sponsorblock/SegmentPlaybackController.java @@ -58,6 +58,7 @@ public class SegmentPlaybackController { /** * Because loading can take time, show the skip to highlight for a few seconds after the segments load. * This is the system time (in milliseconds) to no longer show the initial display skip to highlight. + * Value will be zero if no highlight segment exists, or if the system time to show the highlight has passed. */ private static long highlightSegmentInitialShowEndTime; @@ -198,7 +199,7 @@ public static void setCurrentVideoId(@Nullable String videoId) { return; } if (PlayerType.getCurrent().isNoneOrHidden()) { - LogHelper.printDebug(() -> "ignoring short or story"); + LogHelper.printDebug(() -> "ignoring Short"); return; } if (!ReVancedUtils.isNetworkConnected()) { @@ -238,14 +239,20 @@ static void executeDownloadSegments(@NonNull String videoId) { setSegments(segments); final long videoTime = VideoInformation.getVideoTime(); - // if the current video time is before the highlight - if (highlightSegment != null && videoTime < highlightSegment.end) { - if (highlightSegment.shouldAutoSkip()) { - skipSegment(highlightSegment, false); - return; + if (highlightSegment != null) { + // If the current video time is before the highlight. + final long timeUntilHighlight = highlightSegment.start - videoTime; + if (timeUntilHighlight > 0) { + if (highlightSegment.shouldAutoSkip()) { + skipSegment(highlightSegment, false); + return; + } + highlightSegmentInitialShowEndTime = System.currentTimeMillis() + Math.min( + (long) (timeUntilHighlight / VideoInformation.getPlaybackSpeed()), + DURATION_TO_SHOW_SKIP_BUTTON); } - highlightSegmentInitialShowEndTime = System.currentTimeMillis() + DURATION_TO_SHOW_SKIP_BUTTON; } + // check for any skips now, instead of waiting for the next update to setVideoTime() setVideoTime(videoTime); }); @@ -262,7 +269,7 @@ static void executeDownloadSegments(@NonNull String videoId) { public static void setVideoTime(long millis) { try { if (!SettingsEnum.SB_ENABLED.getBoolean() - || PlayerType.getCurrent().isNoneOrHidden() // shorts playback + || PlayerType.getCurrent().isNoneOrHidden() // Shorts playback. || segments == null || segments.length == 0) { return; } @@ -270,11 +277,17 @@ public static void setVideoTime(long millis) { updateHiddenSegments(millis); - // to debug the timing logic, set this to a very large value (5000 or more) - // then try manually seeking just playback reaches a skip/hide of different segments - final long lookAheadMilliseconds = 1500; // must be larger than the average time between calls to this method final float playbackSpeed = VideoInformation.getPlaybackSpeed(); - final long startTimerLookAheadThreshold = millis + (long)(playbackSpeed * lookAheadMilliseconds); + // Amount of time to look ahead for the next segment, + // and the threshold to determine if a scheduled show/hide is at the correct video time when it's run. + // + // This value must be greater than largest time between calls to this method (1000ms), + // and must be adjusted for the video speed. + // + // To debug the stale skip logic, set this to a very large value (5000 or more) + // then try manually seeking just before playback reaches a segment skip. + final long speedAdjustedTimeThreshold = (long)(playbackSpeed * 1200); + final long startTimerLookAheadThreshold = millis + speedAdjustedTimeThreshold; SponsorSegment foundSegmentCurrentlyPlaying = null; SponsorSegment foundUpcomingSegment = null; @@ -344,9 +357,11 @@ public static void setVideoTime(long millis) { } if (highlightSegment != null) { - if (millis < DURATION_TO_SHOW_SKIP_BUTTON || System.currentTimeMillis() < highlightSegmentInitialShowEndTime) { + if (millis < DURATION_TO_SHOW_SKIP_BUTTON || (highlightSegmentInitialShowEndTime != 0 + && System.currentTimeMillis() < highlightSegmentInitialShowEndTime)) { SponsorBlockViewController.showSkipHighlightButton(highlightSegment); } else { + highlightSegmentInitialShowEndTime = 0; SponsorBlockViewController.hideSkipHighlightButton(); } } @@ -361,12 +376,9 @@ public static void setVideoTime(long millis) { SponsorBlockViewController.hideSkipSegmentButton(); } - // must be greater than the average time between updates to VideoInformation time - final long videoInformationTimeUpdateThresholdMilliseconds = 250; - // schedule a hide, only if the segment end is near final SponsorSegment segmentToHide = - (foundSegmentCurrentlyPlaying != null && foundSegmentCurrentlyPlaying.endIsNear(millis, lookAheadMilliseconds)) + (foundSegmentCurrentlyPlaying != null && foundSegmentCurrentlyPlaying.endIsNear(millis, speedAdjustedTimeThreshold)) ? foundSegmentCurrentlyPlaying : null; @@ -384,9 +396,13 @@ public static void setVideoTime(long millis) { return; } scheduledHideSegment = null; + if (VideoState.getCurrent() != VideoState.PLAYING) { + LogHelper.printDebug(() -> "Ignoring scheduled hide segment as video is paused: " + segmentToHide); + return; + } final long videoTime = VideoInformation.getVideoTime(); - if (!segmentToHide.endIsNear(videoTime, videoInformationTimeUpdateThresholdMilliseconds)) { + if (!segmentToHide.endIsNear(videoTime, speedAdjustedTimeThreshold)) { // current video time is not what's expected. User paused playback LogHelper.printDebug(() -> "Ignoring outdated scheduled hide: " + segmentToHide + " videoInformation time: " + videoTime); @@ -419,10 +435,13 @@ public static void setVideoTime(long millis) { return; } scheduledUpcomingSegment = null; + if (VideoState.getCurrent() != VideoState.PLAYING) { + LogHelper.printDebug(() -> "Ignoring scheduled hide segment as video is paused: " + segmentToSkip); + return; + } final long videoTime = VideoInformation.getVideoTime(); - if (!segmentToSkip.startIsNear(videoTime, - videoInformationTimeUpdateThresholdMilliseconds)) { + if (!segmentToSkip.startIsNear(videoTime, speedAdjustedTimeThreshold)) { // current video time is not what's expected. User paused playback LogHelper.printDebug(() -> "Ignoring outdated scheduled segment: " + segmentToSkip + " videoInformation time: " + videoTime); @@ -488,10 +507,10 @@ private static void skipSegment(@NonNull SponsorSegment segmentToSkip, boolean u SponsorBlockViewController.hideSkipHighlightButton(); SponsorBlockViewController.hideSkipSegmentButton(); - // If trying to seek to end of the video, YouTube can seek just short of the actual end. + // If trying to seek to end of the video, YouTube can seek just before of the actual end. // (especially if the video does not end on a whole second boundary). // This causes additional segment skip attempts, even though it cannot seek any closer to the desired time. - // Check for and ignore repeated skip attempts of the same segment over a short time period. + // Check for and ignore repeated skip attempts of the same segment over a small time period. final long now = System.currentTimeMillis(); final long minimumMillisecondsBetweenSkippingSameSegment = 500; if ((lastSegmentSkipped == segmentToSkip) && (now - lastSegmentSkippedTime < minimumMillisecondsBetweenSkippingSameSegment)) { From d04860fe3ceea1e363a1750a985734e4b2174a1e Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 15 Jul 2023 03:41:52 +0200 Subject: [PATCH 2/7] fix(YouTube - Hide Shorts Components): hide sound button --- .../patches/components/ShortsFilter.java | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/integrations/java/app/revanced/integrations/patches/components/ShortsFilter.java b/integrations/java/app/revanced/integrations/patches/components/ShortsFilter.java index 18fc6f367b..ec1ffe46a4 100644 --- a/integrations/java/app/revanced/integrations/patches/components/ShortsFilter.java +++ b/integrations/java/app/revanced/integrations/patches/components/ShortsFilter.java @@ -1,33 +1,22 @@ package app.revanced.integrations.patches.components; -import static app.revanced.integrations.utils.ReVancedUtils.hideViewBy1dpUnderCondition; -import static app.revanced.integrations.utils.ReVancedUtils.hideViewUnderCondition; - -import android.annotation.SuppressLint; -import android.os.Build; import android.view.View; - +import app.revanced.integrations.settings.SettingsEnum; import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar; -import app.revanced.integrations.settings.SettingsEnum; +import static app.revanced.integrations.utils.ReVancedUtils.hideViewBy1dpUnderCondition; +import static app.revanced.integrations.utils.ReVancedUtils.hideViewUnderCondition; public final class ShortsFilter extends Filter { + // Set by patch. public static PivotBar pivotBar; - @SuppressLint("StaticFieldLeak") - + final StringFilterGroupList shortsFilterGroup = new StringFilterGroupList(); private final StringFilterGroup reelChannelBar = new StringFilterGroup( null, "reel_channel_bar" ); - private final StringFilterGroup infoPanel = new StringFilterGroup( - SettingsEnum.HIDE_SHORTS_INFO_PANEL, - "shorts_info_panel_overview" - ); - public ShortsFilter() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return; - final var thanksButton = new StringFilterGroup( SettingsEnum.HIDE_SHORTS_THANKS_BUTTON, "suggested_action" @@ -48,6 +37,11 @@ public ShortsFilter() { "reel_pivot_button" ); + final var infoPanel = new StringFilterGroup( + SettingsEnum.HIDE_SHORTS_INFO_PANEL, + "shorts_info_panel_overview" + ); + final var channelBar = new StringFilterGroup( SettingsEnum.HIDE_SHORTS_CHANNEL_BAR, "reel_channel_bar" @@ -61,19 +55,20 @@ public ShortsFilter() { "shorts_video_cell" ); - this.pathFilterGroups.addAll(joinButton, subscribeButton, soundButton, channelBar); - this.identifierFilterGroups.addAll(shorts, thanksButton); + shortsFilterGroup.addAll(soundButton, infoPanel); + pathFilterGroups.addAll(joinButton, subscribeButton, channelBar); + identifierFilterGroups.addAll(shorts, thanksButton); } @Override boolean isFiltered(final String path, final String identifier, final byte[] protobufBufferArray) { + // Filter the path only when reelChannelBar is visible. if (reelChannelBar.check(path).isFiltered()) if (this.pathFilterGroups.contains(path)) return true; - // Shorts info panel path appears outside of reelChannelBar path. - if (infoPanel.isEnabled() && infoPanel.check(path).isFiltered()) return true; + if (shortsFilterGroup.contains(path)) return true; return this.identifierFilterGroups.contains(identifier); } From 4f7d7133d1ab5b67ca4d9e6a26c7cbe26c8feb98 Mon Sep 17 00:00:00 2001 From: KAZI MMT <82371061+kazimmt@users.noreply.github.com> Date: Sat, 15 Jul 2023 18:32:21 +0600 Subject: [PATCH 3/7] feat(youtube): rename `video-speed` to `playback-speed` (#438) --- ...java => PlaybackSpeedMenuFilterPatch.java} | 10 ++--- ...tch.java => CustomPlaybackSpeedPatch.java} | 40 +++++++++---------- .../ReVancedSettingsFragment.java | 4 +- 3 files changed, 27 insertions(+), 27 deletions(-) rename integrations/java/app/revanced/integrations/patches/components/{VideoSpeedMenuFilterPatch.java => PlaybackSpeedMenuFilterPatch.java} (60%) rename integrations/java/app/revanced/integrations/patches/playback/speed/{CustomVideoSpeedPatch.java => CustomPlaybackSpeedPatch.java} (76%) diff --git a/integrations/java/app/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch.java b/integrations/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java similarity index 60% rename from integrations/java/app/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch.java rename to integrations/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java index f01d30d152..66b229f493 100644 --- a/integrations/java/app/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch.java +++ b/integrations/java/app/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch.java @@ -1,11 +1,11 @@ package app.revanced.integrations.patches.components; -// Abuse LithoFilter for CustomVideoSpeedPatch. -public final class VideoSpeedMenuFilterPatch extends Filter { +// Abuse LithoFilter for CustomPlaybackSpeedPatch. +public final class PlaybackSpeedMenuFilterPatch extends Filter { // Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread. - public static volatile boolean isVideoSpeedMenuVisible; + public static volatile boolean isPlaybackSpeedMenuVisible; - public VideoSpeedMenuFilterPatch() { + public PlaybackSpeedMenuFilterPatch() { pathFilterGroups.addAll(new StringFilterGroup( null, "playback_speed_sheet_content.eml-js" @@ -14,7 +14,7 @@ public VideoSpeedMenuFilterPatch() { @Override boolean isFiltered(final String path, final String identifier, final byte[] protobufBufferArray) { - isVideoSpeedMenuVisible = super.isFiltered(path, identifier, protobufBufferArray); + isPlaybackSpeedMenuVisible = super.isFiltered(path, identifier, protobufBufferArray); return false; } diff --git a/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java b/integrations/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java similarity index 76% rename from integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java rename to integrations/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java index a8e2e60359..631ad943e1 100644 --- a/integrations/java/app/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch.java +++ b/integrations/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -13,12 +13,12 @@ import java.util.Arrays; -import app.revanced.integrations.patches.components.VideoSpeedMenuFilterPatch; +import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; -public class CustomVideoSpeedPatch { +public class CustomPlaybackSpeedPatch { /** * Maximum playback speed, exclusive value. Custom speeds must be less than this value. */ @@ -27,17 +27,17 @@ public class CustomVideoSpeedPatch { /** * Custom playback speeds. */ - public static float[] customVideoSpeeds; + public static float[] customPlaybackSpeeds; /** - * Minimum value of {@link #customVideoSpeeds} + * Minimum value of {@link #customPlaybackSpeeds} */ - public static float minVideoSpeed; + public static float minPlaybackSpeed; /** - * Maxium value of {@link #customVideoSpeeds} + * Maxium value of {@link #customPlaybackSpeeds} */ - public static float maxVideoSpeed; + public static float maxPlaybackSpeed; /** * PreferenceList entries and values, of all available playback speeds. @@ -60,10 +60,10 @@ private static void loadCustomSpeeds() { if (speedStrings.length == 0) { throw new IllegalArgumentException(); } - customVideoSpeeds = new float[speedStrings.length]; + customPlaybackSpeeds = new float[speedStrings.length]; for (int i = 0, length = speedStrings.length; i < length; i++) { final float speed = Float.parseFloat(speedStrings[i]); - if (speed <= 0 || arrayContains(customVideoSpeeds, speed)) { + if (speed <= 0 || arrayContains(customPlaybackSpeeds, speed)) { throw new IllegalArgumentException(); } if (speed >= MAXIMUM_PLAYBACK_SPEED) { @@ -72,13 +72,13 @@ private static void loadCustomSpeeds() { loadCustomSpeeds(); return; } - minVideoSpeed = Math.min(minVideoSpeed, speed); - maxVideoSpeed = Math.max(maxVideoSpeed, speed); - customVideoSpeeds[i] = speed; + minPlaybackSpeed = Math.min(minPlaybackSpeed, speed); + maxPlaybackSpeed = Math.max(maxPlaybackSpeed, speed); + customPlaybackSpeeds[i] = speed; } } catch (Exception ex) { LogHelper.printInfo(() -> "parse error", ex); - resetCustomSpeeds("Invalid custom video speeds. Using default values."); + resetCustomSpeeds("Invalid custom playback speeds. Using default values."); loadCustomSpeeds(); } } @@ -95,10 +95,10 @@ private static boolean arrayContains(float[] array, float value) { */ public static void initializeListPreference(ListPreference preference) { if (preferenceListEntries == null) { - preferenceListEntries = new String[customVideoSpeeds.length]; - preferenceListEntryValues = new String[customVideoSpeeds.length]; + preferenceListEntries = new String[customPlaybackSpeeds.length]; + preferenceListEntryValues = new String[customPlaybackSpeeds.length]; int i = 0; - for (float speed : customVideoSpeeds) { + for (float speed : customPlaybackSpeeds) { String speedString = String.valueOf(speed); preferenceListEntries[i] = speedString + "x"; preferenceListEntryValues[i] = speedString; @@ -115,14 +115,14 @@ public static void initializeListPreference(ListPreference preference) { public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { // The playback rate menu is a RecyclerView with 2 children. The third child is the "Advanced" quality menu. addRecyclerListener(linearLayout, 2, 1, recyclerView -> { - if (VideoSpeedMenuFilterPatch.isVideoSpeedMenuVisible && + if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible && recyclerView.getChildCount() == 1 && recyclerView.getChildAt(0) instanceof ComponentHost ) { linearLayout.setVisibility(View.GONE); - // Close the new video speed menu and instead show the old one. - showOldVideoSpeedMenu(); + // Close the new Playback speed menu and instead show the old one. + showOldPlaybackSpeedMenu(); // DismissView [R.id.touch_outside] is the 1st ChildView of the 3rd ParentView. ((ViewGroup) linearLayout.getParent().getParent().getParent()) @@ -131,7 +131,7 @@ public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { }); } - public static void showOldVideoSpeedMenu() { + public static void showOldPlaybackSpeedMenu() { LogHelper.printDebug(() -> "Old video quality menu shown"); // Rest of the implementation added by patch. diff --git a/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java b/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java index 50d4a725b0..f90f98da2e 100644 --- a/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java +++ b/integrations/java/app/revanced/integrations/settingsmenu/ReVancedSettingsFragment.java @@ -24,7 +24,7 @@ import com.google.android.apps.youtube.app.application.Shell_HomeActivity; -import app.revanced.integrations.patches.playback.speed.CustomVideoSpeedPatch; +import app.revanced.integrations.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.settings.SharedPrefCategory; import app.revanced.integrations.utils.LogHelper; @@ -135,7 +135,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { // if the preference was included, then initialize it based on the available playback speed Preference defaultSpeedPreference = findPreference(SettingsEnum.PLAYBACK_SPEED_DEFAULT.path); if (defaultSpeedPreference instanceof ListPreference) { - CustomVideoSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); + CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); } // Set current value from SettingsEnum From 0aa9ee87153fee83e80120be06ad62046c97f665 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 16 Jul 2023 02:24:40 +0200 Subject: [PATCH 4/7] feat(YouTube - Hide ads): hide new type of buttoned ad --- .../app/revanced/integrations/patches/components/AdsFilter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/integrations/java/app/revanced/integrations/patches/components/AdsFilter.java b/integrations/java/app/revanced/integrations/patches/components/AdsFilter.java index a16ea57f84..4e1bdfd871 100644 --- a/integrations/java/app/revanced/integrations/patches/components/AdsFilter.java +++ b/integrations/java/app/revanced/integrations/patches/components/AdsFilter.java @@ -23,6 +23,7 @@ public AdsFilter() { "_buttoned_layout", "full_width_square_image_layout", "_ad_with", + "text_image_button_group_layout", "video_display_button_group_layout", "landscape_image_wide_button_layout" ); From 84029d1c282f21cc220ad2ead6ef18abd7055414 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 16 Jul 2023 20:39:51 +0400 Subject: [PATCH 5/7] fix(youtube/return-youtube-dislike): fix dislikes not showing in some situations (#439) --- .../patches/ReturnYouTubeDislikePatch.java | 10 ++++++++-- .../returnyoutubedislike/ReturnYouTubeDislike.java | 4 ++-- .../app/revanced/integrations/shared/PlayerType.kt | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/integrations/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/integrations/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index 21014e7f46..a3d2fc3314 100644 --- a/integrations/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/integrations/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -202,7 +202,13 @@ private static void clearRemovedShortsTextViews() { */ public static boolean setShortsDislikes(@NonNull View likeDislikeView) { try { - if (!SettingsEnum.RYD_ENABLED.getBoolean() || !SettingsEnum.RYD_SHORTS.getBoolean()) { + if (!SettingsEnum.RYD_ENABLED.getBoolean()) { + return false; + } + if (!SettingsEnum.RYD_SHORTS.getBoolean()) { + // Must clear the data here, in case a new video was loaded while PlayerType + // suggested the video was not a short (can happen when spoofing to an old app version). + ReturnYouTubeDislike.setCurrentVideoId(null); return false; } LogHelper.printDebug(() -> "setShortsDislikes"); @@ -302,7 +308,7 @@ public static void newVideoLoaded(@NonNull String videoId) { if (!videoId.equals(currentVideoId)) { currentVideoId = videoId; - final boolean noneHiddenOrMinimized = PlayerType.getCurrent().isNoneHiddenOrMinimized(); + final boolean noneHiddenOrMinimized = PlayerType.getCurrent().isNoneOrHidden(); if (noneHiddenOrMinimized && !SettingsEnum.RYD_SHORTS.getBoolean()) { ReturnYouTubeDislike.setCurrentVideoId(null); return; diff --git a/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java b/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java index fc577f5354..7fcd9d0f3b 100644 --- a/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/integrations/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java @@ -255,7 +255,7 @@ public static void newVideoLoaded(@NonNull String videoId) { // If a Short is opened while a regular video is on screen, this will incorrectly set this as false. // But this check is needed to fix unusual situations of opening/closing the app // while both a regular video and a short are on screen. - dislikeDataIsShort = currentPlayerType.isNoneHiddenOrMinimized(); + dislikeDataIsShort = currentPlayerType.isNoneOrHidden(); RYDCachedFetch entry = futureCache.get(videoId); if (entry != null && entry.futureInProgressOrFinishedSuccessfully()) { @@ -371,7 +371,7 @@ public static void sendVote(@NonNull Vote vote) { // Must make a local copy of videoId, since it may change between now and when the vote thread runs. String videoIdToVoteFor = getCurrentVideoId(); if (videoIdToVoteFor == null || - (SettingsEnum.RYD_SHORTS.getBoolean() && dislikeDataIsShort != PlayerType.getCurrent().isNoneHiddenOrMinimized())) { + (SettingsEnum.RYD_SHORTS.getBoolean() && dislikeDataIsShort != PlayerType.getCurrent().isNoneOrHidden())) { // User enabled RYD after starting playback of a video. // Or shorts was loaded with regular video present, then shorts was closed, // and then user voted on the now visible original video. diff --git a/integrations/java/app/revanced/integrations/shared/PlayerType.kt b/integrations/java/app/revanced/integrations/shared/PlayerType.kt index 0fd89bfcaf..a8dec9ccec 100644 --- a/integrations/java/app/revanced/integrations/shared/PlayerType.kt +++ b/integrations/java/app/revanced/integrations/shared/PlayerType.kt @@ -18,7 +18,7 @@ enum class PlayerType { HIDDEN, /** * When spoofing to 16.x YouTube and watching a short with a regular video in the background, - * the type will be this (and not [HIDDEN]). + * the type can be this (and not [HIDDEN]). */ WATCH_WHILE_MINIMIZED, WATCH_WHILE_MAXIMIZED, From cc5c759a63f9352ccfc553d8e67d0b7b35fcc369 Mon Sep 17 00:00:00 2001 From: Vu Hoan Huy <43563783+d4rkk3y@users.noreply.github.com> Date: Thu, 20 Jul 2023 06:14:10 +0700 Subject: [PATCH 6/7] fix(Tiktok - Settings): bump compatibility (#440) Co-authored-by: oSumAtrIX --- .../tiktok/settingsmenu/SettingsMenu.java | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/integrations/java/app/revanced/tiktok/settingsmenu/SettingsMenu.java b/integrations/java/app/revanced/tiktok/settingsmenu/SettingsMenu.java index 7449ed8ad1..f79d16b714 100644 --- a/integrations/java/app/revanced/tiktok/settingsmenu/SettingsMenu.java +++ b/integrations/java/app/revanced/tiktok/settingsmenu/SettingsMenu.java @@ -6,36 +6,65 @@ import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; - -import com.bytedance.ies.ugc.aweme.commercialize.compliance.personalization.AdPersonalizationActivity; - import app.revanced.tiktok.utils.LogHelper; import app.revanced.tiktok.utils.ReVancedUtils; +import com.bytedance.ies.ugc.aweme.commercialize.compliance.personalization.AdPersonalizationActivity; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; public class SettingsMenu { - public static void initializeSettings(AdPersonalizationActivity base) { + public static Object createSettingsEntry(String entryClazzName, String entryInfoClazzName) { + try { + Class entryClazz = Class.forName(entryClazzName); + Class entryInfoClazz = Class.forName(entryInfoClazzName); + Constructor entryConstructor = entryClazz.getConstructor(entryInfoClazz); + Constructor entryInfoConstructor = entryInfoClazz.getDeclaredConstructors()[0]; + Object buttonInfo = entryInfoConstructor.newInstance("Revanced settings", null, (View.OnClickListener) view -> startSettingsActivity()); + return entryConstructor.newInstance(buttonInfo); + } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | + InstantiationException e) { + throw new RuntimeException(e); + } + } + + /*** + * Initialize the settings menu. + * @param base The activity to initialize the settings menu on. + * @return Whether the settings menu should be initialized. + */ + public static boolean initializeSettings(AdPersonalizationActivity base) { + if (!base.getIntent().getExtras().getBoolean("revanced", false)) return false; + SettingsStatus.load(); + LinearLayout linearLayout = new LinearLayout(base); linearLayout.setLayoutParams(new LinearLayout.LayoutParams(-1, -1)); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setFitsSystemWindows(true); linearLayout.setTransitionGroup(true); + FrameLayout fragment = new FrameLayout(base); fragment.setLayoutParams(new FrameLayout.LayoutParams(-1, -1)); int fragmentId = View.generateViewId(); fragment.setId(fragmentId); + linearLayout.addView(fragment); base.setContentView(linearLayout); + PreferenceFragment preferenceFragment = new ReVancedSettingsFragment(); base.getFragmentManager().beginTransaction().replace(fragmentId, preferenceFragment).commit(); + + return true; } - public static void startSettingsActivity() { + private static void startSettingsActivity() { Context appContext = ReVancedUtils.getAppContext(); if (appContext != null) { Intent intent = new Intent(appContext, AdPersonalizationActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("revanced", true); appContext.startActivity(intent); } else { LogHelper.debug(SettingsMenu.class, "ReVancedUtils.getAppContext() return null"); From 0582d7b22190630ce400bab9877723c8cd1307eb Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 20 Jul 2023 03:17:18 +0400 Subject: [PATCH 7/7] fix(YouTube - Spoof client): show video time and chapters while using seekbar (#435) --- .../SpoofSignatureVerificationPatch.java | 25 +++++++++++++++++++ .../integrations/settings/SettingsEnum.java | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java b/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java index 899d7b6db1..37c7a51dfa 100644 --- a/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java +++ b/integrations/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java @@ -2,6 +2,10 @@ import static app.revanced.integrations.utils.ReVancedUtils.containsAny; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.shared.PlayerType; import app.revanced.integrations.utils.LogHelper; @@ -67,4 +71,25 @@ public static String overrideProtobufParameter(String originalValue) { return originalValue; } + /** + * Injection point. + */ + public static boolean getSeekbarThumbnailOverrideValue() { + return SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean(); + } + + /** + * Injection point. + * + * @param view seekbar thumbnail view. Includes both shorts and regular videos. + */ + public static void seekbarImageViewCreated(ImageView view) { + if (SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { + view.setVisibility(View.GONE); + // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). + ViewGroup parentLayout = (ViewGroup) view.getParent(); + parentLayout.setPadding(0, 0, 0, 0); + } + } + } diff --git a/integrations/java/app/revanced/integrations/settings/SettingsEnum.java b/integrations/java/app/revanced/integrations/settings/SettingsEnum.java index 10fb1ea586..3e7097d938 100644 --- a/integrations/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/integrations/java/app/revanced/integrations/settings/SettingsEnum.java @@ -152,7 +152,8 @@ 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), - SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, "revanced_spoof_signature_verification_user_dialog_message"), + SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, true, + "revanced_spoof_signature_verification_user_dialog_message"), // Swipe controls SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE),