diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a28e7b0..c38a8700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,38 @@ +# [1.10.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0-dev.4...v1.10.0-dev.5) (2024-06-02) + + +### Features + +* **YouTube - Playback speed:** Add option to show speed dialog button in video player ([#636](https://github.com/ReVanced/revanced-integrations/issues/636)) ([59220d6](https://github.com/ReVanced/revanced-integrations/commit/59220d6e25380d5fe6cc8c75456c04d980a83f34)) + +# [1.10.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0-dev.3...v1.10.0-dev.4) (2024-06-02) + + +### Bug Fixes + +* **YouTube - Spoof client:** Restore playback speed menu when spoofing to an iOS client ([2b2a70e](https://github.com/ReVanced/revanced-integrations/commit/2b2a70e6ea02ab3d140d500860d1c70c359fe8ef)) + +# [1.10.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0-dev.2...v1.10.0-dev.3) (2024-06-01) + + +### Features + +* **YouTube:** Support version `19.12`, `19.13`, `19.14`, `19.15` and `19.16` ([#643](https://github.com/ReVanced/revanced-integrations/issues/643)) ([4dce73a](https://github.com/ReVanced/revanced-integrations/commit/4dce73a6fbfeeffb8c2b1759b9c5a5eacb1e3d4b)) + +# [1.10.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.10.0-dev.1...v1.10.0-dev.2) (2024-06-01) + + +### Bug Fixes + +* **YouTube - Spoof client:** Allow swipe gestures to enter/exit fullscreen when spoofing with `Android VR` client ([#645](https://github.com/ReVanced/revanced-integrations/issues/645)) ([b826865](https://github.com/ReVanced/revanced-integrations/commit/b826865ef40a55dc79e6e146e3c35bfe7d792886)) + +# [1.10.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.9.2...v1.10.0-dev.1) (2024-05-31) + + +### Features + +* **YouTube - Hide layout components:** Disable like / subscribe button glow animation ([#646](https://github.com/ReVanced/revanced-integrations/issues/646)) ([777ffb1](https://github.com/ReVanced/revanced-integrations/commit/777ffb13605dcedd58f22ccbedf62a12201e85cf)) + ## [1.9.2](https://github.com/ReVanced/revanced-integrations/compare/v1.9.1...v1.9.2) (2024-05-31) diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/HideAutoplayButtonPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/HideAutoplayButtonPatch.java index 79a40d64..846905c2 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/HideAutoplayButtonPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/HideAutoplayButtonPatch.java @@ -4,7 +4,13 @@ import app.revanced.integrations.youtube.settings.Settings; @SuppressWarnings("unused") public class HideAutoplayButtonPatch { - public static boolean isButtonShown() { - return !Settings.HIDE_AUTOPLAY_BUTTON.get(); + + private static final Boolean HIDE_AUTOPLAY_BUTTON_ENABLED = Settings.HIDE_AUTOPLAY_BUTTON.get(); + + /** + * Injection point. + */ + public static boolean hideAutoPlayButton() { + return HIDE_AUTOPLAY_BUTTON_ENABLED; } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java index 90ed3841..522658c5 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/LayoutComponentsFilter.java @@ -17,17 +17,24 @@ import app.revanced.integrations.youtube.shared.PlayerType; @SuppressWarnings("unused") public final class LayoutComponentsFilter extends Filter { - private final StringTrieSearch exceptions = new StringTrieSearch(); - private static final StringTrieSearch mixPlaylistsExceptions = new StringTrieSearch(); + private static final String COMPACT_CHANNEL_BAR_PATH_PREFIX = "compact_channel_bar.eml"; + private static final String VIDEO_ACTION_BAR_PATH_PREFIX = "video_action_bar.eml"; + private static final String ANIMATED_VECTOR_TYPE_PATH = "AnimatedVectorType"; + + private static final StringTrieSearch mixPlaylistsExceptions = new StringTrieSearch( + "V.ED", // Playlist browse id. + "java.lang.ref.WeakReference" + ); private static final ByteArrayFilterGroup mixPlaylistsExceptions2 = new ByteArrayFilterGroup( null, "cell_description_body" ); - private static final ByteArrayFilterGroup mixPlaylists = new ByteArrayFilterGroup( Settings.HIDE_MIX_PLAYLISTS, "&list=" ); + + private final StringTrieSearch exceptions = new StringTrieSearch(); private final StringFilterGroup searchResultShelfHeader; private final StringFilterGroup inFeedSurvey; private final StringFilterGroup notifyMe; @@ -37,15 +44,9 @@ public final class LayoutComponentsFilter extends Filter { private final StringFilterGroup compactChannelBarInner; private final StringFilterGroup compactChannelBarInnerButton; private final ByteArrayFilterGroup joinMembershipButton; + private final StringFilterGroup likeSubscribeGlow; private final StringFilterGroup horizontalShelves; - static { - mixPlaylistsExceptions.addPatterns( - "V.ED", // Playlist browse id. - "java.lang.ref.WeakReference" - ); - } - @RequiresApi(api = Build.VERSION_CODES.N) public LayoutComponentsFilter() { exceptions.addPatterns( @@ -224,6 +225,11 @@ public final class LayoutComponentsFilter extends Filter { "sponsorships" ); + likeSubscribeGlow = new StringFilterGroup( + Settings.DISABLE_LIKE_SUBSCRIBE_GLOW, + "animated_button_border.eml" + ); + final var channelWatermark = new StringFilterGroup( Settings.HIDE_VIDEO_CHANNEL_WATERMARK, "featured_channel_watermark_overlay" @@ -255,6 +261,7 @@ public final class LayoutComponentsFilter extends Filter { expandableMetadata, inFeedSurvey, notifyMe, + likeSubscribeGlow, channelBar, communityPosts, paidPromotion, @@ -293,6 +300,15 @@ public final class LayoutComponentsFilter extends Filter { return false; } + if (matchedGroup == likeSubscribeGlow) { + if ((path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX)) + && path.contains(ANIMATED_VECTOR_TYPE_PATH)) { + return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); + } + + return false; + } + // The groups are excluded from the filter due to the exceptions list below. // Filter them separately here. if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata) @@ -333,24 +349,31 @@ public final class LayoutComponentsFilter extends Filter { * Called from a different place then the other filters. */ public static boolean filterMixPlaylists(final Object conversionContext, @Nullable final byte[] bytes) { - if (bytes == null) { - Logger.printDebug(() -> "bytes is null"); - return false; + try { + if (bytes == null) { + Logger.printDebug(() -> "bytes is null"); + return false; + } + + // Prevent playlist items being hidden, if a mix playlist is present in it. + if (mixPlaylistsExceptions.matches(conversionContext.toString())) { + return false; + } + + // Prevent hiding the description of some videos accidentally. + if (mixPlaylistsExceptions2.check(bytes).isFiltered()) { + return false; + } + + if (mixPlaylists.check(bytes).isFiltered()) { + Logger.printDebug(() -> "Filtered mix playlist"); + return true; + } + } catch (Exception ex) { + Logger.printException(() -> "filterMixPlaylists failure", ex); } - // Prevent playlist items being hidden, if a mix playlist is present in it. - if (mixPlaylistsExceptions.matches(conversionContext.toString())) - return false; - - if (!mixPlaylists.check(bytes).isFiltered()) - return false; - - // Prevent hiding the description of some videos accidentally. - if (mixPlaylistsExceptions2.check(bytes).isFiltered()) - return false; - - Logger.printDebug(() -> "Filtered mix playlist"); - return true; + return false; } /** diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java index 1cc65371..42faeecf 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/playback/quality/RestoreOldVideoQualityMenuPatch.java @@ -70,8 +70,8 @@ public final class RestoreOldVideoQualityMenuPatch { * * Used to force the creation of the advanced menu item for the Shorts quality flyout. */ - public static boolean forceAdvancedVideoQualityMenuCreation() { - return Settings.RESTORE_OLD_VIDEO_QUALITY_MENU.get(); + public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) { + return Settings.RESTORE_OLD_VIDEO_QUALITY_MENU.get() || original; } /** diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java index 59d63bcb..2ca56ed3 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -159,7 +159,7 @@ public class CustomPlaybackSpeedPatch { }); } - private static void showOldPlaybackSpeedMenu() { + public static void showOldPlaybackSpeedMenu() { // This method is sometimes used multiple times. // To prevent this, ignore method reuse within 1 second. final long now = System.currentTimeMillis(); diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofClientPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofClientPatch.java index 6ce8da4f..9dc021f5 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofClientPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofClientPatch.java @@ -4,7 +4,6 @@ import android.media.MediaCodecInfo; import android.media.MediaCodecList; import android.net.Uri; import android.os.Build; - import app.revanced.integrations.shared.Logger; import app.revanced.integrations.youtube.settings.Settings; @@ -101,6 +100,13 @@ public class SpoofClientPatch { return originalClientModel; } + /** + * Injection point. + */ + public static boolean enablePlayerGesture(boolean original) { + return SPOOF_CLIENT_ENABLED || original; + } + /** * Injection point. */ @@ -108,6 +114,19 @@ public class SpoofClientPatch { return SPOOF_CLIENT_ENABLED; } + /** + * Injection point. + * When spoofing the client to iOS, the playback speed menu is missing from the player response. + * Return true to force create the playback speed menu. + */ + public static boolean forceCreatePlaybackSpeedMenu(boolean original) { + if (SPOOF_CLIENT_ENABLED && SPOOF_CLIENT_TYPE == ClientType.IOS) { + return true; + } + + return original; + } + private enum ClientType { // https://dumps.tadiphone.dev/dumps/oculus/monterey/-/blob/vr_monterey-user-7.1.1-NGI77B-256550.6810.0-release-keys/system/system/build.prop // version 1.37 is not the latest, but it works with livestream audio only playback. diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java index f82450c5..dd5eec20 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java @@ -121,11 +121,13 @@ public class Settings extends BaseSettings { // Player public static final BooleanSetting DISABLE_FULLSCREEN_AMBIENT_MODE = new BooleanSetting("revanced_disable_fullscreen_ambient_mode", TRUE, true); public static final BooleanSetting DISABLE_ROLLING_NUMBER_ANIMATIONS = new BooleanSetting("revanced_disable_rolling_number_animations", FALSE); + public static final BooleanSetting DISABLE_LIKE_SUBSCRIBE_GLOW = new BooleanSetting("revanced_disable_like_subscribe_glow", FALSE); public static final BooleanSetting HIDE_AUTOPLAY_BUTTON = new BooleanSetting("revanced_hide_autoplay_button", TRUE, true); public static final BooleanSetting HIDE_CAST_BUTTON = new BooleanSetting("revanced_hide_cast_button", TRUE, true); public static final BooleanSetting HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE); public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE); public static final BooleanSetting COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_copy_video_url_timestamp", TRUE); + public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE); // External downloader public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE); diff --git a/app/src/main/java/app/revanced/integrations/youtube/videoplayer/PlaybackSpeedDialogButton.java b/app/src/main/java/app/revanced/integrations/youtube/videoplayer/PlaybackSpeedDialogButton.java new file mode 100644 index 00000000..0acf184a --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/youtube/videoplayer/PlaybackSpeedDialogButton.java @@ -0,0 +1,43 @@ +package app.revanced.integrations.youtube.videoplayer; + +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; +import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.shared.Logger; + +public class PlaybackSpeedDialogButton extends BottomControlButton { + @Nullable + private static PlaybackSpeedDialogButton instance; + + public PlaybackSpeedDialogButton(ViewGroup viewGroup) { + super( + viewGroup, + "revanced_playback_speed_dialog_button", + Settings.PLAYBACK_SPEED_DIALOG_BUTTON, + view -> CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu(), + null + ); + } + + /** + * Injection point. + */ + public static void initializeButton(View view) { + try { + instance = new PlaybackSpeedDialogButton((ViewGroup) view); + } catch (Exception ex) { + Logger.printException(() -> "initializeButton failure", ex); + } + } + + /** + * Injection point. + */ + public static void changeVisibility(boolean showing) { + if (instance != null) instance.setVisibility(showing); + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 78b95a4e..16415b07 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 1.9.2 +version = 1.10.0-dev.5