mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-04-30 06:34:37 +02:00
feat(YouTube): Replace with a fingerprint that supports a wider range of versions (..20.06)
This commit is contained in:
parent
08202866e7
commit
a9d25bf9c2
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.ORIGINAL, true);
|
||||
public static final EnumSetting<MiniplayerType> 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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 =
|
||||
|
@ -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<TypeReference>()?.type == hookedClassType
|
||||
}
|
||||
|
||||
val register = getInstruction<OneRegisterInstruction>(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<OneRegisterInstruction>(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<TypeReference>()?.type == "Landroid/widget/ImageView;"
|
||||
}
|
||||
val viewIndex = if (checkCastIndex >= 0) {
|
||||
checkCastIndex
|
||||
} else {
|
||||
indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||
}
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(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
|
||||
""",
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;",
|
||||
|
@ -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<OneRegisterInstruction>(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<OneRegisterInstruction>(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<OneRegisterInstruction>(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<OneRegisterInstruction>(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<TwoRegisterInstruction>(insertIndex)
|
||||
val replaceReference =
|
||||
getInstruction<ReferenceInstruction>(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<TwoRegisterInstruction>(insertIndex)
|
||||
val replaceReference =
|
||||
getInstruction<ReferenceInstruction>(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 =
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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<MutableMethod>()
|
||||
|
||||
@ -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<MethodReference>()!!
|
||||
)
|
||||
}
|
||||
@ -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<OneRegisterInstruction>(index + 1).registerA
|
||||
|
||||
addInstruction(
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -303,6 +303,26 @@
|
||||
<item>VI</item>
|
||||
<item>ZH</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_miniplayer_type_20_03_entries">
|
||||
<item>@string/revanced_miniplayer_type_entry_0</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_1</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_2</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_3</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_4</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_5</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_6</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_7</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_miniplayer_type_20_03_entry_values">
|
||||
<item>DISABLED</item>
|
||||
<item>DEFAULT</item>
|
||||
<item>MINIMAL</item>
|
||||
<item>TABLET</item>
|
||||
<item>MODERN_1</item>
|
||||
<item>MODERN_2</item>
|
||||
<item>MODERN_3</item>
|
||||
<item>MODERN_4</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_miniplayer_type_19_43_entries">
|
||||
<item>@string/revanced_miniplayer_type_entry_0</item>
|
||||
<item>@string/revanced_miniplayer_type_entry_1</item>
|
||||
@ -314,7 +334,7 @@
|
||||
</string-array>
|
||||
<string-array name="revanced_miniplayer_type_19_43_entry_values">
|
||||
<item>DISABLED</item>
|
||||
<item>ORIGINAL</item>
|
||||
<item>DEFAULT</item>
|
||||
<item>MINIMAL</item>
|
||||
<item>TABLET</item>
|
||||
<item>MODERN_1</item>
|
||||
@ -330,7 +350,7 @@
|
||||
<item>@string/revanced_miniplayer_type_entry_6</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_miniplayer_type_19_16_entry_values">
|
||||
<item>ORIGINAL</item>
|
||||
<item>DEFAULT</item>
|
||||
<item>MINIMAL</item>
|
||||
<item>TABLET</item>
|
||||
<item>MODERN_1</item>
|
||||
@ -343,7 +363,7 @@
|
||||
<item>@string/revanced_miniplayer_type_entry_3</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_miniplayer_type_19_14_entry_values">
|
||||
<item>ORIGINAL</item>
|
||||
<item>DEFAULT</item>
|
||||
<item>MINIMAL</item>
|
||||
<item>TABLET</item>
|
||||
</string-array>
|
||||
|
@ -539,12 +539,13 @@ To hide the <b>Get YouTube Premium</b> menu, you can only use <b>Get YouTube Pre
|
||||
|
||||
<string name="revanced_miniplayer_type_title">Miniplayer type</string>
|
||||
<string name="revanced_miniplayer_type_entry_0">Disabled</string>
|
||||
<string name="revanced_miniplayer_type_entry_1">Original</string>
|
||||
<string name="revanced_miniplayer_type_entry_1">Default</string>
|
||||
<string name="revanced_miniplayer_type_entry_2">Minimal</string>
|
||||
<string name="revanced_miniplayer_type_entry_3">Tablet</string>
|
||||
<string name="revanced_miniplayer_type_entry_4">Modern 1</string>
|
||||
<string name="revanced_miniplayer_type_entry_5">Modern 2</string>
|
||||
<string name="revanced_miniplayer_type_entry_6">Modern 3</string>
|
||||
<string name="revanced_miniplayer_type_entry_7">Modern 4</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_title">Enable rounded corners</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_on">Corners are rounded.</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_off">Corners are square.</string>
|
||||
@ -564,20 +565,20 @@ Miniplayer can be dragged to any corner of the screen."</string>
|
||||
|
||||
Miniplayer can be dragged off-screen to the left or right."</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">Horizontal drag gesture disabled.</string>
|
||||
<string name="revanced_miniplayer_hide_expand_close_title">Hide close button</string>
|
||||
<string name="revanced_miniplayer_hide_expand_close_summary_on">Close button is hidden.</string>
|
||||
<string name="revanced_miniplayer_hide_expand_close_summary_off">Close button is shown.</string>
|
||||
<string name="revanced_miniplayer_hide_expand_close_legacy_title">Hide expand and close buttons</string>
|
||||
<string name="revanced_miniplayer_hide_expand_close_legacy_summary_on">"Buttons are hidden.
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">Hide overlay buttons</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Overlay buttons are hidden.</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Overlay buttons are shown.</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_title">Hide expand and close buttons</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_summary_on">"Buttons are hidden.
|
||||
|
||||
Swipe to expand or close."</string>
|
||||
<string name="revanced_miniplayer_hide_expand_close_legacy_summary_off">Expand and close buttons are shown.</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_title">Hide subtexts</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_on">Subtexts are hidden.</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_off">Subtexts are shown.</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_summary_off">Expand and close buttons are shown.</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_title">Hide skip forward and back buttons</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_on">Skip forward and back are hidden.</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_off">Skip forward and back are shown.</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_title">Hide subtexts</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_on">Subtexts are hidden.</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_off">Subtexts are shown.</string>
|
||||
<string name="revanced_miniplayer_width_dip_title">Initial size</string>
|
||||
<string name="revanced_miniplayer_width_dip_summary">Initial on screen size, in pixels.</string>
|
||||
<string name="revanced_miniplayer_width_dip_invalid_toast">Pixel size must be between %1$s and %2$s.</string>
|
||||
|
@ -171,6 +171,9 @@
|
||||
<!-- SETTINGS: MINIPLAYER_TYPE_19_43
|
||||
<ListPreference android:entries="@array/revanced_miniplayer_type_19_43_entries" android:title="@string/revanced_miniplayer_type_title" android:key="revanced_miniplayer_type" android:entryValues="@array/revanced_miniplayer_type_19_43_entry_values" />SETTINGS: MINIPLAYER_TYPE_19_43 -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_TYPE_20_03
|
||||
<ListPreference android:entries="@array/revanced_miniplayer_type_20_03_entries" android:title="@string/revanced_miniplayer_type_title" android:key="revanced_miniplayer_type" android:entryValues="@array/revanced_miniplayer_type_20_03_entry_values" />SETTINGS: MINIPLAYER_TYPE_20_03 -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_DOUBLE_TAP_ACTION
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_double_tap_action_title" android:key="revanced_miniplayer_double_tap_action" android:summaryOn="@string/revanced_miniplayer_double_tap_action_summary_on" android:summaryOff="@string/revanced_miniplayer_double_tap_action_summary_off" />SETTINGS: MINIPLAYER_DOUBLE_TAP_ACTION -->
|
||||
|
||||
@ -183,18 +186,18 @@
|
||||
<!-- SETTINGS: MINIPLAYER_ROUNDED_CORNERS
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_rounded_corners_title" android:key="revanced_miniplayer_rounded_corners" android:summaryOn="@string/revanced_miniplayer_rounded_corners_summary_on" android:summaryOff="@string/revanced_miniplayer_rounded_corners_summary_off" />SETTINGS: MINIPLAYER_ROUNDED_CORNERS -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_TYPE_MODERN
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_subtext_title" android:key="revanced_miniplayer_hide_subtext" android:summaryOn="@string/revanced_miniplayer_hide_subtext_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_subtext_summary_off" />SETTINGS: MINIPLAYER_TYPE_MODERN -->
|
||||
<!-- SETTINGS: MINIPLAYER_OVERLAY_BUTTONS_19_25
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_overlay_buttons_title" android:key="revanced_miniplayer_hide_overlay_buttons" android:summaryOn="@string/revanced_miniplayer_hide_overlay_buttons_legacy_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_overlay_buttons_legacy_summary_off" />SETTINGS: MINIPLAYER_OVERLAY_BUTTONS_19_25 -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_EXPAND_CLOSE_19_25
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_expand_close_title" android:key="revanced_miniplayer_hide_expand_close" android:summaryOn="@string/revanced_miniplayer_hide_expand_close_legacy_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_expand_close_legacy_summary_off" />SETTINGS: MINIPLAYER_EXPAND_CLOSE_19_25 -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_EXPAND_CLOSE_19_26
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_expand_close_title" android:key="revanced_miniplayer_hide_expand_close" android:summaryOn="@string/revanced_miniplayer_hide_expand_close_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_expand_close_summary_off" />SETTINGS: MINIPLAYER_EXPAND_CLOSE_19_26 -->
|
||||
<!-- SETTINGS: MINIPLAYER_OVERLAY_BUTTONS_19_26
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_overlay_buttons_title" android:key="revanced_miniplayer_hide_overlay_buttons" android:summaryOn="@string/revanced_miniplayer_hide_overlay_buttons_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_overlay_buttons_summary_off" />SETTINGS: MINIPLAYER_OVERLAY_BUTTONS_19_26 -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_REWIND_FORWARD
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_rewind_forward_title" android:key="revanced_miniplayer_hide_rewind_forward" android:summaryOn="@string/revanced_miniplayer_hide_rewind_forward_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_rewind_forward_summary_off" />SETTINGS: MINIPLAYER_REWIND_FORWARD -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_TYPE_MODERN
|
||||
<SwitchPreference android:title="@string/revanced_miniplayer_hide_subtext_title" android:key="revanced_miniplayer_hide_subtext" android:summaryOn="@string/revanced_miniplayer_hide_subtext_summary_on" android:summaryOff="@string/revanced_miniplayer_hide_subtext_summary_off" />SETTINGS: MINIPLAYER_TYPE_MODERN -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_WIDTH_DIP
|
||||
<app.revanced.extension.shared.settings.preference.ResettableEditTextPreference android:title="@string/revanced_miniplayer_width_dip_title" android:key="revanced_miniplayer_width_dip" android:summary="@string/revanced_miniplayer_width_dip_summary" android:inputType="number" />SETTINGS: MINIPLAYER_WIDTH_DIP -->
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user