diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/SeekbarColorPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/SeekbarColorPatch.java index d31788832..256d19902 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/SeekbarColorPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/SeekbarColorPatch.java @@ -27,23 +27,28 @@ public class SeekbarColorPatch { private static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000; /** - * Default colors of the gradient seekbar. + * Feed default colors of the gradient seekbar. */ - private static final int[] ORIGINAL_SEEKBAR_GRADIENT_COLORS = {0xFFFF0033, 0xFFFF2791}; + private static final int[] FEED_ORIGINAL_SEEKBAR_GRADIENT_COLORS = {0xFFFF0033, 0xFFFF2791}; /** - * Default positions of the gradient seekbar. + * Feed default positions of the gradient seekbar. */ - private static final float[] ORIGINAL_SEEKBAR_GRADIENT_POSITIONS = {0.8f, 1.0f}; + private static final float[] FEED_ORIGINAL_SEEKBAR_GRADIENT_POSITIONS = {0.8f, 1.0f}; /** * Default YouTube seekbar color brightness. */ private static final float ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS; + /** + * Empty seekbar gradient, if hide seekbar in feed is enabled. + */ + private static final int[] HIDDEN_SEEKBAR_GRADIENT_COLORS = {0x00000000, 0x00000000}; + /** * If {@link Settings#ENABLE_CUSTOM_SEEKBAR_COLOR} is enabled, - * this is the color value of {@link Settings#ENABLE_CUSTOM_SEEKBAR_COLOR_VALUE}. + * this is the color value of {@link Settings#CUSTOM_SEEKBAR_COLOR_VALUE}. * Otherwise this is {@link #ORIGINAL_SEEKBAR_COLOR}. */ private static int seekbarColor = ORIGINAL_SEEKBAR_COLOR; @@ -53,6 +58,11 @@ public class SeekbarColorPatch { */ private static final float[] customSeekbarColorHSV = new float[3]; + /** + * Custom seekbar color, used for linear gradient replacements. + */ + private static final int[] customSeekbarColorInt = new int[2]; + static { float[] hsv = new float[3]; Color.colorToHSV(ORIGINAL_SEEKBAR_COLOR, hsv); @@ -61,16 +71,18 @@ public class SeekbarColorPatch { if (CUSTOM_SEEKBAR_COLOR_ENABLED) { loadCustomSeekbarColor(); } + + Arrays.fill(customSeekbarColorInt, seekbarColor); } private static void loadCustomSeekbarColor() { try { - seekbarColor = Color.parseColor(Settings.ENABLE_CUSTOM_SEEKBAR_COLOR_VALUE.get()); + seekbarColor = Color.parseColor(Settings.CUSTOM_SEEKBAR_COLOR_VALUE.get()); Color.colorToHSV(seekbarColor, customSeekbarColorHSV); } catch (Exception ex) { Utils.showToastShort(str("revanced_custom_seekbar_color_value_invalid_invalid_toast")); Utils.showToastShort(str("revanced_extended_reset_to_default_toast")); - Settings.ENABLE_CUSTOM_SEEKBAR_COLOR_VALUE.resetToDefault(); + Settings.CUSTOM_SEEKBAR_COLOR_VALUE.resetToDefault(); loadCustomSeekbarColor(); } } @@ -165,6 +177,33 @@ public class SeekbarColorPatch { return colorValue; } + /** + * Injection point. + */ + public static int[] getLinearGradient(int[] original) { + if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) { + return HIDDEN_SEEKBAR_GRADIENT_COLORS; + } + return CUSTOM_SEEKBAR_COLOR_ENABLED + ? customSeekbarColorInt + : original; + } + + private static String colorArrayToHex(int[] colors) { + final int length = colors.length; + StringBuilder builder = new StringBuilder(length * 10); + builder.append("["); + int i = 0; + for (int color : colors) { + builder.append(String.format("#%X", color)); + if (++i < length) { + builder.append(", "); + } + } + builder.append("]"); + return builder.toString(); + } + /** * Injection point. */ @@ -174,15 +213,15 @@ public class SeekbarColorPatch { if (CUSTOM_SEEKBAR_COLOR_ENABLED || hideSeekbar) { // Most litho usage of linear gradients is hooked here, // so must only change if the values are those for the seekbar. - if (Arrays.equals(ORIGINAL_SEEKBAR_GRADIENT_COLORS, colors) - && Arrays.equals(ORIGINAL_SEEKBAR_GRADIENT_POSITIONS, positions)) { + if ((Arrays.equals(FEED_ORIGINAL_SEEKBAR_GRADIENT_COLORS, colors) + && Arrays.equals(FEED_ORIGINAL_SEEKBAR_GRADIENT_POSITIONS, positions))) { Arrays.fill(colors, hideSeekbar ? 0x00000000 : seekbarColor); return; } - Logger.printDebug(() -> "Ignoring gradient colors: " + Arrays.toString(colors) + Logger.printDebug(() -> "Ignoring gradient colors: " + colorArrayToHex(colors) + " positions: " + Arrays.toString(positions)); } } 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 d59944886..d6ce2d8e3 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,6 +1,7 @@ package app.revanced.patches.youtube.player.seekbar import app.revanced.patches.youtube.utils.resourceid.reelTimeBarPlayedColor +import app.revanced.patches.youtube.utils.resourceid.ytYoutubeMagenta import app.revanced.util.containsLiteralInstruction import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.or @@ -22,6 +23,35 @@ internal val lithoLinearGradientFingerprint = legacyFingerprint( returnType = "Landroid/graphics/LinearGradient;", parameters = listOf("F", "F", "F", "F", "[I", "[F") ) + +/** + * YouTube 19.25 - 19.47 + */ +internal val playerLinearGradientLegacyFingerprint = legacyFingerprint( + name = "playerLinearGradientLegacyFingerprint", + returnType = "V", + opcodes = listOf( + Opcode.FILLED_NEW_ARRAY, + Opcode.MOVE_RESULT_OBJECT + ), + literals = listOf(ytYoutubeMagenta), +) + +/** + * YouTube 19.49+ + */ +internal val playerLinearGradientFingerprint = legacyFingerprint( + name = "playerLinearGradientFingerprint", + returnType = "Landroid/graphics/LinearGradient;", + accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, + parameters = listOf("I", "I", "I", "I", "Landroid/content/Context;", "I"), + opcodes = listOf( + Opcode.FILLED_NEW_ARRAY, + Opcode.MOVE_RESULT_OBJECT + ), + literals = listOf(ytYoutubeMagenta), +) + internal const val launchScreenLayoutTypeLotteFeatureFlag = 268507948L internal val launchScreenLayoutTypeFingerprint = 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 f3f587372..fe14c9d11 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 @@ -25,6 +25,7 @@ import app.revanced.patches.youtube.utils.playerButtonsVisibilityFingerprint import app.revanced.patches.youtube.utils.playerSeekbarColorFingerprint import app.revanced.patches.youtube.utils.playservice.is_19_25_or_greater import app.revanced.patches.youtube.utils.playservice.is_19_46_or_greater +import app.revanced.patches.youtube.utils.playservice.is_19_49_or_greater import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.inlineTimeBarColorizedBarPlayedColorDark import app.revanced.patches.youtube.utils.resourceid.inlineTimeBarPlayedNotHighlightedColor @@ -253,16 +254,35 @@ val seekbarComponentsPatch = bytecodePatch( addDrawableColorHook("$EXTENSION_SEEKBAR_COLOR_CLASS_DESCRIPTOR->getLithoColor(I)I") if (is_19_25_or_greater) { - playerSeekbarGradientConfigFingerprint.injectLiteralInstructionBooleanCall( - PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG, - "$EXTENSION_SEEKBAR_COLOR_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z" - ) - lithoLinearGradientFingerprint.methodOrThrow().addInstruction( 0, "invoke-static/range { p4 .. p5 }, $EXTENSION_SEEKBAR_COLOR_CLASS_DESCRIPTOR->setLinearGradient([I[F)V" ) + if (!is_19_49_or_greater) { + playerLinearGradientLegacyFingerprint.matchOrThrow().let { + it.method.apply { + val index = it.patternMatch!!.endIndex + val register = getInstruction(index).registerA + + addInstructions( + index + 1, + """ + invoke-static { v$register }, $EXTENSION_SEEKBAR_COLOR_CLASS_DESCRIPTOR->getLinearGradient([I)[I + move-result-object v$register + """ + ) + } + } + } else { + // TODO: add 19.49 support + playerSeekbarGradientConfigFingerprint.injectLiteralInstructionBooleanCall( + PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG, + "$EXTENSION_SEEKBAR_COLOR_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z" + ) + } + + if (!restoreOldSplashAnimationIncluded) { // Don't use the lotte splash screen layout if using custom seekbar. arrayOf( 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 d6f71edc7..d05423dea 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 @@ -51,6 +51,8 @@ var is_19_44_or_greater = false private set var is_19_46_or_greater = false private set +var is_19_49_or_greater = false + private set var is_20_02_or_greater = false private set @@ -91,6 +93,7 @@ val versionCheckPatch = resourcePatch( is_19_43_or_greater = 244405000 <= playStoreServicesVersion is_19_44_or_greater = 244505000 <= playStoreServicesVersion is_19_46_or_greater = 244705000 <= playStoreServicesVersion + is_19_49_or_greater = 245005000 <= playStoreServicesVersion is_20_02_or_greater = 250299000 <= 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 bf1b58fe0..bf423d64a 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 @@ -243,7 +243,8 @@ var ytPremiumWordMarkHeader = -1L private set var ytWordMarkHeader = -1L private set - +var ytYoutubeMagenta = -1L + private set internal val sharedResourceIdPatch = resourcePatch( description = "sharedResourceIdPatch" @@ -707,5 +708,9 @@ internal val sharedResourceIdPatch = resourcePatch( ATTR, "ytWordmarkHeader" ] + ytYoutubeMagenta = resourceMappings[ + COLOR, + "yt_youtube_magenta", + ] } } \ No newline at end of file