diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/SeekbarThumbnailsPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/SeekbarThumbnailsPatch.java new file mode 100644 index 0000000000..a48274336c --- /dev/null +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/SeekbarThumbnailsPatch.java @@ -0,0 +1,16 @@ +package app.revanced.extension.youtube.patches; + +import app.revanced.extension.youtube.settings.Settings; + +@SuppressWarnings("unused") +public class SeekbarThumbnailsPatch { + + private static final boolean SEEKBAR_THUMBNAILS_HIGH_QUALITY_ENABLED = Settings.SEEKBAR_THUMBNAILS_HIGH_QUALITY.get(); + + /** + * Injection point. + */ + public static boolean useHighQualityFullscreenThumbnails() { + return SEEKBAR_THUMBNAILS_HIGH_QUALITY_ENABLED; + } +} diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java index 1ff26a7ba7..d463cbdd52 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -250,6 +250,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting SEEKBAR_TAPPING = new BooleanSetting("revanced_seekbar_tapping", TRUE); public static final BooleanSetting SLIDE_TO_SEEK = new BooleanSetting("revanced_slide_to_seek", FALSE, true); public static final BooleanSetting RESTORE_OLD_SEEKBAR_THUMBNAILS = new BooleanSetting("revanced_restore_old_seekbar_thumbnails", TRUE); + public static final BooleanSetting SEEKBAR_THUMBNAILS_HIGH_QUALITY = new BooleanSetting("revanced_seekbar_thumbnails_high_quality", FALSE, true, "revanced_seekbar_thumbnails_high_quality_dialog_message"); 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); public static final BooleanSetting SEEKBAR_CUSTOM_COLOR = new BooleanSetting("revanced_seekbar_custom_color", FALSE, true); diff --git a/patches/api/patches.api b/patches/api/patches.api index 6d6f8d2762..4782cf765a 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -1196,6 +1196,10 @@ public final class app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch public static final fun getSeekbarColorPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/youtube/layout/seekbar/SeekbarThumbnailsPatchKt { + public static final fun getSeekbarThumbnailsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatchKt { public static final fun getShortsAutoplayPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt index cf620bc644..c3fe10c2dd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt @@ -117,3 +117,10 @@ internal val slideToSeekFingerprint = fingerprint { ) literal { 67108864 } } + +internal val fullscreenSeekbarThumbnailsQualityFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Z") + parameters() + literal { 45399684L } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt new file mode 100644 index 0000000000..9a49d0e012 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt @@ -0,0 +1,64 @@ +package app.revanced.patches.youtube.layout.seekbar + +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.all.misc.resources.addResources +import app.revanced.patches.all.misc.resources.addResourcesPatch +import app.revanced.patches.shared.misc.settings.preference.SwitchPreference +import app.revanced.patches.youtube.interaction.seekbar.fullscreenSeekbarThumbnailsQualityFingerprint +import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch +import app.revanced.patches.youtube.misc.playservice.is_19_17_or_greater +import app.revanced.patches.youtube.misc.playservice.versionCheckPatch +import app.revanced.patches.youtube.misc.settings.PreferenceScreen + +private const val EXTENSION_CLASS_DESCRIPTOR = + "Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;" + +@Suppress("unused") +val seekbarThumbnailsPatch = bytecodePatch( + name = "Seekbar thumbnails", + description = "Adds an option to use high quality fullscreen seekbar thumbnails.", +) { + dependsOn( + sharedExtensionPatch, + addResourcesPatch, + versionCheckPatch, + ) + + compatibleWith( + "com.google.android.youtube"( + "18.38.44", + "18.49.37", + "19.16.39", + "19.25.37", + "19.34.42", + ) + ) + + val fullscreenSeekbarThumbnailsQualityMatch by fullscreenSeekbarThumbnailsQualityFingerprint() + + execute { + addResources("youtube", "layout.seekbar.seekbarThumbnailsPatch") + + PreferenceScreen.SEEKBAR.addPreferences( + if (!is_19_17_or_greater) { + SwitchPreference( + key = "revanced_seekbar_thumbnails_high_quality", + summaryOnKey = "revanced_seekbar_thumbnails_high_quality_legacy_summary_on", + summaryOffKey = "revanced_seekbar_thumbnails_high_quality_legacy_summary_on" + ) + } else { + SwitchPreference("revanced_seekbar_thumbnails_high_quality") + } + ) + + fullscreenSeekbarThumbnailsQualityMatch.mutableMethod.addInstructions( + 0, + """ + invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->useHighQualityFullscreenThumbnails()Z + move-result v0 + return v0 + """ + ) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt index a21927289a..1dbdad8845 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt @@ -2,7 +2,6 @@ package app.revanced.patches.youtube.layout.seekbar import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.instructions -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch @@ -11,6 +10,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playservice.is_19_17_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen +import java.util.logging.Logger private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/RestoreOldSeekbarThumbnailsPatch;" @@ -39,8 +39,7 @@ val restoreOldSeekbarThumbnailsPatch = bytecodePatch( execute { if (is_19_17_or_greater) { - // Give a more informative error, if the user has turned off version checks. - throw PatchException("'Restore old seekbar thumbnails' cannot be patched to any version after 19.16.39") + return@execute Logger.getLogger(this::class.java.name).severe("'Restore old seekbar thumbnails' cannot be patched to any version after 19.16.39") } addResources("youtube", "layout.seekbar.restoreOldSeekbarThumbnailsPatch") diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 75b7a65409..d1fdfd8c81 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -762,6 +762,14 @@ This is because Crowdin requires temporarily flattening this file and removing t Wide search bar is enabled Wide search bar is disabled + + Enable high quality thumbnails + Seekbar thumbnails are high quality + Seekbar thumbnails are medium quality + Fullscreen seekbar thumbnails are high quality + Fullscreen seekbar thumbnails are medium quality + This will restore thumbnails to livestreams that do not have seekbar thumbnails.\n\nInternet data usage may be higher, and seekbar thumbnails will have a slight delay before showing.\n\nThis feature works best with a very fast internet connection. + Restore old seekbar thumbnails Seekbar thumbnails will appear above the seekbar