From 2bd7b5aeedaa838e36dad4bfea0a2b02c53eb299 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Sun, 15 Dec 2024 14:34:03 +0900 Subject: [PATCH] fix(YouTube - Seekbar components): `Custom seekbar color` not applied to gradient seekbar in YouTube 19.34.42 --- .../patches/utils/DrawableColorPatch.java | 2 +- .../youtube/patches/player/PlayerPatch.java | 61 ++-- .../patches/player/SeekbarColorPatch.java | 260 ++++++++++++++++++ .../patches/utils/DrawableColorPatch.java | 2 +- .../patches/utils/ProgressBarDrawable.java | 6 +- .../music/general/amoled/AmoledPatch.kt | 2 +- .../youtube/layout/theme/SharedThemePatch.kt | 2 +- .../youtube/player/seekbar/Fingerprints.kt | 31 +++ .../player/seekbar/SeekbarComponentsPatch.kt | 175 +++++++++++- .../utils/playservice/VersionCheckPatch.kt | 3 + .../youtube/seekbar/values/attrs.xml | 4 + .../youtube/settings/host/values/strings.xml | 1 + 12 files changed, 487 insertions(+), 62 deletions(-) create mode 100644 extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/SeekbarColorPatch.java create mode 100644 patches/src/main/resources/youtube/seekbar/values/attrs.xml diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/patches/utils/DrawableColorPatch.java b/extensions/shared/src/main/java/app/revanced/extension/music/patches/utils/DrawableColorPatch.java index d72807458..ddb7b0101 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/patches/utils/DrawableColorPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/patches/utils/DrawableColorPatch.java @@ -6,7 +6,7 @@ public class DrawableColorPatch { -14606047 // comments box background }; - public static int getColor(int originalValue) { + public static int getLithoColor(int originalValue) { if (anyEquals(originalValue, DARK_VALUES)) return -16777215; diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java index deb2bb5b8..8b9c2de35 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java @@ -7,7 +7,6 @@ import static app.revanced.extension.youtube.utils.ExtendedUtils.validateValue; import android.app.Activity; import android.content.pm.ActivityInfo; -import android.graphics.Color; import android.support.v7.widget.RecyclerView; import android.util.TypedValue; import android.view.View; @@ -597,12 +596,26 @@ public class PlayerPatch { return !Settings.HIDE_PLAYER_FLYOUT_MENU_PIP.get(); } + /** + * Overriding this values is possible only after the litho component has been loaded. + * Otherwise, crash will occur. + * See {@link InitializationPatch#onCreate}. + * + * @param original original value. + * @return whether to enable Sleep timer Mode in the player flyout menu. + */ + public static boolean hideDeprecatedSleepTimerMenu(boolean original) { + if (!BaseSettings.SETTINGS_INITIALIZED.get()) { + return original; + } + + return !Settings.HIDE_PLAYER_FLYOUT_MENU_SLEEP_TIMER.get(); + } + // endregion // region [Seekbar components] patch - public static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000; - public static String appendTimeStampInformation(String original) { if (!Settings.APPEND_TIME_STAMP_INFORMATION.get()) return original; @@ -641,48 +654,6 @@ public class PlayerPatch { } } - public static int getSeekbarClickedColorValue(final int colorValue) { - return colorValue == ORIGINAL_SEEKBAR_COLOR - ? overrideSeekbarColor(colorValue) - : colorValue; - } - - public static int resumedProgressBarColor(final int colorValue) { - return Settings.ENABLE_CUSTOM_SEEKBAR_COLOR.get() - ? getSeekbarClickedColorValue(colorValue) - : colorValue; - } - - /** - * Overrides all drawable color that use the YouTube seekbar color. - * Used only for the video thumbnails seekbar. - *
- * If {@link Settings#HIDE_SEEKBAR_THUMBNAIL} is enabled, this returns a fully transparent color. - */ - public static int getColor(int colorValue) { - if (colorValue == ORIGINAL_SEEKBAR_COLOR) { - if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) { - return 0x00000000; - } - return overrideSeekbarColor(ORIGINAL_SEEKBAR_COLOR); - } - return colorValue; - } - - /** - * Points where errors occur when playing videos on the PlayStore (ROOT Build) - */ - public static int overrideSeekbarColor(final int colorValue) { - try { - return Settings.ENABLE_CUSTOM_SEEKBAR_COLOR.get() - ? Color.parseColor(Settings.ENABLE_CUSTOM_SEEKBAR_COLOR_VALUE.get()) - : colorValue; - } catch (Exception ignored) { - Settings.ENABLE_CUSTOM_SEEKBAR_COLOR_VALUE.resetToDefault(); - } - return colorValue; - } - public static boolean enableSeekbarTapping() { return Settings.ENABLE_SEEKBAR_TAPPING.get(); } 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 new file mode 100644 index 000000000..65e379851 --- /dev/null +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/SeekbarColorPatch.java @@ -0,0 +1,260 @@ +package app.revanced.extension.youtube.patches.player; + +import static app.revanced.extension.shared.utils.StringRef.str; + +import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.drawable.AnimatedVectorDrawable; + +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 java.util.Arrays; +import java.util.Locale; + +@SuppressWarnings("unused") +public class SeekbarColorPatch { + + private static final boolean CUSTOM_SEEKBAR_COLOR_ENABLED = + Settings.ENABLE_CUSTOM_SEEKBAR_COLOR.get(); + + /** + * Default color of the litho seekbar. + * Differs slightly from the default custom seekbar color setting. + */ + private static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000; + + /** + * Default colors of the gradient seekbar. + */ + private static final int[] ORIGINAL_SEEKBAR_GRADIENT_COLORS = { 0xFFFF0033, 0xFFFF2791 }; + + /** + * Default positions of the gradient seekbar. + */ + private static final float[] ORIGINAL_SEEKBAR_GRADIENT_POSITIONS = { 0.8f, 1.0f }; + + /** + * Default YouTube seekbar color brightness. + */ + private static final float ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS; + + /** + * If {@link Settings#ENABLE_CUSTOM_SEEKBAR_COLOR} is enabled, + * this is the color value of {@link Settings#ENABLE_CUSTOM_SEEKBAR_COLOR_VALUE}. + * Otherwise this is {@link #ORIGINAL_SEEKBAR_COLOR}. + */ + private static int seekbarColor = ORIGINAL_SEEKBAR_COLOR; + + /** + * Custom seekbar hue, saturation, and brightness values. + */ + private static final float[] customSeekbarColorHSV = new float[3]; + + static { + float[] hsv = new float[3]; + Color.colorToHSV(ORIGINAL_SEEKBAR_COLOR, hsv); + ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS = hsv[2]; + + if (CUSTOM_SEEKBAR_COLOR_ENABLED) { + loadCustomSeekbarColor(); + } + } + + private static void loadCustomSeekbarColor() { + try { + seekbarColor = Color.parseColor(Settings.ENABLE_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(); + loadCustomSeekbarColor(); + } + } + + public static int getSeekbarColor() { + return seekbarColor; + } + + /** + * Injection point + */ + public static boolean playerSeekbarGradientEnabled(boolean original) { + if (CUSTOM_SEEKBAR_COLOR_ENABLED) return false; + + return original; + } + + /** + * Injection point + */ + public static boolean useLotteLaunchSplashScreen(boolean original) { + Logger.printDebug(() -> "useLotteLaunchSplashScreen original: " + original); + + if (CUSTOM_SEEKBAR_COLOR_ENABLED) return false; + + return original; + } + + private static int colorChannelTo3Bits(int channel8Bits) { + final float channel3Bits = channel8Bits * 7 / 255f; + + // If a color channel is near zero, then allow rounding up so values between + // 0x12 and 0x23 will show as 0x24. But always round down when the channel is + // near full saturation, otherwise rounding to nearest will cause all values + // between 0xEC and 0xFE to always show as full saturation (0xFF). + return channel3Bits < 6 + ? Math.round(channel3Bits) + : (int) channel3Bits; + } + + private static String get9BitStyleIdentifier(int color24Bit) { + final int r3 = colorChannelTo3Bits(Color.red(color24Bit)); + final int g3 = colorChannelTo3Bits(Color.green(color24Bit)); + final int b3 = colorChannelTo3Bits(Color.blue(color24Bit)); + + return String.format(Locale.US, "splash_seekbar_color_style_%d_%d_%d", r3, g3, b3); + } + + /** + * Injection point + */ + public static void setSplashAnimationDrawableTheme(AnimatedVectorDrawable vectorDrawable) { + // Alternatively a ColorMatrixColorFilter can be used to change the color of the drawable + // without using any styles, but a color filter cannot selectively change the seekbar + // while keeping the red YT logo untouched. + // Even if the seekbar color xml value is changed to a completely different color (such as green), + // a color filter still cannot be selectively applied when the drawable has more than 1 color. + try { + String seekbarStyle = get9BitStyleIdentifier(seekbarColor); + Logger.printDebug(() -> "Using splash seekbar style: " + seekbarStyle); + + final int styleIdentifierDefault = ResourceUtils.getStyleIdentifier(seekbarStyle); + if (styleIdentifierDefault == 0) { + throw new RuntimeException("Seekbar style not found: " + seekbarStyle); + } + + Resources.Theme theme = Utils.getContext().getResources().newTheme(); + theme.applyStyle(styleIdentifierDefault, true); + + vectorDrawable.applyTheme(theme); + } catch (Exception ex) { + Logger.printException(() -> "setSplashAnimationDrawableTheme failure", ex); + } + } + + /** + * Injection point. + *
+ * Overrides all Litho components that use the YouTube seekbar color. + * Used only for the video thumbnails seekbar. + *
+ * If {@link Settings#HIDE_SEEKBAR_THUMBNAIL} is enabled, this returns a fully transparent color. + */ + public static int getLithoColor(int colorValue) { + if (colorValue == ORIGINAL_SEEKBAR_COLOR) { + if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) { + return 0x00000000; + } + + return getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR); + } + return colorValue; + } + + /** + * Injection point. + */ + public static void setLinearGradient(int[] colors, float[] positions) { + final boolean hideSeekbar = Settings.HIDE_SEEKBAR_THUMBNAIL.get(); + + 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)) { + Arrays.fill(colors, hideSeekbar + ? 0x00000000 + : seekbarColor); + return; + } + + Logger.printDebug(() -> "Ignoring gradient colors: " + Arrays.toString(colors) + + " positions: " + Arrays.toString(positions)); + } + } + + /** + * Injection point. + *
+ * Overrides color when video player seekbar is clicked. + */ + public static int getVideoPlayerSeekbarClickedColor(int colorValue) { + if (!CUSTOM_SEEKBAR_COLOR_ENABLED) { + return colorValue; + } + + return colorValue == ORIGINAL_SEEKBAR_COLOR + ? getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR) + : colorValue; + } + + /** + * Injection point. + *
+ * Overrides color used for the video player seekbar.
+ */
+ public static int getVideoPlayerSeekbarColor(int originalColor) {
+ if (!CUSTOM_SEEKBAR_COLOR_ENABLED) {
+ return originalColor;
+ }
+
+ return getSeekbarColorValue(originalColor);
+ }
+
+ /**
+ * Color parameter is changed to the custom seekbar color, while retaining
+ * the brightness and alpha changes of the parameter value compared to the original seekbar color.
+ */
+ private static int getSeekbarColorValue(int originalColor) {
+ try {
+ if (!CUSTOM_SEEKBAR_COLOR_ENABLED || originalColor == seekbarColor) {
+ return originalColor; // nothing to do
+ }
+
+ final int alphaDifference = Color.alpha(originalColor) - Color.alpha(ORIGINAL_SEEKBAR_COLOR);
+
+ // The seekbar uses the same color but different brightness for different situations.
+ float[] hsv = new float[3];
+ Color.colorToHSV(originalColor, hsv);
+ final float brightnessDifference = hsv[2] - ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS;
+
+ // Apply the brightness difference to the custom seekbar color.
+ hsv[0] = customSeekbarColorHSV[0];
+ hsv[1] = customSeekbarColorHSV[1];
+ hsv[2] = clamp(customSeekbarColorHSV[2] + brightnessDifference, 0, 1);
+
+ final int replacementAlpha = clamp(Color.alpha(seekbarColor) + alphaDifference, 0, 255);
+ final int replacementColor = Color.HSVToColor(replacementAlpha, hsv);
+ Logger.printDebug(() -> String.format("Original color: #%08X replacement color: #%08X",
+ originalColor, replacementColor));
+ return replacementColor;
+ } catch (Exception ex) {
+ Logger.printException(() -> "getSeekbarColorValue failure", ex);
+ return originalColor;
+ }
+ }
+
+ /** @noinspection SameParameterValue */
+ private static int clamp(int value, int lower, int upper) {
+ return Math.max(lower, Math.min(value, upper));
+ }
+
+ /** @noinspection SameParameterValue */
+ private static float clamp(float value, float lower, float upper) {
+ return Math.max(lower, Math.min(value, upper));
+ }
+}
diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/DrawableColorPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/DrawableColorPatch.java
index 853779b37..772dcd3e6 100644
--- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/DrawableColorPatch.java
+++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/DrawableColorPatch.java
@@ -22,7 +22,7 @@ public class DrawableColorPatch {
private static int whiteColor = 0;
private static int blackColor = 0;
- public static int getColor(int originalValue) {
+ public static int getLithoColor(int originalValue) {
if (anyEquals(originalValue, DARK_VALUES)) {
return getBlackColor();
} else if (anyEquals(originalValue, WHITE_VALUES)) {
diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/ProgressBarDrawable.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/ProgressBarDrawable.java
index 3cb20d617..b3d4543cd 100644
--- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/ProgressBarDrawable.java
+++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/utils/ProgressBarDrawable.java
@@ -1,8 +1,5 @@
package app.revanced.extension.youtube.patches.utils;
-import static app.revanced.extension.youtube.patches.player.PlayerPatch.ORIGINAL_SEEKBAR_COLOR;
-import static app.revanced.extension.youtube.patches.player.PlayerPatch.resumedProgressBarColor;
-
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
@@ -12,6 +9,7 @@ import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import app.revanced.extension.youtube.patches.player.SeekbarColorPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
@@ -24,7 +22,7 @@ public class ProgressBarDrawable extends Drawable {
if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) {
return;
}
- paint.setColor(resumedProgressBarColor(ORIGINAL_SEEKBAR_COLOR));
+ paint.setColor(SeekbarColorPatch.getSeekbarColor());
canvas.drawRect(getBounds(), paint);
}
diff --git a/patches/src/main/kotlin/app/revanced/patches/music/general/amoled/AmoledPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/general/amoled/AmoledPatch.kt
index 310578ff1..c2a79075d 100644
--- a/patches/src/main/kotlin/app/revanced/patches/music/general/amoled/AmoledPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/music/general/amoled/AmoledPatch.kt
@@ -23,7 +23,7 @@ val amoledPatch = resourcePatch(
)
execute {
- addDrawableColorHook("$UTILS_PATH/DrawableColorPatch;->getColor(I)I")
+ addDrawableColorHook("$UTILS_PATH/DrawableColorPatch;->getLithoColor(I)I")
document("res/values/colors.xml").use { document ->
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/SharedThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/SharedThemePatch.kt
index 89d7f1133..0ca1403b1 100644
--- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/SharedThemePatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/SharedThemePatch.kt
@@ -24,7 +24,7 @@ val sharedThemePatch = resourcePatch(
)
execute {
- addDrawableColorHook("$UTILS_PATH/DrawableColorPatch;->getColor(I)I")
+ addDrawableColorHook("$UTILS_PATH/DrawableColorPatch;->getLithoColor(I)I")
// edit the resource files to change the splash screen color
val attrsResourceFile = "res/values/attrs.xml"
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 34240c475..d59944886 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,11 +1,42 @@
package app.revanced.patches.youtube.player.seekbar
import app.revanced.patches.youtube.utils.resourceid.reelTimeBarPlayedColor
+import app.revanced.util.containsLiteralInstruction
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
+internal const val PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG = 45617850L
+
+internal val playerSeekbarGradientConfigFingerprint = legacyFingerprint(
+ name = "playerSeekbarGradientConfigFingerprint",
+ returnType = "Z",
+ parameters = emptyList(),
+ literals = listOf(PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG),
+)
+
+internal val lithoLinearGradientFingerprint = legacyFingerprint(
+ name = "lithoLinearGradientFingerprint",
+ accessFlags = AccessFlags.STATIC.value,
+ returnType = "Landroid/graphics/LinearGradient;",
+ parameters = listOf("F", "F", "F", "F", "[I", "[F")
+)
+internal const val launchScreenLayoutTypeLotteFeatureFlag = 268507948L
+
+internal val launchScreenLayoutTypeFingerprint = legacyFingerprint(
+ name = "launchScreenLayoutTypeFingerprint",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ returnType = "V",
+ customFingerprint = { method, _ ->
+ val firstParameter = method.parameterTypes.firstOrNull()
+ // 19.25 - 19.45
+ (firstParameter == "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
+ || firstParameter == "Landroid/app/Activity;") // 19.46+
+ && method.containsLiteralInstruction(launchScreenLayoutTypeLotteFeatureFlag)
+ }
+)
+
internal val controlsOverlayStyleFingerprint = legacyFingerprint(
name = "controlsOverlayStyleFingerprint",
opcodes = listOf(Opcode.CONST_HIGH16),
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 b55f7febd..2372a7df5 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
@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.player.seekbar
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -9,14 +10,19 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.drawable.addDrawableColorHook
import app.revanced.patches.shared.drawable.drawableColorHookPatch
+import app.revanced.patches.shared.mainactivity.onCreateMethod
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.extension.Constants.PATCH_STATUS_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
+import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_PATH
import app.revanced.patches.youtube.utils.flyoutmenu.flyoutMenuHookPatch
+import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
import app.revanced.patches.youtube.utils.patch.PatchList.SEEKBAR_COMPONENTS
import app.revanced.patches.youtube.utils.playerButtonsResourcesFingerprint
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.versionCheckPatch
import app.revanced.patches.youtube.utils.resourceid.inlineTimeBarColorizedBarPlayedColorDark
import app.revanced.patches.youtube.utils.resourceid.inlineTimeBarPlayedNotHighlightedColor
@@ -29,6 +35,8 @@ import app.revanced.patches.youtube.utils.settings.ResourceUtils.getContext
import app.revanced.patches.youtube.utils.settings.settingsPatch
import app.revanced.patches.youtube.utils.totalTimeFingerprint
import app.revanced.patches.youtube.video.information.videoInformationPatch
+import app.revanced.util.copyXmlNode
+import app.revanced.util.findElementByAttributeValueOrThrow
import app.revanced.util.findMethodsOrThrow
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
import app.revanced.util.fingerprint.matchOrThrow
@@ -38,6 +46,7 @@ import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
+import app.revanced.util.inputStreamFromBundledResource
import app.revanced.util.updatePatchStatus
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@@ -46,6 +55,45 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import org.w3c.dom.Element
+import java.io.ByteArrayInputStream
+
+internal const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color"
+
+/**
+ * Generate a style xml with all combinations of 9-bit colors.
+ */
+private fun create9BitSeekbarColorStyles(): String = StringBuilder().apply {
+ append("")
+ append("