diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/MiniplayerPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/MiniplayerPatch.java index 615d27e10..6476683b3 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/MiniplayerPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/MiniplayerPatch.java @@ -1,15 +1,17 @@ package app.revanced.extension.youtube.patches.general; import static app.revanced.extension.shared.utils.StringRef.str; +import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.DEFAULT; import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.DISABLED; import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_1; import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_2; import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_3; -import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.ORIGINAL; +import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_4; import static app.revanced.extension.youtube.utils.ExtendedUtils.IS_19_20_OR_GREATER; import static app.revanced.extension.youtube.utils.ExtendedUtils.IS_19_21_OR_GREATER; import static app.revanced.extension.youtube.utils.ExtendedUtils.IS_19_26_OR_GREATER; import static app.revanced.extension.youtube.utils.ExtendedUtils.IS_19_29_OR_GREATER; +import static app.revanced.extension.youtube.utils.ExtendedUtils.IS_19_34_OR_GREATER; import static app.revanced.extension.youtube.utils.ExtendedUtils.validateValue; import android.content.Context; @@ -27,7 +29,6 @@ import app.revanced.extension.shared.utils.Logger; import app.revanced.extension.shared.utils.ResourceUtils; import app.revanced.extension.shared.utils.Utils; import app.revanced.extension.youtube.settings.Settings; -import app.revanced.extension.youtube.utils.ExtendedUtils; @SuppressWarnings({"unused", "SpellCheckingInspection"}) public final class MiniplayerPatch { @@ -44,7 +45,7 @@ public final class MiniplayerPatch { /** * Unmodified type, and same as un-patched. */ - ORIGINAL(null, null), + DEFAULT(null, null), /** * Exactly the same as MINIMAL and only here for migration of user settings. * Eventually this should be deleted. @@ -57,10 +58,13 @@ public final class MiniplayerPatch { MODERN_2(null, 2), MODERN_3(null, 3), /** - * Half broken miniplayer, that might be work in progress or left over abandoned code. - * Can force this type by editing the import/export settings. + * Works and is functional with 20.03+ */ - MODERN_4(null, 4); + MODERN_4(null, 4), + /** + * Half broken miniplayer, and in 20.02 and earlier is declared as type 4. + */ + MODERN_5(null, 5); /** * Legacy tablet hook value. @@ -157,20 +161,21 @@ public final class MiniplayerPatch { private static final boolean DRAG_AND_DROP_ENABLED = CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DRAG_AND_DROP.get(); - private static final boolean HIDE_EXPAND_CLOSE_ENABLED = - Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.get() - && Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.isAvailable(); + private static final boolean HIDE_OVERLAY_BUTTONS_ENABLED = + Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.get() + && Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.isAvailable(); private static final boolean HIDE_SUBTEXT_ENABLED = - (CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3) && Settings.MINIPLAYER_HIDE_SUBTEXT.get(); + (CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3 || CURRENT_TYPE == MODERN_4) + && Settings.MINIPLAYER_HIDE_SUBTEXT.get(); // 19.25 is last version that has forward/back buttons for phones, // but buttons still show for tablets/foldable devices and they don't work well so always hide. private static final boolean HIDE_REWIND_FORWARD_ENABLED = CURRENT_TYPE == MODERN_1 - && (ExtendedUtils.IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get()); + && (IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get()); private static final boolean MINIPLAYER_ROUNDED_CORNERS_ENABLED = - Settings.MINIPLAYER_ROUNDED_CORNERS.get(); + CURRENT_TYPE.isModern() && Settings.MINIPLAYER_ROUNDED_CORNERS.get(); private static final boolean MINIPLAYER_HORIZONTAL_DRAG_ENABLED = DRAG_AND_DROP_ENABLED && Settings.MINIPLAYER_HORIZONTAL_DRAG.get(); @@ -202,11 +207,12 @@ public final class MiniplayerPatch { } } - public static final class MiniplayerHideExpandCloseAvailability implements Setting.Availability { + public static final class MiniplayerHideOverlayButtonsAvailability implements Setting.Availability { @Override public boolean isAvailable() { MiniplayerType type = Settings.MINIPLAYER_TYPE.get(); - return (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3)) + return type == MODERN_4 + || (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3)) || (!IS_19_26_OR_GREATER && type == MODERN_1 && !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && !Settings.MINIPLAYER_DRAG_AND_DROP.get()) || (IS_19_29_OR_GREATER && type == MODERN_3); @@ -220,7 +226,7 @@ public final class MiniplayerPatch { * effectively disabling the miniplayer. */ public static boolean getMiniplayerOnCloseHandler(boolean original) { - return CURRENT_TYPE == ORIGINAL + return CURRENT_TYPE == DEFAULT ? original : CURRENT_TYPE == DISABLED; } @@ -239,7 +245,7 @@ public final class MiniplayerPatch { * Injection point. */ public static boolean getModernMiniplayerOverride(boolean original) { - return CURRENT_TYPE == ORIGINAL + return CURRENT_TYPE == DEFAULT ? original : CURRENT_TYPE.isModern(); } @@ -257,9 +263,13 @@ public final class MiniplayerPatch { /** * Injection point. */ - public static void adjustMiniplayerOpacity(ImageView view) { + public static void adjustMiniplayerOpacity(View view) { if (CURRENT_TYPE == MODERN_1) { - view.setImageAlpha(OPACITY_LEVEL); + if (view instanceof ImageView imageView) { + imageView.setImageAlpha(OPACITY_LEVEL); + } else { + Logger.printException(() -> "Unknown miniplayer overlay view. viewType: " + view.getClass().getName()); + } } } @@ -267,7 +277,7 @@ public final class MiniplayerPatch { * Injection point. */ public static boolean getModernFeatureFlagsActiveOverride(boolean original) { - if (CURRENT_TYPE == ORIGINAL) { + if (CURRENT_TYPE == DEFAULT) { return original; } @@ -277,8 +287,8 @@ public final class MiniplayerPatch { /** * Injection point. */ - public static boolean enableMiniplayerDoubleTapAction(boolean original) { - if (CURRENT_TYPE == ORIGINAL) { + public static boolean getMiniplayerDoubleTapAction(boolean original) { + if (CURRENT_TYPE == DEFAULT) { return original; } @@ -288,8 +298,8 @@ public final class MiniplayerPatch { /** * Injection point. */ - public static boolean enableMiniplayerDragAndDrop(boolean original) { - if (CURRENT_TYPE == ORIGINAL) { + public static boolean getMiniplayerDragAndDrop(boolean original) { + if (CURRENT_TYPE == DEFAULT) { return original; } @@ -300,9 +310,33 @@ public final class MiniplayerPatch { /** * Injection point. */ - public static boolean setRoundedCorners(boolean original) { - if (CURRENT_TYPE.isModern()) { - return MINIPLAYER_ROUNDED_CORNERS_ENABLED; + public static boolean getRoundedCorners(boolean original) { + if (CURRENT_TYPE == DEFAULT) { + return original; + } + + return MINIPLAYER_ROUNDED_CORNERS_ENABLED; + } + + /** + * Injection point. + */ + public static boolean getHorizontalDrag(boolean original) { + if (CURRENT_TYPE == DEFAULT) { + return original; + } + + return MINIPLAYER_HORIZONTAL_DRAG_ENABLED; + } + + /** + * Injection point. + */ + public static boolean getMaximizeAnimation(boolean original) { + // This must be forced on if horizontal drag is enabled, + // otherwise the UI has visual glitches when maximizing the miniplayer. + if (MINIPLAYER_HORIZONTAL_DRAG_ENABLED) { + return true; } return original; @@ -311,7 +345,7 @@ public final class MiniplayerPatch { /** * Injection point. */ - public static int setMiniplayerDefaultSize(int original) { + public static int getMiniplayerDefaultSize(int original) { if (CURRENT_TYPE.isModern()) { if (MINIPLAYER_SIZE == 0) { setMiniPlayerSize(); @@ -324,29 +358,26 @@ public final class MiniplayerPatch { return original; } + /** + * Injection point. + */ + public static void hideMiniplayerExpandClose(View view) { + Utils.hideViewByRemovingFromParentUnderCondition(HIDE_OVERLAY_BUTTONS_ENABLED, view); + } /** * Injection point. */ - public static boolean setHorizontalDrag(boolean original) { - if (CURRENT_TYPE.isModern()) { - return MINIPLAYER_HORIZONTAL_DRAG_ENABLED; + public static void hideMiniplayerActionButton(View view) { + if (CURRENT_TYPE == MODERN_4) { + Utils.hideViewByRemovingFromParentUnderCondition(HIDE_OVERLAY_BUTTONS_ENABLED, view); } - - return original; } /** * Injection point. */ - public static void hideMiniplayerExpandClose(ImageView view) { - Utils.hideViewByRemovingFromParentUnderCondition(HIDE_EXPAND_CLOSE_ENABLED, view); - } - - /** - * Injection point. - */ - public static void hideMiniplayerRewindForward(ImageView view) { + public static void hideMiniplayerRewindForward(View view) { Utils.hideViewByRemovingFromParentUnderCondition(HIDE_REWIND_FORWARD_ENABLED, view); } diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java index e05f77cc1..a13257adf 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -170,13 +170,13 @@ public class Settings extends BaseSettings { public static final StringSetting CUSTOM_FILTER_STRINGS = new StringSetting("revanced_custom_filter_strings", "", true, parent(CUSTOM_FILTER)); // PreferenceScreen: General - Miniplayer - public static final EnumSetting MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.ORIGINAL, true); + public static final EnumSetting MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.DEFAULT, true); private static final Setting.Availability MINIPLAYER_ANY_MODERN = MINIPLAYER_TYPE.availability(MODERN_1, MODERN_2, MODERN_3, MODERN_4); public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_drag_and_drop", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_horizontal_drag", FALSE, true, new MiniplayerPatch.MiniplayerHorizontalDragAvailability()); - public static final BooleanSetting MINIPLAYER_HIDE_EXPAND_CLOSE = new BooleanSetting("revanced_miniplayer_hide_expand_close", FALSE, true, new MiniplayerPatch.MiniplayerHideExpandCloseAvailability()); - public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3)); + public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability()); + public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3, MODERN_4)); public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, MINIPLAYER_TYPE.availability(MODERN_1)); public static final BooleanSetting MINIPLAYER_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_rounded_corners", TRUE, true, MINIPLAYER_ANY_MODERN); public static final IntegerSetting MINIPLAYER_WIDTH_DIP = new IntegerSetting("revanced_miniplayer_width_dip", 192, true, MINIPLAYER_ANY_MODERN); diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedSettingsPreference.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedSettingsPreference.java index a3987e7b9..43ee95719 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedSettingsPreference.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedSettingsPreference.java @@ -2,8 +2,6 @@ package app.revanced.extension.youtube.settings.preference; import static app.revanced.extension.shared.utils.StringRef.str; import static app.revanced.extension.shared.utils.Utils.isSDKAbove; -import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_1; -import static app.revanced.extension.youtube.patches.general.MiniplayerPatch.MiniplayerType.MODERN_3; import static app.revanced.extension.youtube.utils.ExtendedUtils.isSpoofingToLessThan; import android.preference.Preference; @@ -11,7 +9,6 @@ import android.preference.SwitchPreference; import app.revanced.extension.shared.settings.Setting; import app.revanced.extension.youtube.patches.general.LayoutSwitchPatch; -import app.revanced.extension.youtube.patches.general.MiniplayerPatch; import app.revanced.extension.youtube.patches.utils.PatchStatus; import app.revanced.extension.youtube.patches.utils.ReturnYouTubeDislikePatch; import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike; @@ -48,7 +45,6 @@ public class ReVancedSettingsPreference extends ReVancedPreferenceFragment { AmbientModePreferenceLinks(); ExternalDownloaderPreferenceLinks(); FullScreenPanelPreferenceLinks(); - MiniPlayerPreferenceLinks(); NavigationPreferenceLinks(); RYDPreferenceLinks(); SeekBarPreferenceLinks(); @@ -140,22 +136,6 @@ public class ReVancedSettingsPreference extends ReVancedPreferenceFragment { ); } - /** - * Enable/Disable Preference related to Miniplayer settings - */ - private static void MiniPlayerPreferenceLinks() { - final MiniplayerPatch.MiniplayerType CURRENT_TYPE = Settings.MINIPLAYER_TYPE.get(); - final boolean available = - (CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3) && - !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && - !Settings.MINIPLAYER_DRAG_AND_DROP.get(); - - enableDisablePreferences( - !available, - Settings.MINIPLAYER_HIDE_EXPAND_CLOSE - ); - } - /** * Enable/Disable Preference related to Navigation settings */ diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/Fingerprints.kt index 304c4d0f9..bf4d6c797 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/Fingerprints.kt @@ -7,6 +7,7 @@ import app.revanced.patches.youtube.utils.resourceid.miniplayerMaxSize import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerClose import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerExpand import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerForwardButton +import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerOverlayActionButton import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerRewindButton import app.revanced.patches.youtube.utils.resourceid.scrimOverlay import app.revanced.patches.youtube.utils.resourceid.ytOutlinePictureInPictureWhite @@ -15,6 +16,8 @@ import app.revanced.util.or import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +// region legacy miniplayer + internal val miniplayerDimensionsCalculatorParentFingerprint = legacyFingerprint( name = "miniplayerDimensionsCalculatorParentFingerprint", returnType = "V", @@ -23,6 +26,68 @@ internal val miniplayerDimensionsCalculatorParentFingerprint = legacyFingerprint literals = listOf(floatyBarTopMargin), ) +/** + * Matches using the class found in [miniplayerDimensionsCalculatorParentFingerprint]. + */ +internal val miniplayerOverrideNoContextFingerprint = legacyFingerprint( + name = "miniplayerOverrideNoContextFingerprint", + accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, + returnType = "Z", + opcodes = listOf(Opcode.IGET_BOOLEAN), // anchor to insert the instruction +) + +internal val miniplayerOverrideFingerprint = legacyFingerprint( + name = "miniplayerOverrideFingerprint", + returnType = "L", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + strings = listOf("appName") +) + +internal val miniplayerResponseModelSizeCheckFingerprint = legacyFingerprint( + name = "miniplayerResponseModelSizeCheckFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "L", + parameters = listOf("Ljava/lang/Object;", "Ljava/lang/Object;"), + opcodes = listOf( + Opcode.RETURN_OBJECT, + Opcode.CHECK_CAST, + Opcode.CHECK_CAST, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + ) +) + +// endregion + +// region modern miniplayer + +internal const val MINIPLAYER_MODERN_FEATURE_KEY = 45622882L +// In later targets this feature flag does nothing and is dead code. +internal const val MINIPLAYER_MODERN_FEATURE_LEGACY_KEY = 45630429L +internal const val MINIPLAYER_DOUBLE_TAP_FEATURE_KEY = 45628823L +internal const val MINIPLAYER_DRAG_DROP_FEATURE_KEY = 45628752L +internal const val MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY = 45658112L +internal const val MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY = 45652224L +internal const val MINIPLAYER_INITIAL_SIZE_FEATURE_KEY = 45640023L +internal const val MINIPLAYER_DISABLED_FEATURE_KEY = 45657015L +internal const val MINIPLAYER_ANIMATED_EXPAND_FEATURE_KEY = 45644360L + +internal val miniplayerModernConstructorFingerprint = legacyFingerprint( + name = "miniplayerModernConstructorFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, + parameters = listOf("L"), + literals = listOf(45623000L), +) + +internal val miniplayerModernViewParentFingerprint = legacyFingerprint( + name = "miniplayerModernViewParentFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "Ljava/lang/String;", + parameters = listOf(), + strings = listOf("player_overlay_modern_mini_player_controls") +) + /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ @@ -38,43 +103,18 @@ internal val miniplayerModernAddViewListenerFingerprint = legacyFingerprint( */ internal val miniplayerModernCloseButtonFingerprint = legacyFingerprint( name = "miniplayerModernCloseButtonFingerprint", - returnType = "Landroid/widget/ImageView;", + returnType = "L", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), literals = listOf(modernMiniPlayerClose), ) -internal const val MINIPLAYER_MODERN_FEATURE_KEY = 45622882L - -// In later targets this feature flag does nothing and is dead code. -internal const val MINIPLAYER_MODERN_FEATURE_LEGACY_KEY = 45630429L -internal const val MINIPLAYER_DOUBLE_TAP_FEATURE_KEY = 45628823L -internal const val MINIPLAYER_DRAG_DROP_FEATURE_KEY = 45628752L -internal const val MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY = 45658112L -internal const val MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY = 45652224L -internal const val MINIPLAYER_INITIAL_SIZE_FEATURE_KEY = 45640023L -internal const val MINIPLAYER_DISABLED_FEATURE_KEY = 45657015L - -internal val miniplayerModernConstructorFingerprint = legacyFingerprint( - name = "miniplayerModernConstructorFingerprint", - accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - parameters = listOf("L"), - literals = listOf(45623000L), -) - -internal val miniplayerOnCloseHandlerFingerprint = legacyFingerprint( - name = "miniplayerOnCloseHandlerFingerprint", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - returnType = "Z", - literals = listOf(MINIPLAYER_DISABLED_FEATURE_KEY), -) - /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ internal val miniplayerModernExpandButtonFingerprint = legacyFingerprint( name = "miniplayerModernExpandButtonFingerprint", - returnType = "Landroid/widget/ImageView;", + returnType = "L", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), literals = listOf(modernMiniPlayerExpand), @@ -96,7 +136,7 @@ internal val miniplayerModernExpandCloseDrawablesFingerprint = legacyFingerprint */ internal val miniplayerModernForwardButtonFingerprint = legacyFingerprint( name = "miniplayerModernForwardButtonFingerprint", - returnType = "Landroid/widget/ImageView;", + returnType = "L", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), literals = listOf(modernMiniPlayerForwardButton), @@ -107,7 +147,6 @@ internal val miniplayerModernForwardButtonFingerprint = legacyFingerprint( */ internal val miniplayerModernOverlayViewFingerprint = legacyFingerprint( name = "miniplayerModernOverlayViewFingerprint", - returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), literals = listOf(scrimOverlay), @@ -118,18 +157,21 @@ internal val miniplayerModernOverlayViewFingerprint = legacyFingerprint( */ internal val miniplayerModernRewindButtonFingerprint = legacyFingerprint( name = "miniplayerModernRewindButtonFingerprint", - returnType = "Landroid/widget/ImageView;", + returnType = "L", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), literals = listOf(modernMiniPlayerRewindButton), ) -internal val miniplayerModernViewParentFingerprint = legacyFingerprint( - name = "miniplayerModernViewParentFingerprint", +/** + * Matches using the class found in [miniplayerModernViewParentFingerprint]. + */ +internal val miniplayerModernActionButtonFingerprint = legacyFingerprint( + name = "miniplayerModernActionButtonFingerprint", + returnType = "L", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - returnType = "Ljava/lang/String;", - parameters = listOf(), - strings = listOf("player_overlay_modern_mini_player_controls") + parameters = emptyList(), + literals = listOf(modernMiniPlayerOverlayActionButton), ) internal val miniplayerMinimumSizeFingerprint = legacyFingerprint( @@ -138,33 +180,11 @@ internal val miniplayerMinimumSizeFingerprint = legacyFingerprint( literals = listOf(192L, 128L, miniplayerMaxSize), ) -internal val miniplayerOverrideFingerprint = legacyFingerprint( - name = "miniplayerOverrideFingerprint", - returnType = "L", +internal val miniplayerOnCloseHandlerFingerprint = legacyFingerprint( + name = "miniplayerOnCloseHandlerFingerprint", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - strings = listOf("appName") -) - -internal val miniplayerOverrideNoContextFingerprint = legacyFingerprint( - name = "miniplayerOverrideNoContextFingerprint", - accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, returnType = "Z", - opcodes = listOf(Opcode.IGET_BOOLEAN), // anchor to insert the instruction -) - -internal val miniplayerResponseModelSizeCheckFingerprint = legacyFingerprint( - name = "miniplayerResponseModelSizeCheckFingerprint", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - returnType = "L", - parameters = listOf("Ljava/lang/Object;", "Ljava/lang/Object;"), - opcodes = listOf( - Opcode.RETURN_OBJECT, - Opcode.CHECK_CAST, - Opcode.CHECK_CAST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - ) + literals = listOf(MINIPLAYER_DISABLED_FEATURE_KEY), ) internal const val YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME = diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt index 0c9882607..80e8990e9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt @@ -11,16 +11,19 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_PATH import app.revanced.patches.youtube.utils.patch.PatchList.MINIPLAYER import app.revanced.patches.youtube.utils.playservice.is_19_15_or_greater +import app.revanced.patches.youtube.utils.playservice.is_19_17_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_23_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_25_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_26_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_29_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_36_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_43_or_greater +import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerClose import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerExpand import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerForwardButton +import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerOverlayActionButton import app.revanced.patches.youtube.utils.resourceid.modernMiniPlayerRewindButton import app.revanced.patches.youtube.utils.resourceid.scrimOverlay import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch @@ -36,6 +39,7 @@ import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.mutableClassOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.AccessFlags @@ -116,25 +120,6 @@ val miniplayerPatch = bytecodePatch( ) } - fun MutableMethod.hookInflatedView( - literalValue: Long, - hookedClassType: String, - extensionMethodName: String, - ) { - val imageViewIndex = indexOfFirstInstructionOrThrow( - indexOfFirstLiteralInstructionOrThrow(literalValue) - ) { - opcode == Opcode.CHECK_CAST && - getReference()?.type == hookedClassType - } - - val register = getInstruction(imageViewIndex).registerA - addInstruction( - imageViewIndex + 1, - "invoke-static { v$register }, $extensionMethodName" - ) - } - // Modern mini player is only present and functional in 19.15+. // Resource is not present in older versions. Using it to determine, if patching an old version. val isPatchingOldVersion = !is_19_15_or_greater @@ -212,7 +197,7 @@ val miniplayerPatch = bytecodePatch( if (is_19_23_or_greater) { miniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( MINIPLAYER_DRAG_DROP_FEATURE_KEY, - "$EXTENSION_CLASS_DESCRIPTOR->enableMiniplayerDragAndDrop(Z)Z" + "$EXTENSION_CLASS_DESCRIPTOR->getMiniplayerDragAndDrop(Z)Z" ) settingArray += "SETTINGS: MINIPLAYER_DRAG_AND_DROP" } @@ -230,7 +215,7 @@ val miniplayerPatch = bytecodePatch( miniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( MINIPLAYER_DOUBLE_TAP_FEATURE_KEY, - "$EXTENSION_CLASS_DESCRIPTOR->enableMiniplayerDoubleTapAction(Z)Z" + "$EXTENSION_CLASS_DESCRIPTOR->getMiniplayerDoubleTapAction(Z)Z" ) if (!is_19_29_or_greater) { @@ -244,13 +229,11 @@ val miniplayerPatch = bytecodePatch( MINIPLAYER_INITIAL_SIZE_FEATURE_KEY, ) val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.LONG_TO_INT) - val register = getInstruction(targetIndex).registerA addInstructions( - targetIndex + 1, - """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->setMiniplayerDefaultSize(I)I + targetIndex + 1, """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getMiniplayerDefaultSize(I)I move-result v$register """, ) @@ -270,15 +253,17 @@ val miniplayerPatch = bytecodePatch( replaceInstruction(index, "const/16 v$register, 170") } + settingArray += "SETTINGS: MINIPLAYER_OVERLAY_BUTTONS_19_26" settingArray += "SETTINGS: MINIPLAYER_WIDTH_DIP" } else { + settingArray += "SETTINGS: MINIPLAYER_OVERLAY_BUTTONS_19_25" settingArray += "SETTINGS: MINIPLAYER_REWIND_FORWARD" } if (is_19_36_or_greater) { miniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY, - "$EXTENSION_CLASS_DESCRIPTOR->setRoundedCorners(Z)Z" + "$EXTENSION_CLASS_DESCRIPTOR->getRoundedCorners(Z)Z" ) settingArray += "SETTINGS: MINIPLAYER_ROUNDED_CORNERS" @@ -292,13 +277,23 @@ val miniplayerPatch = bytecodePatch( miniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY, - "$EXTENSION_CLASS_DESCRIPTOR->setHorizontalDrag(Z)Z" + "$EXTENSION_CLASS_DESCRIPTOR->getHorizontalDrag(Z)Z" + ) + + miniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( + MINIPLAYER_ANIMATED_EXPAND_FEATURE_KEY, + "$EXTENSION_CLASS_DESCRIPTOR->getMaximizeAnimation(Z)Z" ) settingArray += "SETTINGS: MINIPLAYER_HORIZONTAL_DRAG" - settingArray += "SETTINGS: MINIPLAYER_TYPE_19_43" + } + + settingArray += if (is_20_03_or_greater) { + "SETTINGS: MINIPLAYER_TYPE_20_03" + } else if (is_19_43_or_greater) { + "SETTINGS: MINIPLAYER_TYPE_19_43" } else { - settingArray += "SETTINGS: MINIPLAYER_TYPE_19_16" + "SETTINGS: MINIPLAYER_TYPE_19_16" } // endregion @@ -339,6 +334,11 @@ val miniplayerPatch = bytecodePatch( modernMiniPlayerClose, "hideMiniplayerExpandClose" ), + Triple( + miniplayerModernActionButtonFingerprint, + modernMiniPlayerOverlayActionButton, + "hideMiniplayerActionButton" + ), Triple( miniplayerModernRewindButtonFingerprint, modernMiniPlayerRewindButton, @@ -355,11 +355,24 @@ val miniplayerPatch = bytecodePatch( "adjustMiniplayerOpacity" ) ).forEach { (fingerprint, literalValue, methodName) -> - fingerprint.methodOrThrow(miniplayerModernViewParentFingerprint).hookInflatedView( - literalValue, - "Landroid/widget/ImageView;", - "$EXTENSION_CLASS_DESCRIPTOR->$methodName(Landroid/widget/ImageView;)V" - ) + fingerprint.methodOrThrow(miniplayerModernViewParentFingerprint).apply { + val literalIndex = indexOfFirstLiteralInstructionOrThrow(literalValue) + val checkCastIndex = indexOfFirstInstruction(literalIndex) { + opcode == Opcode.CHECK_CAST && + getReference()?.type == "Landroid/widget/ImageView;" + } + val viewIndex = if (checkCastIndex >= 0) { + checkCastIndex + } else { + indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT) + } + val viewRegister = getInstruction(viewIndex).registerA + + addInstruction( + viewIndex + 1, + "invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V" + ) + } } miniplayerModernAddViewListenerFingerprint.methodOrThrow( @@ -374,39 +387,42 @@ val miniplayerPatch = bytecodePatch( // Modern 2 uses the same overlay controls as the regular video player, // and the overlay views are added at runtime. // Add a hook to the overlay class, and pass the added views to extension. + // Problem is fixed in 19.21+ // // NOTE: Modern 2 uses the same video UI as the regular player except resized to smaller. // This patch code could be used to hide other player overlays that do not use Litho. - youTubePlayerOverlaysLayoutFingerprint.matchOrThrow().let { - it.method.apply { - it.classDef.methods.add( - ImmutableMethod( - YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME, - "addView", - listOf( - ImmutableMethodParameter("Landroid/view/View;", annotations, null), - ImmutableMethodParameter("I", annotations, null), - ImmutableMethodParameter( - "Landroid/view/ViewGroup\$LayoutParams;", - annotations, - null + if (!is_19_17_or_greater) { + youTubePlayerOverlaysLayoutFingerprint.matchOrThrow().let { + it.method.apply { + it.classDef.methods.add( + ImmutableMethod( + YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME, + "addView", + listOf( + ImmutableMethodParameter("Landroid/view/View;", annotations, null), + ImmutableMethodParameter("I", annotations, null), + ImmutableMethodParameter( + "Landroid/view/ViewGroup\$LayoutParams;", + annotations, + null + ), ), - ), - "V", - AccessFlags.PUBLIC.value, - annotations, - null, - MutableMethodImplementation(4), - ).toMutable().apply { - addInstructions( - """ - invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V - invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V - return-void - """, - ) - } - ) + "V", + AccessFlags.PUBLIC.value, + annotations, + null, + MutableMethodImplementation(4), + ).toMutable().apply { + addInstructions( + """ + invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V + invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V + return-void + """, + ) + } + ) + } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt index 33098e261..a36f776ab 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt @@ -45,6 +45,8 @@ internal val nextGenWatchLayoutFingerprint = legacyFingerprint( } ) +internal const val RESTORE_SLIDE_TO_SEEK_FEATURE_FLAG = 45411329L + /** * This value restores the 'Slide to seek' behavior. * Deprecated in YouTube v19.18.41+. @@ -54,7 +56,7 @@ internal val restoreSlideToSeekBehaviorFingerprint = legacyFingerprint( returnType = "Z", parameters = emptyList(), opcodes = listOf(Opcode.MOVE_RESULT), - literals = listOf(45411329L), + literals = listOf(RESTORE_SLIDE_TO_SEEK_FEATURE_FLAG), ) internal val slideToSeekMotionEventFingerprint = legacyFingerprint( @@ -72,6 +74,8 @@ internal val slideToSeekMotionEventFingerprint = legacyFingerprint( ) ) +internal const val SPEED_OVERLAY_FEATURE_FLAG = 45411330L + /** * This value disables 'Playing at 2x speed' while holding down. * Deprecated in YouTube v19.18.41+. @@ -81,7 +85,7 @@ internal val speedOverlayFingerprint = legacyFingerprint( returnType = "Z", parameters = emptyList(), opcodes = listOf(Opcode.MOVE_RESULT), - literals = listOf(45411330L), + literals = listOf(SPEED_OVERLAY_FEATURE_FLAG), ) /** @@ -152,6 +156,13 @@ internal val filmStripOverlayPreviewFingerprint = legacyFingerprint( ) ) +internal const val FILM_STRIP_OVERLAY_V2_FEATURE_FLAG = 45420198L + +internal val filmStripOverlayConfigV2Fingerprint = legacyFingerprint( + name = "filmStripOverlayConfigV2Fingerprint", + literals = listOf(FILM_STRIP_OVERLAY_V2_FEATURE_FLAG), +) + internal val infoCardsIncognitoFingerprint = legacyFingerprint( name = "infoCardsIncognitoFingerprint", returnType = "Ljava/lang/Boolean;", diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt index 029818d01..9c2796c68 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt @@ -24,6 +24,8 @@ import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedV import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater +import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater +import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.darkBackground import app.revanced.patches.youtube.utils.resourceid.fadeDurationFast @@ -91,8 +93,8 @@ private val speedOverlayPatch = bytecodePatch( // region patch for Disable speed overlay (Enable slide to seek) mapOf( - restoreSlideToSeekBehaviorFingerprint to 45411329L, - speedOverlayFingerprint to 45411330L + restoreSlideToSeekBehaviorFingerprint to RESTORE_SLIDE_TO_SEEK_FEATURE_FLAG, + speedOverlayFingerprint to SPEED_OVERLAY_FEATURE_FLAG ).forEach { (fingerprint, literal) -> fingerprint.injectLiteralInstructionBooleanCall( literal, @@ -237,18 +239,21 @@ private val speedOverlayPatch = bytecodePatch( ) } - speedOverlayTextValueFingerprint.matchOrThrow().let { - it.method.apply { - val targetIndex = it.patternMatch!!.startIndex - val targetRegister = - getInstruction(targetIndex).registerA + // Removed in YouTube 20.03+ + if (!is_20_03_or_greater) { + speedOverlayTextValueFingerprint.matchOrThrow().let { + it.method.apply { + val targetIndex = it.patternMatch!!.startIndex + val targetRegister = + getInstruction(targetIndex).registerA - addInstructions( - targetIndex + 1, """ - invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue()D - move-result-wide v$targetRegister - """ - ) + addInstructions( + targetIndex + 1, """ + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue()D + move-result-wide v$targetRegister + """ + ) + } } } @@ -509,32 +514,42 @@ val playerComponentsPatch = bytecodePatch( fingerprint.methodOrThrow(filmStripOverlayParentFingerprint).hookFilmstripOverlay() } - youtubeControlsOverlayFingerprint.methodOrThrow().apply { - val constIndex = indexOfFirstLiteralInstructionOrThrow(fadeDurationFast) - val constRegister = getInstruction(constIndex).registerA - val insertIndex = - indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.INVOKE_VIRTUAL) + 1 - val jumpIndex = implementation!!.instructions.let { instruction -> - insertIndex + instruction.subList(insertIndex, instruction.size - 1) - .indexOfFirst { instructions -> - instructions.opcode == Opcode.GOTO || instructions.opcode == Opcode.GOTO_16 - } + // Removed in YouTube 20.05+ + if (!is_20_05_or_greater) { + youtubeControlsOverlayFingerprint.methodOrThrow().apply { + val constIndex = indexOfFirstLiteralInstructionOrThrow(fadeDurationFast) + val constRegister = getInstruction(constIndex).registerA + val insertIndex = + indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = implementation!!.instructions.let { instruction -> + insertIndex + instruction.subList(insertIndex, instruction.size - 1) + .indexOfFirst { instructions -> + instructions.opcode == Opcode.GOTO || instructions.opcode == Opcode.GOTO_16 + } + } + + val replaceInstruction = getInstruction(insertIndex) + val replaceReference = + getInstruction(insertIndex).reference + + addInstructionsWithLabels( + insertIndex + 1, getAllLiteralComponent(insertIndex, jumpIndex - 1) + """ + const v$constRegister, $fadeDurationFast + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideFilmstripOverlay()Z + move-result v${replaceInstruction.registerA} + if-nez v${replaceInstruction.registerA}, :hidden + iget-object v${replaceInstruction.registerA}, v${replaceInstruction.registerB}, $replaceReference + """, ExternalLabel("hidden", getInstruction(jumpIndex)) + ) + removeInstruction(insertIndex) } - - val replaceInstruction = getInstruction(insertIndex) - val replaceReference = - getInstruction(insertIndex).reference - - addInstructionsWithLabels( - insertIndex + 1, getAllLiteralComponent(insertIndex, jumpIndex - 1) + """ - const v$constRegister, $fadeDurationFast - invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideFilmstripOverlay()Z - move-result v${replaceInstruction.registerA} - if-nez v${replaceInstruction.registerA}, :hidden - iget-object v${replaceInstruction.registerA}, v${replaceInstruction.registerB}, $replaceReference - """, ExternalLabel("hidden", getInstruction(jumpIndex)) + } else { + // This is a new film strip overlay added to YouTube 20.05+ + // Disabling this flag is not related to the operation of the patch. + filmStripOverlayConfigV2Fingerprint.injectLiteralInstructionBooleanCall( + FILM_STRIP_OVERLAY_V2_FEATURE_FLAG, + "0x0" ) - removeInstruction(insertIndex) } // endregion @@ -571,6 +586,7 @@ val playerComponentsPatch = bytecodePatch( ) } + // Removed in YouTube 20.02+ if (!is_20_02_or_greater) { youtubeControlsOverlayFingerprint.methodOrThrow().apply { val insertIndex = diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/Fingerprints.kt index f28ffa716..22584d1ab 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/Fingerprints.kt @@ -1,7 +1,9 @@ package app.revanced.patches.youtube.player.seekbar +import app.revanced.patches.youtube.utils.resourceid.inlineTimeBarLiveSeekAbleRange import app.revanced.patches.youtube.utils.resourceid.reelTimeBarPlayedColor import app.revanced.patches.youtube.utils.resourceid.ytStaticBrandRed +import app.revanced.patches.youtube.utils.resourceid.ytTextSecondary import app.revanced.patches.youtube.utils.resourceid.ytYoutubeMagenta import app.revanced.util.containsLiteralInstruction import app.revanced.util.fingerprint.legacyFingerprint @@ -35,11 +37,18 @@ internal val playerSeekbarGradientConfigFingerprint = legacyFingerprint( literals = listOf(PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG), ) -internal val playerSeekbarHandleColorFingerprint = legacyFingerprint( - name = "playerSeekbarHandleColorFingerprint", +internal val playerSeekbarHandleColorPrimaryFingerprint = legacyFingerprint( + name = "playerSeekbarHandleColorPrimaryFingerprint", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, parameters = listOf("Landroid/content/Context;"), - literals = listOf(ytStaticBrandRed), + literals = listOf(ytTextSecondary, ytStaticBrandRed), +) + +internal val playerSeekbarHandleColorSecondaryFingerprint = legacyFingerprint( + name = "playerSeekbarHandleColorSecondaryFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, + parameters = listOf("Landroid/content/Context;"), + literals = listOf(inlineTimeBarLiveSeekAbleRange, ytStaticBrandRed), ) internal val watchHistoryMenuUseProgressDrawableFingerprint = legacyFingerprint( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt index 841804880..23bdab4dd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt @@ -265,8 +265,11 @@ val seekbarComponentsPatch = bytecodePatch( "$EXTENSION_SEEKBAR_COLOR_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z" ) - playerSeekbarHandleColorFingerprint.methodOrThrow().apply { - addColorChangeInstructions(ytStaticBrandRed, "getVideoPlayerSeekbarColorAccent") + arrayOf( + playerSeekbarHandleColorPrimaryFingerprint, + playerSeekbarHandleColorSecondaryFingerprint + ).forEach { + it.methodOrThrow().addColorChangeInstructions(ytStaticBrandRed, "getVideoPlayerSeekbarColorAccent") } // If hiding feed seekbar thumbnails, then turn off the cairo gradient // of the watch history menu items as they use the same gradient as the diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt index 89aa98555..b1387c2aa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt @@ -95,7 +95,6 @@ internal val playerButtonsResourcesFingerprint = legacyFingerprint( internal val playerButtonsVisibilityFingerprint = legacyFingerprint( name = "playerButtonsVisibilityFingerprint", returnType = "V", - accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, opcodes = listOf( Opcode.IGET_OBJECT, Opcode.IGET_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/engagement/EngagementPanelHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/engagement/EngagementPanelHookPatch.kt index e8607bd69..dd1bc5793 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/engagement/EngagementPanelHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/engagement/EngagementPanelHookPatch.kt @@ -16,6 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.util.MethodUtil +private lateinit var engagementPanelBuilderMethod: MutableMethod private lateinit var hideEngagementPanelMethod: MutableMethod private var showEngagementPanelMethods = mutableListOf() @@ -26,8 +27,10 @@ val engagementPanelHookPatch = bytecodePatch( execute { engagementPanelBuilderFingerprint.matchOrThrow().let { + engagementPanelBuilderMethod = it.method + it.classDef.methods.filter { method -> - method.indexOfEngagementPanelBuilderInstruction(it.method) >= 0 + method.indexOfEngagementPanelBuilderInstruction() >= 0 }.forEach { method -> showEngagementPanelMethods.add(method) } @@ -38,11 +41,11 @@ val engagementPanelHookPatch = bytecodePatch( } } -private fun Method.indexOfEngagementPanelBuilderInstruction(targetMethod: MutableMethod) = +private fun Method.indexOfEngagementPanelBuilderInstruction() = indexOfFirstInstructionReversed { opcode == Opcode.INVOKE_DIRECT && MethodUtil.methodSignaturesMatch( - targetMethod, + engagementPanelBuilderMethod, getReference()!! ) } @@ -50,7 +53,7 @@ private fun Method.indexOfEngagementPanelBuilderInstruction(targetMethod: Mutabl internal fun hookEngagementPanelState(classDescriptor: String) { showEngagementPanelMethods.forEach { method -> method.apply { - val index = indexOfEngagementPanelBuilderInstruction(this) + val index = indexOfEngagementPanelBuilderInstruction() val register = getInstruction(index + 1).registerA addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt index d05423dea..0015e98d5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt @@ -55,6 +55,10 @@ var is_19_49_or_greater = false private set var is_20_02_or_greater = false private set +var is_20_03_or_greater = false + private set +var is_20_05_or_greater = false + private set val versionCheckPatch = resourcePatch( description = "versionCheckPatch", @@ -95,5 +99,7 @@ val versionCheckPatch = resourcePatch( is_19_46_or_greater = 244705000 <= playStoreServicesVersion is_19_49_or_greater = 245005000 <= playStoreServicesVersion is_20_02_or_greater = 250299000 <= playStoreServicesVersion + is_20_03_or_greater = 250405000 <= playStoreServicesVersion + is_20_05_or_greater = 250605000 <= playStoreServicesVersion } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt index 6a0b3cc17..654130e91 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt @@ -115,6 +115,8 @@ var imageOnlyTab = -1L private set var inlineTimeBarColorizedBarPlayedColorDark = -1L private set +var inlineTimeBarLiveSeekAbleRange = -1L + private set var inlineTimeBarPlayedNotHighlightedColor = -1L private set var insetOverlayViewLayout = -1L @@ -135,6 +137,8 @@ var modernMiniPlayerExpand = -1L private set var modernMiniPlayerForwardButton = -1L private set +var modernMiniPlayerOverlayActionButton = -1L + private set var modernMiniPlayerRewindButton = -1L private set var musicAppDeeplinkButtonView = -1L @@ -241,6 +245,8 @@ var ytOutlineXWhite = -1L private set var ytPremiumWordMarkHeader = -1L private set +var ytTextSecondary = -1L + private set var ytStaticBrandRed = -1L private set var ytWordMarkHeader = -1L @@ -454,6 +460,10 @@ internal val sharedResourceIdPatch = resourcePatch( COLOR, "inline_time_bar_colorized_bar_played_color_dark" ] + inlineTimeBarLiveSeekAbleRange = resourceMappings[ + COLOR, + "inline_time_bar_live_seekable_range" + ] inlineTimeBarPlayedNotHighlightedColor = resourceMappings[ COLOR, "inline_time_bar_played_not_highlighted_color" @@ -494,6 +504,10 @@ internal val sharedResourceIdPatch = resourcePatch( ID, "modern_miniplayer_forward_button" ] + modernMiniPlayerOverlayActionButton = resourceMappings[ + ID, + "modern_miniplayer_overlay_action_button" + ] modernMiniPlayerRewindButton = resourceMappings[ ID, "modern_miniplayer_rewind_button" @@ -706,6 +720,10 @@ internal val sharedResourceIdPatch = resourcePatch( ATTR, "ytPremiumWordmarkHeader" ] + ytTextSecondary = resourceMappings[ + ATTR, + "ytTextSecondary", + ] ytStaticBrandRed = resourceMappings[ ATTR, "ytStaticBrandRed", diff --git a/patches/src/main/resources/youtube/settings/host/values/arrays.xml b/patches/src/main/resources/youtube/settings/host/values/arrays.xml index 777c1fc90..aea3a5f9c 100644 --- a/patches/src/main/resources/youtube/settings/host/values/arrays.xml +++ b/patches/src/main/resources/youtube/settings/host/values/arrays.xml @@ -303,6 +303,26 @@ VI ZH + + @string/revanced_miniplayer_type_entry_0 + @string/revanced_miniplayer_type_entry_1 + @string/revanced_miniplayer_type_entry_2 + @string/revanced_miniplayer_type_entry_3 + @string/revanced_miniplayer_type_entry_4 + @string/revanced_miniplayer_type_entry_5 + @string/revanced_miniplayer_type_entry_6 + @string/revanced_miniplayer_type_entry_7 + + + DISABLED + DEFAULT + MINIMAL + TABLET + MODERN_1 + MODERN_2 + MODERN_3 + MODERN_4 + @string/revanced_miniplayer_type_entry_0 @string/revanced_miniplayer_type_entry_1 @@ -314,7 +334,7 @@ DISABLED - ORIGINAL + DEFAULT MINIMAL TABLET MODERN_1 @@ -330,7 +350,7 @@ @string/revanced_miniplayer_type_entry_6 - ORIGINAL + DEFAULT MINIMAL TABLET MODERN_1 @@ -343,7 +363,7 @@ @string/revanced_miniplayer_type_entry_3 - ORIGINAL + DEFAULT MINIMAL TABLET diff --git a/patches/src/main/resources/youtube/settings/host/values/strings.xml b/patches/src/main/resources/youtube/settings/host/values/strings.xml index cf61a1fc3..a51ec0e10 100644 --- a/patches/src/main/resources/youtube/settings/host/values/strings.xml +++ b/patches/src/main/resources/youtube/settings/host/values/strings.xml @@ -539,12 +539,13 @@ To hide the Get YouTube Premium menu, you can only use Get YouTube Pre Miniplayer type Disabled - Original + Default Minimal Tablet Modern 1 Modern 2 Modern 3 + Modern 4 Enable rounded corners Corners are rounded. Corners are square. @@ -564,20 +565,20 @@ Miniplayer can be dragged to any corner of the screen." Miniplayer can be dragged off-screen to the left or right." Horizontal drag gesture disabled. - Hide close button - Close button is hidden. - Close button is shown. - Hide expand and close buttons - "Buttons are hidden. + Hide overlay buttons + Overlay buttons are hidden. + Overlay buttons are shown. + Hide expand and close buttons + "Buttons are hidden. Swipe to expand or close." - Expand and close buttons are shown. - Hide subtexts - Subtexts are hidden. - Subtexts are shown. + Expand and close buttons are shown. Hide skip forward and back buttons Skip forward and back are hidden. Skip forward and back are shown. + Hide subtexts + Subtexts are hidden. + Subtexts are shown. Initial size Initial on screen size, in pixels. Pixel size must be between %1$s and %2$s. diff --git a/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml index d758e37d7..1d9b0bfec 100644 --- a/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -171,6 +171,9 @@ + + @@ -183,18 +186,18 @@ - + - - - + + +