diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/EnableDebuggingPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/EnableDebuggingPatch.java index 333420f40f..f0e0e1f273 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/EnableDebuggingPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/EnableDebuggingPatch.java @@ -9,14 +9,23 @@ @SuppressWarnings("unused") public final class EnableDebuggingPatch { - private static final ConcurrentMap featureFlags - = new ConcurrentHashMap<>(300, 0.75f, 1); + /** + * Only log if debugging is enabled on startup. + * This prevents enabling debugging + * while the app is running then failing to restart + * resulting in an incomplete log. + */ + private static final boolean LOG_FEATURE_FLAGS = BaseSettings.DEBUG.get(); + + private static final ConcurrentMap featureFlags = LOG_FEATURE_FLAGS + ? new ConcurrentHashMap<>(800, 0.5f, 1) + : null; /** * Injection point. */ public static boolean isBooleanFeatureFlagEnabled(boolean value, long flag) { - if (value && BaseSettings.DEBUG.get()) { + if (LOG_FEATURE_FLAGS && value) { if (featureFlags.putIfAbsent(flag, true) == null) { Logger.printDebug(() -> "boolean feature is enabled: " + flag); } @@ -29,7 +38,7 @@ public static boolean isBooleanFeatureFlagEnabled(boolean value, long flag) { * Injection point. */ public static double isDoubleFeatureFlagEnabled(double value, long flag, double defaultValue) { - if (defaultValue != value && BaseSettings.DEBUG.get()) { + if (LOG_FEATURE_FLAGS && defaultValue != value) { if (featureFlags.putIfAbsent(flag, true) == null) { // Align the log outputs to make post processing easier. Logger.printDebug(() -> " double feature is enabled: " + flag @@ -44,7 +53,7 @@ public static double isDoubleFeatureFlagEnabled(double value, long flag, double * Injection point. */ public static long isLongFeatureFlagEnabled(long value, long flag, long defaultValue) { - if (defaultValue != value && BaseSettings.DEBUG.get()) { + if (LOG_FEATURE_FLAGS && defaultValue != value) { if (featureFlags.putIfAbsent(flag, true) == null) { Logger.printDebug(() -> " long feature is enabled: " + flag + " value: " + value + (defaultValue == 0 ? "" : " default: " + defaultValue)); @@ -58,7 +67,7 @@ public static long isLongFeatureFlagEnabled(long value, long flag, long defaultV * Injection point. */ public static String isStringFeatureFlagEnabled(String value, long flag, String defaultValue) { - if (BaseSettings.DEBUG.get() && !defaultValue.equals(value)) { + if (LOG_FEATURE_FLAGS && !defaultValue.equals(value)) { if (featureFlags.putIfAbsent(flag, true) == null) { Logger.printDebug(() -> " string feature is enabled: " + flag + " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue)); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java index 17e6b258e7..b7ceb2b986 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java @@ -36,6 +36,11 @@ public final class SeekbarColorPatch { */ private static final float[] FEED_ORIGINAL_SEEKBAR_GRADIENT_POSITIONS = { 0.8f, 1.0f }; + /** + * Empty seekbar gradient, if hide seekbar in feed is enabled. + */ + private static final int[] HIDDEN_SEEKBAR_GRADIENT_COLORS = { 0x0, 0x0 }; + /** * Default YouTube seekbar color brightness. */ @@ -43,10 +48,10 @@ public final class SeekbarColorPatch { /** * If {@link Settings#SEEKBAR_CUSTOM_COLOR} is enabled, - * this is the color value of {@link Settings#SEEKBAR_CUSTOM_COLOR_VALUE}. + * this is the color value of {@link Settings#SEEKBAR_CUSTOM_COLOR_PRIMARY}. * Otherwise this is {@link #ORIGINAL_SEEKBAR_COLOR}. */ - private static int seekbarColor = ORIGINAL_SEEKBAR_COLOR; + private static int customSeekbarColor = ORIGINAL_SEEKBAR_COLOR; /** * Custom seekbar hue, saturation, and brightness values. @@ -56,7 +61,7 @@ public final class SeekbarColorPatch { /** * Custom seekbar color, used for linear gradient replacements. */ - private static final int[] customSeekbarColorInt = new int[2]; + private static final int[] customSeekbarColorGradient = new int[2]; static { float[] hsv = new float[3]; @@ -65,24 +70,27 @@ public final class SeekbarColorPatch { if (SEEKBAR_CUSTOM_COLOR_ENABLED) { loadCustomSeekbarColor(); - - Arrays.fill(customSeekbarColorInt, seekbarColor); } } private static void loadCustomSeekbarColor() { try { - seekbarColor = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_VALUE.get()); - Color.colorToHSV(seekbarColor, customSeekbarColorHSV); + customSeekbarColor = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.get()); + Color.colorToHSV(customSeekbarColor, customSeekbarColorHSV); + + customSeekbarColorGradient[0] = customSeekbarColor; + customSeekbarColorGradient[1] = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_ACCENT.get()); } catch (Exception ex) { Utils.showToastShort(str("revanced_seekbar_custom_color_invalid")); - Settings.SEEKBAR_CUSTOM_COLOR_VALUE.resetToDefault(); + Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.resetToDefault(); + Settings.SEEKBAR_CUSTOM_COLOR_ACCENT.resetToDefault(); + loadCustomSeekbarColor(); } } public static int getSeekbarColor() { - return seekbarColor; + return customSeekbarColor; } /** @@ -126,7 +134,7 @@ public static void setSplashAnimationDrawableTheme(AnimatedVectorDrawable vector // 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); + String seekbarStyle = get9BitStyleIdentifier(customSeekbarColor); Logger.printDebug(() -> "Using splash seekbar style: " + seekbarStyle); final int styleIdentifierDefault = Utils.getResourceIdentifier( @@ -153,15 +161,6 @@ public static boolean showWatchHistoryProgressDrawable(boolean original) { return !HIDE_SEEKBAR_THUMBNAIL_ENABLED && original; } - /** - * Injection point. - */ - public static int getSeekbarScrubHandleColor(int colorValue) { - return SEEKBAR_CUSTOM_COLOR_ENABLED - ? seekbarColor - : colorValue; - } - /** * Injection point. * @@ -173,21 +172,13 @@ public static int getSeekbarScrubHandleColor(int colorValue) { public static int getLithoColor(int colorValue) { if (colorValue == ORIGINAL_SEEKBAR_COLOR) { if (HIDE_SEEKBAR_THUMBNAIL_ENABLED) { - return 0x00000000; + return 0x0; } - return getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR); + return customSeekbarColor; } - return colorValue; - } - /** - * Injection point. - */ - public static int[] getLinearGradient(int[] original) { - return SEEKBAR_CUSTOM_COLOR_ENABLED - ? customSeekbarColorInt - : original; + return colorValue; } private static String colorArrayToHex(int[] colors) { @@ -210,21 +201,31 @@ private static String colorArrayToHex(int[] colors) { /** * Injection point. */ - public static void setLinearGradient(int[] colors, float[] positions) { + public static int[] getPlayerLinearGradient(int[] original) { + return SEEKBAR_CUSTOM_COLOR_ENABLED + ? customSeekbarColorGradient + : original; + } + + /** + * Injection point. + */ + public static int[] getLithoLinearGradient(int[] colors, float[] positions) { if (SEEKBAR_CUSTOM_COLOR_ENABLED || HIDE_SEEKBAR_THUMBNAIL_ENABLED) { // Most litho usage of linear gradients is hooked here, // so must only change if the values are those for the seekbar. if ((Arrays.equals(FEED_ORIGINAL_SEEKBAR_GRADIENT_COLORS, colors) && Arrays.equals(FEED_ORIGINAL_SEEKBAR_GRADIENT_POSITIONS, positions))) { - Arrays.fill(colors, HIDE_SEEKBAR_THUMBNAIL_ENABLED - ? 0x00000000 - : seekbarColor); - return; + return HIDE_SEEKBAR_THUMBNAIL_ENABLED + ? HIDDEN_SEEKBAR_GRADIENT_COLORS + : customSeekbarColorGradient; } Logger.printDebug(() -> "Ignoring gradient colors: " + colorArrayToHex(colors) + " positions: " + Arrays.toString(positions)); } + + return colors; } /** @@ -238,7 +239,7 @@ public static int getVideoPlayerSeekbarClickedColor(int colorValue) { } return colorValue == ORIGINAL_SEEKBAR_COLOR - ? getSeekbarColorValue(ORIGINAL_SEEKBAR_COLOR) + ? customSeekbarColor : colorValue; } @@ -248,11 +249,9 @@ public static int getVideoPlayerSeekbarClickedColor(int colorValue) { * Overrides color used for the video player seekbar. */ public static int getVideoPlayerSeekbarColor(int originalColor) { - if (!SEEKBAR_CUSTOM_COLOR_ENABLED) { - return originalColor; - } - - return getSeekbarColorValue(originalColor); + return SEEKBAR_CUSTOM_COLOR_ENABLED + ? getSeekbarColorValue(originalColor) + : originalColor; } /** @@ -261,10 +260,6 @@ public static int getVideoPlayerSeekbarColor(int originalColor) { */ private static int getSeekbarColorValue(int originalColor) { try { - if (!SEEKBAR_CUSTOM_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. @@ -277,7 +272,7 @@ private static int getSeekbarColorValue(int originalColor) { hsv[1] = customSeekbarColorHSV[1]; hsv[2] = clamp(customSeekbarColorHSV[2] + brightnessDifference, 0, 1); - final int replacementAlpha = clamp(Color.alpha(seekbarColor) + alphaDifference, 0, 255); + final int replacementAlpha = clamp(Color.alpha(customSeekbarColor) + alphaDifference, 0, 255); final int replacementColor = Color.HSVToColor(replacementAlpha, hsv); Logger.printDebug(() -> String.format("Original color: #%08X replacement color: #%08X", originalColor, replacementColor)); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java index 6d76255c51..59b803d985 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -27,6 +27,8 @@ import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY; import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY_ONCE; +import android.graphics.Color; + import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.settings.BaseSettings; import app.revanced.extension.shared.settings.BooleanSetting; @@ -267,18 +269,19 @@ public class Settings extends BaseSettings { public static final BooleanSetting SHORTS_AUTOPLAY_BACKGROUND = new BooleanSetting("revanced_shorts_autoplay_background", TRUE); // Seekbar - - public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", TRUE); + public static final BooleanSetting DISABLE_PRECISE_SEEKING_GESTURE = new BooleanSetting("revanced_disable_precise_seeking_gesture", FALSE); public static final BooleanSetting HIDE_SEEKBAR = new BooleanSetting("revanced_hide_seekbar", FALSE, true); public static final BooleanSetting HIDE_SEEKBAR_THUMBNAIL = new BooleanSetting("revanced_hide_seekbar_thumbnail", FALSE, true); public static final BooleanSetting HIDE_TIMESTAMP = new BooleanSetting("revanced_hide_timestamp", FALSE); public static final BooleanSetting RESTORE_OLD_SEEKBAR_THUMBNAILS = new BooleanSetting("revanced_restore_old_seekbar_thumbnails", TRUE); - public static final BooleanSetting SEEKBAR_CUSTOM_COLOR = new BooleanSetting("revanced_seekbar_custom_color", FALSE, true); - public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", TRUE); + public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", FALSE); public static final BooleanSetting SEEKBAR_THUMBNAILS_HIGH_QUALITY = new BooleanSetting("revanced_seekbar_thumbnails_high_quality", FALSE, true, "revanced_seekbar_thumbnails_high_quality_dialog_message", new SeekbarThumbnailsHighQualityAvailability()); public static final BooleanSetting SLIDE_TO_SEEK = new BooleanSetting("revanced_slide_to_seek", FALSE, true); - public static final StringSetting SEEKBAR_CUSTOM_COLOR_VALUE = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033", true, parent(SEEKBAR_CUSTOM_COLOR)); + public static final BooleanSetting SEEKBAR_CUSTOM_COLOR = new BooleanSetting("revanced_seekbar_custom_color", FALSE, true); + private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033"); + public static final StringSetting SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_primary", "#FF0033", true, parent(SEEKBAR_CUSTOM_COLOR)); + public static final StringSetting SEEKBAR_CUSTOM_COLOR_ACCENT = new StringSetting("revanced_seekbar_custom_color_accent", "#FF2791", true, parent(SEEKBAR_CUSTOM_COLOR)); // Misc public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE); @@ -406,6 +409,30 @@ public class Settings extends BaseSettings { MINIPLAYER_TYPE.save(MINIMAL); } + // Migrate old single color seekbar with a slightly brighter accent color based on the primary. + // Eventually delete this logic. + if (!DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.isSetToDefault()) { + try { + String oldPrimaryColorString = DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.get(); + final int oldPrimaryColor = Color.parseColor(oldPrimaryColorString); + SEEKBAR_CUSTOM_COLOR_PRIMARY.save(oldPrimaryColorString); + + final float brightnessScale = 1.3f; + final int accentColor = Color.argb( + 0, // Save without alpha channel. + Math.min(255, (int) (brightnessScale * Color.red(oldPrimaryColor))), + Math.min(255, (int) (brightnessScale * Color.green(oldPrimaryColor))), + Math.min(255, (int) (brightnessScale * Color.blue(oldPrimaryColor))) + ); + + SEEKBAR_CUSTOM_COLOR_ACCENT.save(String.format("#%06X", accentColor)); + } catch (Exception ex) { + Logger.printException(() -> "Could not parse old seekbar color", ex); + } + + DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.resetToDefault(); + } + // endregion // region SB import/export callbacks diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt index 5ccbdad845..93e8ff19ca 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt @@ -200,25 +200,27 @@ val seekbarColorPatch = bytecodePatch( ) execute { - fun MutableMethod.addColorChangeInstructions(resourceId: Long) { - val registerIndex = indexOfFirstLiteralInstructionOrThrow(resourceId) + 2 - val colorRegister = getInstruction(registerIndex).registerA + fun MutableMethod.addColorChangeInstructions(resourceId: Long, methodName: String) { + val index = indexOfFirstLiteralInstructionOrThrow(resourceId) + val insertIndex = indexOfFirstInstructionOrThrow(index, Opcode.MOVE_RESULT) + val register = getInstruction(insertIndex).registerA + addInstructions( - registerIndex + 1, + insertIndex + 1, + """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(I)I + move-result v$register """ - invoke-static { v$colorRegister }, $EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I - move-result v$colorRegister - """, ) } playerSeekbarColorFingerprint.method.apply { - addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId) - addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId) + addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId, "getVideoPlayerSeekbarColor") + addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId, "getVideoPlayerSeekbarColor") } shortsSeekbarColorFingerprint.method.apply { - addColorChangeInstructions(reelTimeBarPlayedColorId) + addColorChangeInstructions(reelTimeBarPlayedColorId, "getVideoPlayerSeekbarColor") } setSeekbarClickedColorFingerprint.originalMethod.let { @@ -245,17 +247,7 @@ val seekbarColorPatch = bytecodePatch( // 19.25+ changes playerSeekbarHandleColorFingerprint.method.apply { - val index = indexOfFirstLiteralInstructionOrThrow(ytStaticBrandRedId) - val insertIndex = indexOfFirstInstructionOrThrow(index, Opcode.MOVE_RESULT) - val register = getInstruction(insertIndex).registerA - - addInstructions( - insertIndex + 1, - """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getSeekbarScrubHandleColor(I)I - move-result v$register - """ - ) + addColorChangeInstructions(ytStaticBrandRedId, "getVideoPlayerSeekbarColor") } // If hiding feed seekbar thumbnails, then turn off the cairo gradient @@ -273,16 +265,19 @@ val seekbarColorPatch = bytecodePatch( addInstructions( index + 1, """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z - move-result v$register - """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z + move-result v$register + """ ) } } - lithoLinearGradientFingerprint.method.addInstruction( + lithoLinearGradientFingerprint.method.addInstructions( 0, - "invoke-static/range { p4 .. p5 }, $EXTENSION_CLASS_DESCRIPTOR->setLinearGradient([I[F)V" + """ + invoke-static/range { p4 .. p5 }, $EXTENSION_CLASS_DESCRIPTOR->getLithoLinearGradient([I[F)[I + move-result-object p4 + """ ) val playerFingerprint = @@ -302,7 +297,7 @@ val seekbarColorPatch = bytecodePatch( addInstructions( index + 1, """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getLinearGradient([I)[I + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerLinearGradient([I)[I move-result-object v$register """ ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt index 92d3a3fd88..285909ce46 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt @@ -13,6 +13,8 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.TextPreference import app.revanced.patches.youtube.layout.seekbar.seekbarColorPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch +import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater +import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.forEachChildElement @@ -71,6 +73,7 @@ val themePatch = bytecodePatch( dependsOn( lithoColorHookPatch, seekbarColorPatch, + versionCheckPatch, resourcePatch { dependsOn( settingsPatch, @@ -83,9 +86,15 @@ val themePatch = bytecodePatch( PreferenceScreen.SEEKBAR.addPreferences( SwitchPreference("revanced_seekbar_custom_color"), - TextPreference("revanced_seekbar_custom_color_value", inputType = InputType.TEXT_CAP_CHARACTERS), + TextPreference("revanced_seekbar_custom_color_primary", inputType = InputType.TEXT_CAP_CHARACTERS), ) + if (is_19_25_or_greater) { + PreferenceScreen.SEEKBAR.addPreferences( + TextPreference("revanced_seekbar_custom_color_accent", inputType = InputType.TEXT_CAP_CHARACTERS), + ) + } + // Edit theme colors via resources. document("res/values/colors.xml").use { document -> diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index ffceca0ad6..7e7a6f2dba 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -1223,8 +1223,10 @@ Swipe to expand or close" Enable custom seekbar color Custom seekbar color is shown Original seekbar color is shown - Custom seekbar color - The color of the seekbar + Custom seekbar color + The color of the seekbar + Custom seekbar accent color + The accent color of the seekbar Invalid seekbar color value