From e9e4cf39b6ab2879fc145c1dfcb51e7e8e89d932 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 28 Jul 2025 20:44:18 +0200 Subject: [PATCH 01/33] feat(YouTube - Playback speed): Add "Restore old playback speed menu" option (#5552) --- .../patches/ReturnYouTubeDislikePatch.java | 4 +- ...terPatch.java => HideInfoCardsFilter.java} | 4 +- ...atch.java => PlaybackSpeedMenuFilter.java} | 23 +++- ...h.java => ReturnYouTubeDislikeFilter.java} | 4 +- .../speed/CustomPlaybackSpeedPatch.java | 82 ++++++++----- .../extension/youtube/settings/Settings.java | 3 +- .../hide/infocards/HideInfoCardsPatch.kt | 2 +- .../ReturnYouTubeDislikePatch.kt | 2 +- .../speed/custom/CustomPlaybackSpeedPatch.kt | 111 +++++++++++++++++- .../video/speed/custom/Fingerprints.kt | 23 ++++ .../resources/addresources/values/strings.xml | 3 + 11 files changed, 216 insertions(+), 45 deletions(-) rename extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/{HideInfoCardsFilterPatch.java => HideInfoCardsFilter.java} (78%) rename extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/{PlaybackSpeedMenuFilterPatch.java => PlaybackSpeedMenuFilter.java} (58%) rename extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/{ReturnYouTubeDislikeFilterPatch.java => ReturnYouTubeDislikeFilter.java} (97%) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java index bb351b66bb..dbd1ad8d4c 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java @@ -16,7 +16,7 @@ import java.util.Objects; import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Utils; -import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilterPatch; +import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilter; import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.shared.PlayerType; @@ -55,7 +55,7 @@ public class ReturnYouTubeDislikePatch { private static volatile ReturnYouTubeDislike lastLithoShortsVideoData; /** - * Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilterPatch} + * Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilter} * detects the video ids, but the current Short can arbitrarily reload the same span, * then use the {@link #lastLithoShortsVideoData} if this value is greater than zero. */ diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/HideInfoCardsFilter.java similarity index 78% rename from extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch.java rename to extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/HideInfoCardsFilter.java index ce92b592ee..3c4c33d161 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/HideInfoCardsFilter.java @@ -3,9 +3,9 @@ package app.revanced.extension.youtube.patches.components; import app.revanced.extension.youtube.settings.Settings; @SuppressWarnings("unused") -public final class HideInfoCardsFilterPatch extends Filter { +public final class HideInfoCardsFilter extends Filter { - public HideInfoCardsFilterPatch() { + public HideInfoCardsFilter() { addIdentifierCallbacks( new StringFilterGroup( Settings.HIDE_INFO_CARDS, diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java similarity index 58% rename from extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java rename to extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java index 531578a8b4..78ce3595d5 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java @@ -8,27 +8,44 @@ import app.revanced.extension.youtube.settings.Settings; /** * Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}. */ -public final class PlaybackSpeedMenuFilterPatch extends Filter { +public final class PlaybackSpeedMenuFilter extends Filter { + + /** + * Old litho based speed selection menu. + */ + public static volatile boolean isOldPlaybackSpeedMenuVisible; /** * 0.05x speed selection menu. */ public static volatile boolean isPlaybackRateSelectorMenuVisible; - public PlaybackSpeedMenuFilterPatch() { + private final StringFilterGroup oldPlaybackMenuGroup; + + public PlaybackSpeedMenuFilter() { // 0.05x litho speed menu. var playbackRateSelectorGroup = new StringFilterGroup( Settings.CUSTOM_SPEED_MENU, "playback_rate_selector_menu_sheet.eml-js" ); + // Old litho based speed menu. + oldPlaybackMenuGroup = new StringFilterGroup( + Settings.CUSTOM_SPEED_MENU, + "playback_speed_sheet_content.eml-js"); + + addPathCallbacks(playbackRateSelectorGroup); } @Override boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { - isPlaybackRateSelectorMenuVisible = true; + if (matchedGroup == oldPlaybackMenuGroup) { + isOldPlaybackSpeedMenuVisible = true; + } else { + isPlaybackRateSelectorMenuVisible = true; + } return false; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java similarity index 97% rename from extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java rename to extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java index 0d1504e40e..2164e4331b 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java @@ -26,7 +26,7 @@ import app.revanced.extension.youtube.TrieSearch; * * Once a way to asynchronously update litho text is found, this strategy will no longer be needed. */ -public final class ReturnYouTubeDislikeFilterPatch extends Filter { +public final class ReturnYouTubeDislikeFilter extends Filter { /** * Last unique video id's loaded. Value is ignored and Map is treated as a Set. @@ -67,7 +67,7 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter { private final ByteArrayFilterGroupList videoIdFilterGroup = new ByteArrayFilterGroupList(); - public ReturnYouTubeDislikeFilterPatch() { + public ReturnYouTubeDislikeFilter() { // When a new Short is opened, the like buttons always seem to load before the dislike. // But if swiping back to a previous video and liking/disliking, then only that single button reloads. // So must check for both buttons. diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java index da37aa426a..88eae4a0d3 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -23,7 +23,6 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewParent; import android.view.Window; import android.view.WindowManager; import android.view.animation.Animation; @@ -42,7 +41,7 @@ import java.util.function.Function; import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Utils; import app.revanced.extension.youtube.patches.VideoInformation; -import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilterPatch; +import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilter; import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.shared.PlayerType; import kotlin.Unit; @@ -80,6 +79,16 @@ public class CustomPlaybackSpeedPatch { */ public static final float[] customPlaybackSpeeds; + /** + * Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}. + */ + private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax; + + /** + * The last time the old playback menu was forcefully called. + */ + private static volatile long lastTimeOldPlaybackMenuInvoked; + /** * Formats speeds to UI strings. */ @@ -90,11 +99,6 @@ public class CustomPlaybackSpeedPatch { */ private static WeakReference currentDialog = new WeakReference<>(null); - /** - * Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}. - */ - private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax; - static { // Cap at 2 decimals (rounds automatically). speedFormatter.setMaximumFractionDigits(2); @@ -174,25 +178,33 @@ public class CustomPlaybackSpeedPatch { public static void onFlyoutMenuCreate(RecyclerView recyclerView) { recyclerView.getViewTreeObserver().addOnDrawListener(() -> { try { - if (PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible) { - if (hideLithoMenuAndShowCustomSpeedMenu(recyclerView, 5)) { - PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible = false; + if (PlaybackSpeedMenuFilter.isPlaybackRateSelectorMenuVisible) { + if (hideLithoMenuAndShowSpeedMenu(recyclerView, 5)) { + PlaybackSpeedMenuFilter.isPlaybackRateSelectorMenuVisible = false; } } } catch (Exception ex) { - Logger.printException(() -> "onFlyoutMenuCreate failure", ex); + Logger.printException(() -> "isPlaybackRateSelectorMenuVisible failure", ex); + } + + try { + if (PlaybackSpeedMenuFilter.isOldPlaybackSpeedMenuVisible) { + if (hideLithoMenuAndShowSpeedMenu(recyclerView, 8)) { + PlaybackSpeedMenuFilter.isOldPlaybackSpeedMenuVisible = false; + } + } + } catch (Exception ex) { + Logger.printException(() -> "isOldPlaybackSpeedMenuVisible failure", ex); } }); } - @SuppressWarnings("SameParameterValue") - private static boolean hideLithoMenuAndShowCustomSpeedMenu(RecyclerView recyclerView, int expectedChildCount) { + private static boolean hideLithoMenuAndShowSpeedMenu(RecyclerView recyclerView, int expectedChildCount) { if (recyclerView.getChildCount() == 0) { return false; } - View firstChild = recyclerView.getChildAt(0); - if (!(firstChild instanceof ViewGroup playbackSpeedParentView)) { + if (!(recyclerView.getChildAt(0) instanceof ViewGroup playbackSpeedParentView)) { return false; } @@ -200,33 +212,49 @@ public class CustomPlaybackSpeedPatch { return false; } - ViewParent parentView3rd = Utils.getParentView(recyclerView, 3); - if (!(parentView3rd instanceof ViewGroup)) { - return true; + if (!(Utils.getParentView(recyclerView, 3) instanceof ViewGroup parentView3rd)) { + return false; } - ViewParent parentView4th = parentView3rd.getParent(); - if (!(parentView4th instanceof ViewGroup)) { - return true; + if (!(parentView3rd.getParent() instanceof ViewGroup parentView4th)) { + return false; } // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView. // This only shows in phone layout. - final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0); + var touchInsidedView = parentView4th.getChildAt(0); touchInsidedView.setSoundEffectsEnabled(false); touchInsidedView.performClick(); // In tablet layout there is no Dismiss View, instead we just hide all two parent views. - ((ViewGroup) parentView3rd).setVisibility(View.GONE); - ((ViewGroup) parentView4th).setVisibility(View.GONE); + parentView3rd.setVisibility(View.GONE); + parentView4th.setVisibility(View.GONE); - // Close the litho speed menu and show the modern custom speed dialog. - showModernCustomPlaybackSpeedDialog(recyclerView.getContext()); - Logger.printDebug(() -> "Modern playback speed dialog shown"); + // Close the litho speed menu and show the custom speeds. + if (Settings.RESTORE_OLD_SPEED_MENU.get()) { + showOldPlaybackSpeedMenu(); + Logger.printDebug(() -> "Old playback speed dialog shown"); + } else { + showModernCustomPlaybackSpeedDialog(recyclerView.getContext()); + Logger.printDebug(() -> "Modern playback speed dialog shown"); + } return true; } + public static void showOldPlaybackSpeedMenu() { + // This method is sometimes used multiple times. + // To prevent this, ignore method reuse within 1 second. + final long now = System.currentTimeMillis(); + if (now - lastTimeOldPlaybackMenuInvoked < 1000) { + Logger.printDebug(() -> "Ignoring call to showOldPlaybackSpeedMenu"); + return; + } + lastTimeOldPlaybackMenuInvoked = now; + + // Rest of the implementation added by patch. + } + /** * Displays a modern custom dialog for adjusting video playback speed. *

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 edeb7ca0b5..2f51b13475 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 @@ -68,8 +68,9 @@ public class Settings extends BaseSettings { public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE); public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_last_selected_toast", TRUE, false, parent(REMEMBER_PLAYBACK_SPEED_LAST_SELECTED)); - public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE); public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f); + public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE); + public static final BooleanSetting RESTORE_OLD_SPEED_MENU = new BooleanSetting("revanced_restore_old_speed_menu", FALSE, parent(CUSTOM_SPEED_MENU)); public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds", "0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true); diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt index 0a3d7cdbf5..cac5c169b9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt @@ -99,7 +99,7 @@ val hideInfoCardsPatch = bytecodePatch( ) // Info cards can also appear as Litho components. - val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch;" + val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilter;" addLithoFilter(filterClassDescriptor) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index 200e652f34..b65b8f6c4e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -43,7 +43,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch;" private const val FILTER_CLASS_DESCRIPTOR = - "Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;" + "Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter;" val returnYouTubeDislikePatch = bytecodePatch( name = "Return YouTube Dislike", diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt index e6732fb093..b463755719 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt @@ -1,11 +1,19 @@ package app.revanced.patches.youtube.video.speed.custom +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 +import app.revanced.patcher.extensions.InstructionExtensions.instructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patcher.patch.resourcePatch +import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch +import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.resourceMappingPatch +import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.InputType import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.TextPreference @@ -18,18 +26,34 @@ import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTr import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstruction import app.revanced.util.indexOfFirstLiteralInstructionOrThrow +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.immutable.ImmutableField private const val FILTER_CLASS_DESCRIPTOR = - "Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch;" + "Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter;" -private const val EXTENSION_CLASS_DESCRIPTOR = +internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch;" +internal var speedUnavailableId = -1L + private set + +private val customPlaybackSpeedResourcePatch = resourcePatch { + dependsOn(resourceMappingPatch) + + execute { + speedUnavailableId = resourceMappings["string", "varispeed_unavailable_message"] + } +} + internal val customPlaybackSpeedPatch = bytecodePatch( description = "Adds custom playback speed options.", ) { @@ -39,7 +63,8 @@ internal val customPlaybackSpeedPatch = bytecodePatch( addResourcesPatch, lithoFilterPatch, versionCheckPatch, - recyclerViewTreeHookPatch + recyclerViewTreeHookPatch, + customPlaybackSpeedResourcePatch ) execute { @@ -48,6 +73,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( settingsMenuVideoSpeedGroup.addAll( listOf( SwitchPreference("revanced_custom_speed_menu"), + SwitchPreference("revanced_restore_old_speed_menu"), TextPreference( "revanced_custom_playback_speeds", inputType = InputType.TEXT_MULTI_LINE @@ -77,15 +103,88 @@ internal val customPlaybackSpeedPatch = bytecodePatch( replaceInstruction(limitMaxIndex, "const/high16 v$limitMaxRegister, 8.0f") } + + // Replace the speeds float array with custom speeds. + // These speeds are used if the speed menu is immediately opened after a video is opened. + speedArrayGeneratorFingerprint.method.apply { + val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "size" } + val sizeCallResultRegister = getInstruction(sizeCallIndex + 1).registerA + + replaceInstruction(sizeCallIndex + 1, "const/4 v$sizeCallResultRegister, 0x0") + + val arrayLengthConstIndex = indexOfFirstLiteralInstructionOrThrow(7) + val arrayLengthConstDestination = getInstruction(arrayLengthConstIndex).registerA + val playbackSpeedsArrayType = "$EXTENSION_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F" + + addInstructions( + arrayLengthConstIndex + 1, + """ + sget-object v$arrayLengthConstDestination, $playbackSpeedsArrayType + array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination + """, + ) + + val originalArrayFetchIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + reference?.type == "[F" && reference.definingClass.endsWith("/PlayerConfigModel;") + } + val originalArrayFetchDestination = + getInstruction(originalArrayFetchIndex).registerA + + replaceInstruction( + originalArrayFetchIndex, + "sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType", + ) + } + + // region Force old video quality menu. + + // Add a static INSTANCE field to the class. + // This is later used to call "showOldPlaybackSpeedMenu" on the instance. + + val instanceField = ImmutableField( + getOldPlaybackSpeedsFingerprint.originalClassDef.type, + "INSTANCE", + getOldPlaybackSpeedsFingerprint.originalClassDef.type, + AccessFlags.PUBLIC.value or AccessFlags.STATIC.value, + null, + null, + null, + ).toMutable() + + getOldPlaybackSpeedsFingerprint.classDef.staticFields.add(instanceField) + // Set the INSTANCE field to the instance of the class. + // In order to prevent a conflict with another patch, add the instruction at index 1. + getOldPlaybackSpeedsFingerprint.method.addInstruction(1, "sput-object p0, $instanceField") + + // Get the "showOldPlaybackSpeedMenu" method. + // This is later called on the field INSTANCE. + val showOldPlaybackSpeedMenuMethod = showOldPlaybackSpeedMenuFingerprint.match( + getOldPlaybackSpeedsFingerprint.classDef, + ).method + + // Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE. + showOldPlaybackSpeedMenuExtensionFingerprint.method.apply { + addInstructionsWithLabels( + instructions.lastIndex, + """ + sget-object v0, $instanceField + if-nez v0, :not_null + return-void + :not_null + invoke-virtual { v0 }, $showOldPlaybackSpeedMenuMethod + """ + ) + } + + // endregion + // Close the unpatched playback dialog and show the modern custom dialog. addRecyclerViewTreeHook(EXTENSION_CLASS_DESCRIPTOR) // Required to check if the playback speed menu is currently shown. addLithoFilter(FILTER_CLASS_DESCRIPTOR) - // endregion - - // region Custom tap and hold 2x speed. if (is_19_25_or_greater) { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt index 9d8ba83153..f39a4136f1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt @@ -3,10 +3,33 @@ package app.revanced.patches.youtube.video.speed.custom import app.revanced.patcher.fingerprint import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.StringReference +internal val getOldPlaybackSpeedsFingerprint = fingerprint { + parameters("[L", "I") + strings("menu_item_playback_speed") +} + +internal val showOldPlaybackSpeedMenuFingerprint = fingerprint { + literal { speedUnavailableId } +} + +internal val showOldPlaybackSpeedMenuExtensionFingerprint = fingerprint { + custom { method, classDef -> + method.name == "showOldPlaybackSpeedMenu" && classDef.type == EXTENSION_CLASS_DESCRIPTOR + } +} + +internal val speedArrayGeneratorFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) + returns("[L") + parameters("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;") + strings("0.0#") +} + internal val speedLimiterFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 79e04133b4..8a356d06d0 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -1547,6 +1547,9 @@ Enabling this can unlock higher video qualities" Custom playback speed menu Custom speed menu is shown Custom speed menu is not shown + Restore old playback speed menu + Old speed menu is shown + Modern speed menu is shown Custom playback speeds Add or change the custom playback speeds Custom speeds must be less than %s From f0d4e9bfb43784015989327994e7465d3adb89eb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 28 Jul 2025 18:47:44 +0000 Subject: [PATCH 02/33] chore: Release v5.33.0-dev.1 [skip ci] # [5.33.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0-dev.1) (2025-07-28) ### Features * **YouTube - Playback speed:** Add "Restore old playback speed menu" option ([#5552](https://github.com/ReVanced/revanced-patches/issues/5552)) ([e9e4cf3](https://github.com/ReVanced/revanced-patches/commit/e9e4cf39b6ab2879fc145c1dfcb51e7e8e89d932)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a89c085bfe..5c8c6054a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0-dev.1) (2025-07-28) + + +### Features + +* **YouTube - Playback speed:** Add "Restore old playback speed menu" option ([#5552](https://github.com/ReVanced/revanced-patches/issues/5552)) ([b01f15b](https://github.com/ReVanced/revanced-patches/commit/b01f15b9acb0427aed99b0141ae271831b7936bf)) + # [5.32.0](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.32.0) (2025-07-27) diff --git a/gradle.properties b/gradle.properties index c106b2be46..65e70b74a5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.32.0 +version = 5.33.0-dev.1 From afc7c75df1bd05c7eb6c8fed44be374edf73c30a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 04:29:42 -0400 Subject: [PATCH 03/33] chore: Sync translations (#5555) --- .../addresources/values-ar-rSA/strings.xml | 3 ++ .../addresources/values-be-rBY/strings.xml | 3 ++ .../addresources/values-bg-rBG/strings.xml | 3 ++ .../addresources/values-bn-rBD/strings.xml | 3 ++ .../addresources/values-cs-rCZ/strings.xml | 3 ++ .../addresources/values-da-rDK/strings.xml | 3 ++ .../addresources/values-de-rDE/strings.xml | 3 ++ .../addresources/values-el-rGR/strings.xml | 3 ++ .../addresources/values-es-rES/strings.xml | 3 ++ .../addresources/values-et-rEE/strings.xml | 3 ++ .../addresources/values-fil-rPH/strings.xml | 3 ++ .../addresources/values-fr-rFR/strings.xml | 3 ++ .../addresources/values-ga-rIE/strings.xml | 3 ++ .../addresources/values-hu-rHU/strings.xml | 3 ++ .../addresources/values-hy-rAM/strings.xml | 3 ++ .../addresources/values-in-rID/strings.xml | 3 ++ .../addresources/values-it-rIT/strings.xml | 3 ++ .../addresources/values-iw-rIL/strings.xml | 3 ++ .../addresources/values-ja-rJP/strings.xml | 3 ++ .../addresources/values-ko-rKR/strings.xml | 9 +++-- .../addresources/values-lt-rLT/strings.xml | 3 ++ .../addresources/values-lv-rLV/strings.xml | 3 ++ .../addresources/values-nl-rNL/strings.xml | 3 ++ .../addresources/values-pl-rPL/strings.xml | 3 ++ .../addresources/values-pt-rBR/strings.xml | 3 ++ .../addresources/values-pt-rPT/strings.xml | 3 ++ .../addresources/values-ro-rRO/strings.xml | 3 ++ .../addresources/values-ru-rRU/strings.xml | 3 ++ .../addresources/values-sk-rSK/strings.xml | 3 ++ .../addresources/values-sl-rSI/strings.xml | 3 ++ .../addresources/values-sq-rAL/strings.xml | 3 ++ .../addresources/values-sr-rCS/strings.xml | 3 ++ .../addresources/values-sr-rSP/strings.xml | 3 ++ .../addresources/values-sv-rSE/strings.xml | 3 ++ .../addresources/values-th-rTH/strings.xml | 3 ++ .../addresources/values-tr-rTR/strings.xml | 3 ++ .../addresources/values-uk-rUA/strings.xml | 3 ++ .../addresources/values-vi-rVN/strings.xml | 37 ++++++++++--------- .../addresources/values-zh-rCN/strings.xml | 3 ++ 39 files changed, 137 insertions(+), 20 deletions(-) diff --git a/patches/src/main/resources/addresources/values-ar-rSA/strings.xml b/patches/src/main/resources/addresources/values-ar-rSA/strings.xml index b8de28fe02..2ce5dc22d5 100644 --- a/patches/src/main/resources/addresources/values-ar-rSA/strings.xml +++ b/patches/src/main/resources/addresources/values-ar-rSA/strings.xml @@ -1469,6 +1469,9 @@ Second \"item\" text" قائمة سرعة التشغيل المخصصة يتم عرض قائمة سرعة التشغيل المخصصة لا يتم عرض قائمة سرعة التشغيل المخصصة + استعادة قائمة سرعة التشغيل القديمة + قائمة السرعة القديمة معروضة + قائمة السرعة الحديثة معروضة سرعة التشغيل المخصصة إضافة أو تغيير سرعة التشغيل المخصصة يجب أن تكون سرعات التشغيل المخصصة أقل من %s diff --git a/patches/src/main/resources/addresources/values-be-rBY/strings.xml b/patches/src/main/resources/addresources/values-be-rBY/strings.xml index 1076c0646d..a2f8c5ccb3 100644 --- a/patches/src/main/resources/addresources/values-be-rBY/strings.xml +++ b/patches/src/main/resources/addresources/values-be-rBY/strings.xml @@ -1470,6 +1470,9 @@ Second \"item\" text" Меню пользовательской скорости воспроизведения Меню пользовательской скорости отображается Меню пользовательской скорости не отображается + Аднавіць старое меню хуткасці прайгравання + Паказана старое меню хуткасці + Паказана сучаснае меню хуткасці Карыстальніцкія хуткасці прайгравання Добавьте или измените пользовательскую скорость воспроизведения Нестандартныя хуткасці павінны быць менш за %s diff --git a/patches/src/main/resources/addresources/values-bg-rBG/strings.xml b/patches/src/main/resources/addresources/values-bg-rBG/strings.xml index 3eec26d5cb..1b2cf1ba25 100644 --- a/patches/src/main/resources/addresources/values-bg-rBG/strings.xml +++ b/patches/src/main/resources/addresources/values-bg-rBG/strings.xml @@ -1469,6 +1469,9 @@ Second \"item\" text" Менюто за потребителска скорост Менюто за потребителска скорост се показва Менюто за потребителска скорост не се показва + Възстановяване на старото меню за скорост на възпроизвеждане + Показва се старото меню за скорост + Показва се модерното меню за скорост Персонализирани скорости на възпроизвеждане Добавете или променете скоростa на възпроизвеждане Персонализираните скорости трябва да са по-малки от %s diff --git a/patches/src/main/resources/addresources/values-bn-rBD/strings.xml b/patches/src/main/resources/addresources/values-bn-rBD/strings.xml index 83163b8734..e37a42269c 100644 --- a/patches/src/main/resources/addresources/values-bn-rBD/strings.xml +++ b/patches/src/main/resources/addresources/values-bn-rBD/strings.xml @@ -1465,6 +1465,9 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট কাস্টম প্লেব্যাক গতি মেনু কাস্টম স্পিড মেনু দেখানো হচ্ছে কাস্টম স্পিড মেনু দেখানো হচ্ছে না + পুরানো প্লেব্যাক গতি মেনু পুনরুদ্ধার করুন + পুরানো গতির মেনু দেখানো হয়েছে + আধুনিক গতির মেনু দেখানো হয়েছে নিজস্ব প্লেব্যাক স্পিড কাস্টম প্লেব্যাক গতি যোগ করুন অথবা পরিবর্তন করুন কাস্টম গতি %s এর চেয়ে কম হতে হবে diff --git a/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml b/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml index 678bb57ade..8dc89881b6 100644 --- a/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml +++ b/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml @@ -1469,6 +1469,9 @@ Povolením této funkce lze odemknout vyšší kvality videa" Menu vlastní rychlosti přehrávání Menu vlastní rychlosti se zobrazuje Menu vlastní rychlosti se nezobrazuje + Obnovit staré menu rychlosti přehrávání + Zobrazeno staré menu rychlosti + Zobrazeno moderní menu rychlosti Vlastní rychlosti přehrávání Přidat nebo změnit vlastní rychlosti přehrávání Vlastní rychlosti musí být menší než %s diff --git a/patches/src/main/resources/addresources/values-da-rDK/strings.xml b/patches/src/main/resources/addresources/values-da-rDK/strings.xml index f6318994f9..6ff8941f30 100644 --- a/patches/src/main/resources/addresources/values-da-rDK/strings.xml +++ b/patches/src/main/resources/addresources/values-da-rDK/strings.xml @@ -1471,6 +1471,9 @@ Aktivering af dette kan låse op for højere videokvalitet" Tilpasset afspilningshastighed menu Tilpasset hastighed menu er vist Brugerdefineret hastighedsmenu vises ikke + Gendan gammel afspilningshastighedsmenu + Gammel hastighedsmenu vises + Moderne hastighedsmenu vises Tilpasset afspilningshastighed Tilføj eller ændr den brugerdefinerede afspilningshastighed Brugerdefinerede hastigheder skal være mindre end %s diff --git a/patches/src/main/resources/addresources/values-de-rDE/strings.xml b/patches/src/main/resources/addresources/values-de-rDE/strings.xml index 082ea81fc0..88865eddf3 100644 --- a/patches/src/main/resources/addresources/values-de-rDE/strings.xml +++ b/patches/src/main/resources/addresources/values-de-rDE/strings.xml @@ -1464,6 +1464,9 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w Benutzerdefiniertes Wiedergabegeschwindigkeitsmenü Benutzerdefiniertes Geschwindigkeitsmenü wird angezeigt Benutzerdefiniertes Geschwindigkeitsmenü wird nicht angezeigt + Altes Wiedergabegeschwindigkeitsmenü wiederherstellen + Altes Geschwindigkeitsmenü wird angezeigt + Modernes Geschwindigkeitsmenü wird angezeigt Benutzerdefinierte Wiedergabegeschwindigkeiten Hinzufügen oder Ändern der benutzerdefinierten Wiedergabegeschwindigkeit Benutzerdefinierte Geschwindigkeiten müssen kleiner als %s sein diff --git a/patches/src/main/resources/addresources/values-el-rGR/strings.xml b/patches/src/main/resources/addresources/values-el-rGR/strings.xml index 0808a28f19..c6c8a31728 100644 --- a/patches/src/main/resources/addresources/values-el-rGR/strings.xml +++ b/patches/src/main/resources/addresources/values-el-rGR/strings.xml @@ -1468,6 +1468,9 @@ Second \"item\" text" Μενού προσαρμοσμένης ταχύτητας αναπαραγωγής Το μενού προσαρμοσμένης ταχύτητας αναπαραγωγής εμφανίζεται Το μενού προσαρμοσμένης ταχύτητας αναπαραγωγής δεν εμφανίζεται + Επαναφορά παλιού μενού ταχύτητας αναπαραγωγής + Το παλιό μενού ταχύτητας εμφανίζεται + Το σύγχρονο μενού ταχύτητας εμφανίζεται Προσαρμοσμένες ταχύτητες αναπαραγωγής Προσθέστε ή αλλάξτε τις προσαρμοσμένες ταχύτητες αναπαραγωγής Οι ταχύτητες πρέπει να είναι μικρότερες από %sx diff --git a/patches/src/main/resources/addresources/values-es-rES/strings.xml b/patches/src/main/resources/addresources/values-es-rES/strings.xml index 29564bed67..8486373b48 100644 --- a/patches/src/main/resources/addresources/values-es-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-es-rES/strings.xml @@ -1460,6 +1460,9 @@ Habilitar esto puede desbloquear calidades de vídeo más altas" Menú de velocidad de reproducción personalizada Menú de velocidad personalizado se muestra Menú de velocidad personalizado no se muestra + Restaurar el menú de velocidad de reproducción antiguo + Se muestra el menú de velocidad antiguo + Se muestra el menú de velocidad moderno Velocidades de reproducción personalizadas Añadir o cambiar las velocidades de reproducción personalizadas Las velocidades personalizadas deben ser menores que %s diff --git a/patches/src/main/resources/addresources/values-et-rEE/strings.xml b/patches/src/main/resources/addresources/values-et-rEE/strings.xml index d4649b60ed..cdd7773899 100644 --- a/patches/src/main/resources/addresources/values-et-rEE/strings.xml +++ b/patches/src/main/resources/addresources/values-et-rEE/strings.xml @@ -1469,6 +1469,9 @@ Selle lubamine võib avada kõrgema video kvaliteedi" Kohandatud taasesituse kiiruse menüü Kohandatud kiiruse menüü kuvatakse Kohandatud kiiruse menüüd ei kuvata + Taasta vana taasesituse kiiruse menüü + Kuvatakse vana kiiruse menüü + Kuvatakse kaasaegne kiiruse menüü Kohandatud taasesituse kiirused Lisa või muuda kohandatud taasesituse kiirusi Kohandatud kiirused peavad olema alla %s diff --git a/patches/src/main/resources/addresources/values-fil-rPH/strings.xml b/patches/src/main/resources/addresources/values-fil-rPH/strings.xml index 8ed1831a8d..2282434406 100644 --- a/patches/src/main/resources/addresources/values-fil-rPH/strings.xml +++ b/patches/src/main/resources/addresources/values-fil-rPH/strings.xml @@ -1467,6 +1467,9 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video"Menu ng pasadyang bilis ng pag-playback Ipinapakita ang menu ng pasadyang bilis Hindi ipinapakita ang menu ng pasadyang bilis + Ibalik ang lumang menu ng bilis ng pag-playback + Ipinapakita ang lumang menu ng bilis + Ipinapakita ang modernong menu ng bilis Mga custom na bilis ng pag-playback Magdagdag o baguhin ang mga pasadyang bilis ng pag-playback Ang mga custom na bilis ay dapat na mas mababa sa %s diff --git a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml index 436db2b0a6..21c5274ccc 100644 --- a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml +++ b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml @@ -1470,6 +1470,9 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures"Menu de vitesse de lecture personnalisée Le menu de vitesse personnalisée est affiché Le menu de vitesse personnalisée n\'est pas affiché + Restaurer l\'ancien menu de vitesse de lecture + L\'ancien menu de vitesse est affiché + Le menu de vitesse moderne est affiché Vitesses de lecture personnalisées Ajouter ou modifier les vitesses de lecture personnalisées Il doit y avoir moins de %s vitesses personnalisées diff --git a/patches/src/main/resources/addresources/values-ga-rIE/strings.xml b/patches/src/main/resources/addresources/values-ga-rIE/strings.xml index 9051285d77..9573625b88 100644 --- a/patches/src/main/resources/addresources/values-ga-rIE/strings.xml +++ b/patches/src/main/resources/addresources/values-ga-rIE/strings.xml @@ -1469,6 +1469,9 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil" Roghchlár luas athsheinm saincheaptha Taispeántar roghchlár luais saincheaptha Ní thaispeántar roghchlár luais saincheaptha + Athchóirigh an seanchalafort luais athsheinm + Tá an seanchalafort luais taispeánta + Tá an calafort luais nua-aimseartha taispeánta Luas athsheinm saincheaptha Cuir leis nó athraigh na luasanna athsheinm saincheaptha Ní mór luas saincheaptha a bheith níos lú ná %s diff --git a/patches/src/main/resources/addresources/values-hu-rHU/strings.xml b/patches/src/main/resources/addresources/values-hu-rHU/strings.xml index 4936aab72c..b8f2658f46 100644 --- a/patches/src/main/resources/addresources/values-hu-rHU/strings.xml +++ b/patches/src/main/resources/addresources/values-hu-rHU/strings.xml @@ -1466,6 +1466,9 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását"Egyedi lejátszási sebesség menü Megjelenik az egyéni sebesség menü Az egyéni sebesség menü nem jelenik meg + Régi lejátszási sebesség menü visszaállítása + A régi sebességmenü megjelenik + A modern sebességmenü megjelenik Egyedi lejátszási sebesség Egyéni lejátszási sebesség hozzáadása vagy módosítása Az egyéni sebességeknek kevesebbnek kell lenniük, mint %s diff --git a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml index 9ced3529c0..ab28a8803a 100644 --- a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml +++ b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml @@ -1470,6 +1470,9 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի Տեսանյութի արագության հարմարեցված մենյու Հարմարեցված արագության մենյուը ցուցադրվում է Հարմարեցված արագության մենյուը չի ցուցադրվում + Վերականգնել հին նվագարկման արագության ընտրացանկը + Ցուցադրվում է հին արագության ընտրացանկը + Ցուցադրվում է ժամանակակից արագության ընտրացանկը Տեսանյութի վերարտադրման հարմարեցված արագություններ Ավելացնել կամ փոփոխել տեսանյութի վերարտադրման հարմարեցված արագությունները Պատրաստված արագությունները պետք է լինեն ավելի քիչ քան %s diff --git a/patches/src/main/resources/addresources/values-in-rID/strings.xml b/patches/src/main/resources/addresources/values-in-rID/strings.xml index c9b67ee883..75312dd02e 100644 --- a/patches/src/main/resources/addresources/values-in-rID/strings.xml +++ b/patches/src/main/resources/addresources/values-in-rID/strings.xml @@ -1468,6 +1468,9 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Menu kecepatan pemutaran khusus Menu kecepatan khusus ditampilkan Menu kecepatan khusus tidak ditampilkan + Pulihkan menu kecepatan pemutaran lama + Menu kecepatan lama ditampilkan + Menu kecepatan modern ditampilkan Kecepatan pemutaran khusus Tambah atau ubah kecepatan pemutaran khusus Kecepatan khusus harus kurang dari %s diff --git a/patches/src/main/resources/addresources/values-it-rIT/strings.xml b/patches/src/main/resources/addresources/values-it-rIT/strings.xml index 07b3efa33b..a3db099e8a 100644 --- a/patches/src/main/resources/addresources/values-it-rIT/strings.xml +++ b/patches/src/main/resources/addresources/values-it-rIT/strings.xml @@ -1468,6 +1468,9 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Menu di velocità di riproduzione personalizzato Il menu di velocità personalizzato è visibile Il menu di velocità personalizzato non è visibile + Ripristina il vecchio menu della velocità di riproduzione + Il vecchio menu della velocità è mostrato + Il menu della velocità moderno è mostrato Velocità di riproduzione personalizzate Aggiungi o modifica la velocità di riproduzione personalizzata Le velocità personalizzate devono essere inferiori a %s diff --git a/patches/src/main/resources/addresources/values-iw-rIL/strings.xml b/patches/src/main/resources/addresources/values-iw-rIL/strings.xml index 5218aca9c8..e6a586018b 100644 --- a/patches/src/main/resources/addresources/values-iw-rIL/strings.xml +++ b/patches/src/main/resources/addresources/values-iw-rIL/strings.xml @@ -1471,6 +1471,9 @@ Second \"item\" text" תפריט מהירות הפעלה מותאם אישית תפריט מהירות מותאם אישית מוצג תפריט מהירות מותאם אישית אינו מוצג + שחזר תפריט מהירות השמעה ישן + תפריט מהירות ישן מוצג + תפריט מהירות מודרני מוצג מהירויות הפעלה מותאמות אישית הוסף או שנה את המהירויות הפעלה המותאמות אישית מהירויות מותאמות אישית חייבות להיות קטנות מ-%s diff --git a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml index 711697e765..172f3c2455 100644 --- a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml +++ b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml @@ -1469,6 +1469,9 @@ Automotive レイアウト カスタムした再生速度リストを使用する カスタムした再生速度リストが表示されます デフォルトの再生速度リストが表示されます + 古い再生速度メニューを復元 + 古い速度メニューが表示されます + 最新の速度メニューが表示されます カスタム再生速度リスト カスタム再生速度リストを編集します 再生速度は %s 未満である必要があります diff --git a/patches/src/main/resources/addresources/values-ko-rKR/strings.xml b/patches/src/main/resources/addresources/values-ko-rKR/strings.xml index 40bfe98170..6feaea9336 100644 --- a/patches/src/main/resources/addresources/values-ko-rKR/strings.xml +++ b/patches/src/main/resources/addresources/values-ko-rKR/strings.xml @@ -207,9 +207,9 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 설문 조사 숨기기 설문 조사가 숨겨집니다 설문 조사가 표시됩니다 - 콘서트 선반 숨기기 - 콘서트 선반이 숨겨집니다 - 콘서트 선반이 표시됩니다 + 콘서트 티켓 선반 숨기기 + 콘서트 티켓 선반이 숨겨집니다 + 콘서트 티켓 선반이 표시됩니다 동영상 추천 라벨 숨기기 검색 결과에서 다음 라벨이 숨겨집니다:\n• 시청자가 이 동영상도 시청함\n• 내가 좋아할 만한 동영상 @@ -1476,6 +1476,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요" 사용자 정의 동영상 재생 속도 활성화하기 사용자 정의 동영상 재생 속도를 활성화합니다 사용자 정의 동영상 재생 속도를 비활성화합니다 + 이전 재생 속도 메뉴 복원하기 + 이전 재생 속도 메뉴가 표시됩니다 + 모던 재생 속도 메뉴가 표시됩니다 사용자 정의 동영상 재생 속도 편집하기 동영상 재생 속도 값을 추가 또는 변경할 수 있습니다 재생 속도 값은 %s배속보다 작아야 합니다 diff --git a/patches/src/main/resources/addresources/values-lt-rLT/strings.xml b/patches/src/main/resources/addresources/values-lt-rLT/strings.xml index aa4fbf2028..7998220f24 100644 --- a/patches/src/main/resources/addresources/values-lt-rLT/strings.xml +++ b/patches/src/main/resources/addresources/values-lt-rLT/strings.xml @@ -1468,6 +1468,9 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v Tinkintas atkūrimo greičio meniu Tinkintas greičio meniu rodomas Tinkintas greičio meniu nerodomas + Atkurti seną atkūrimo greičio meniu + Rodomas senas greičio meniu + Rodomas modernus greičio meniu Tinkintas atkūrimo greitis Pridėti arba pakeisti tinkintą atkūrimo greitį Pasirinktinis greitis turi būti mažesnis nei %s diff --git a/patches/src/main/resources/addresources/values-lv-rLV/strings.xml b/patches/src/main/resources/addresources/values-lv-rLV/strings.xml index 7b99a31015..a9b83e6624 100644 --- a/patches/src/main/resources/addresources/values-lv-rLV/strings.xml +++ b/patches/src/main/resources/addresources/values-lv-rLV/strings.xml @@ -1470,6 +1470,9 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk Pielāgotas atskaņošanas ātruma izvēlne Pielāgotas ātruma izvēlne tiek rādīta Pielāgotas ātruma izvēlne netiek rādīta + Atjaunot veco atskaņošanas ātruma izvēlni + Tiek rādīta vecā ātruma izvēlne + Tiek rādīta modernā ātruma izvēlne Pielāgotie atskaņošanas ātrumi Pievienojiet vai mainiet pielāgotos atskaņošanas ātrumus Pielāgoti ātrumi ir jābūt mazākiem par %s diff --git a/patches/src/main/resources/addresources/values-nl-rNL/strings.xml b/patches/src/main/resources/addresources/values-nl-rNL/strings.xml index ca4b0d8941..0fb4251ae5 100644 --- a/patches/src/main/resources/addresources/values-nl-rNL/strings.xml +++ b/patches/src/main/resources/addresources/values-nl-rNL/strings.xml @@ -1467,6 +1467,9 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen" Menu voor aangepaste afspeelsnelheid Menu voor aangepaste snelheid wordt weergegeven Menu voor aangepaste snelheid wordt niet weergegeven + Oud afspeelsnelheidsmenu herstellen + Oud snelheidsmenu wordt getoond + Modern snelheidsmenu wordt getoond Aangepaste afspeelsnelheden Voeg aangepaste afspeelsnelheden toe of wijzig ze Aangepaste snelheden moeten lager zijn dan %s diff --git a/patches/src/main/resources/addresources/values-pl-rPL/strings.xml b/patches/src/main/resources/addresources/values-pl-rPL/strings.xml index cde7076ac4..e5fe980263 100644 --- a/patches/src/main/resources/addresources/values-pl-rPL/strings.xml +++ b/patches/src/main/resources/addresources/values-pl-rPL/strings.xml @@ -1465,6 +1465,9 @@ Włączenie tego może odblokować wyższe jakości wideo" Niestandardowe menu prędkości odtwarzania Niestandardowe menu prędkości jest widoczne Niestandardowe menu prędkości nie jest widoczne + Przywróć stare menu prędkości odtwarzania + Pokazane jest stare menu prędkości + Pokazane jest nowoczesne menu prędkości Niestandardowe prędkości odtwarzania Dodaj lub zmień niestandardowe prędkości odtwarzania Prędkości niestandardowe muszą być mniejsze niż %s diff --git a/patches/src/main/resources/addresources/values-pt-rBR/strings.xml b/patches/src/main/resources/addresources/values-pt-rBR/strings.xml index 725d38105d..7ac040cb92 100644 --- a/patches/src/main/resources/addresources/values-pt-rBR/strings.xml +++ b/patches/src/main/resources/addresources/values-pt-rBR/strings.xml @@ -1468,6 +1468,9 @@ Habilitar isso pode desbloquear qualidades de vídeo mais altas" Menu de velocidade de reprodução personalizado O menu de velocidade personalizado é mostrado O menu de velocidade personalizado não é mostrado + Restaurar menu antigo de velocidade de reprodução + Menu antigo de velocidade de reprodução é exibido + Menu moderno de velocidade de reprodução é exibido Velocidade de reprodução personalizada Adicionar ou mudar as velocidades de reprodução personalizadas Velocidades personalizadas devem ser menores que %s diff --git a/patches/src/main/resources/addresources/values-pt-rPT/strings.xml b/patches/src/main/resources/addresources/values-pt-rPT/strings.xml index bbeaf27eb2..fefff758e3 100644 --- a/patches/src/main/resources/addresources/values-pt-rPT/strings.xml +++ b/patches/src/main/resources/addresources/values-pt-rPT/strings.xml @@ -1469,6 +1469,9 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Menu personalizado de velocidade de reprodução O menu de velocidade personalizado é exibido O menu de velocidade personalizado não é mostrado + Restaurar menu antigo de velocidade de reprodução + Menu antigo de velocidade é exibido + Menu moderno de velocidade é exibido Velocidade de reprodução personalizada Adicionar ou alterar as velocidades de reprodução personalizadas Tốc độ tùy chỉnh phải nhỏ hơn %s diff --git a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml index 2db750e492..1f133df404 100644 --- a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml +++ b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml @@ -1468,6 +1468,9 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Meniu de redare personalizat Meniul de viteză personalizat este afișat Meniul de viteză personalizat nu este afișat + Restaurare meniu vechi de viteză de redare + Meniul vechi de viteză este afișat + Meniul modern de viteză este afișat Viteze de redare personalizate Adaugă sau modifică vitezele de redare personalizate Vitezele personalizate trebuie să fie mai mici de %s diff --git a/patches/src/main/resources/addresources/values-ru-rRU/strings.xml b/patches/src/main/resources/addresources/values-ru-rRU/strings.xml index f6eee316c3..e1709b745f 100644 --- a/patches/src/main/resources/addresources/values-ru-rRU/strings.xml +++ b/patches/src/main/resources/addresources/values-ru-rRU/strings.xml @@ -1476,6 +1476,9 @@ Second \"item\" text" Показать кастомное меню скорости Кастомное меню скорости воспроизведения показано Кастомное меню скорости воспроизведения скрыто + Восстановить старое меню скорости воспроизведения + Старое меню скорости показано + Современное меню скорости показано Кастомные скорости воспроизведения Добавить или изменить кастомные скорости воспроизведения Кастомные скорости должны быть меньше, чем %s diff --git a/patches/src/main/resources/addresources/values-sk-rSK/strings.xml b/patches/src/main/resources/addresources/values-sk-rSK/strings.xml index 8ecbf1ff52..7aa9fbcaf3 100644 --- a/patches/src/main/resources/addresources/values-sk-rSK/strings.xml +++ b/patches/src/main/resources/addresources/values-sk-rSK/strings.xml @@ -1462,6 +1462,9 @@ Povolením tejto možnosti môžete odomknúť vyššie kvality videa" Menu vlastnej rýchlosti prehrávania Menu vlastnej rýchlosti sa zobrazuje Menu vlastnej rýchlosti sa nezobrazuje + Obnoviť staré menu rýchlosti prehrávania + Zobrazuje sa staré menu rýchlosti + Zobrazuje sa moderné menu rýchlosti Vlastné rýchlosti prehrávania Pridať alebo zmeň vlastné rýchlosti prehrávania Vlastné rýchlosti musia byť menšie ako %s diff --git a/patches/src/main/resources/addresources/values-sl-rSI/strings.xml b/patches/src/main/resources/addresources/values-sl-rSI/strings.xml index 493cc81779..ff591f3ee9 100644 --- a/patches/src/main/resources/addresources/values-sl-rSI/strings.xml +++ b/patches/src/main/resources/addresources/values-sl-rSI/strings.xml @@ -1469,6 +1469,9 @@ Omogočanje tega lahko odklene višje kakovosti videa" Meni za nastavitev hitrosti predvajanja Meni za nastavitev hitrosti je prikazan Meni za nastavitev hitrosti ni prikazan + Obnovi stari meni hitrosti predvajanja + Prikazan je stari meni hitrosti + Prikazan je sodoben meni hitrosti Nastavitev hitrosti predvajanja po meri Dodajte ali spremenite hitrosti predvajanja po meri Hitrosti predvajanja po meri morajo biti manjše od %s diff --git a/patches/src/main/resources/addresources/values-sq-rAL/strings.xml b/patches/src/main/resources/addresources/values-sq-rAL/strings.xml index bb43c9eeb6..6b6d629c62 100644 --- a/patches/src/main/resources/addresources/values-sq-rAL/strings.xml +++ b/patches/src/main/resources/addresources/values-sq-rAL/strings.xml @@ -1467,6 +1467,9 @@ Aktivizimi i kësaj mund të zhbllokojë cilësi më të larta video" Menyja e shpejtësisë së përsëritjes së përshtatshme Menyja e shpejtësisë së përshtatshme shfaqet Menyja e shpejtësisë së përshtatshme nuk shfaqet + Rivendos menunë e vjetër të shpejtësisë së riprodhimit + Menyja e vjetër e shpejtësisë shfaqet + Menyja moderne e shpejtësisë shfaqet Shpejtësi të përsëritjes së përshtatshme Shtoni ose ndryshoni shpejtësitë e përsëritjes së përshtatshme Shpejtësitë e personalizuara duhet të jenë më të vogla se %s diff --git a/patches/src/main/resources/addresources/values-sr-rCS/strings.xml b/patches/src/main/resources/addresources/values-sr-rCS/strings.xml index c43af89fea..8d4dcccb08 100644 --- a/patches/src/main/resources/addresources/values-sr-rCS/strings.xml +++ b/patches/src/main/resources/addresources/values-sr-rCS/strings.xml @@ -1468,6 +1468,9 @@ Ako ovo omogućite, mogu biti otključani viši kvaliteti videa" Meni prilagođene brzine reprodukcije Meni prilagođene brzine reprodukcije je prikazan Meni prilagođene brzine reprodukcije nije prikazan + Vrati stari meni za brzinu reprodukcije + Prikazan je stari meni brzine reprodukcije + Prikazan je moderni meni brzine reprodukcije Prilagođene brzine reprodukcije Dodajte ili promenite prilagođene brzine reprodukcije Prilagođene brzine moraju biti manje od %s diff --git a/patches/src/main/resources/addresources/values-sr-rSP/strings.xml b/patches/src/main/resources/addresources/values-sr-rSP/strings.xml index 704656a975..3ad3b49a48 100644 --- a/patches/src/main/resources/addresources/values-sr-rSP/strings.xml +++ b/patches/src/main/resources/addresources/values-sr-rSP/strings.xml @@ -1471,6 +1471,9 @@ Second \"item\" text" Мени прилагођене брзине репродукције Мени прилагођене брзине репродукције је приказан Мени прилагођене брзине репродукције није приказан + Врати стари мени брзине репродукције + Приказан је стари мени брзине репродукције + Приказан је модерни мени брзине репродукције Прилагођене брзине репродукције Додајте или промените прилагођене брзине репродукције Прилагођене брзине морају бити мање од %s diff --git a/patches/src/main/resources/addresources/values-sv-rSE/strings.xml b/patches/src/main/resources/addresources/values-sv-rSE/strings.xml index 4881ccfc76..2a8cca521a 100644 --- a/patches/src/main/resources/addresources/values-sv-rSE/strings.xml +++ b/patches/src/main/resources/addresources/values-sv-rSE/strings.xml @@ -1468,6 +1468,9 @@ Om du aktiverar detta kan högre videokvaliteter låsas upp" Anpassad meny för uppspelningshastighet Anpassad hastighetsmeny visas Anpassad hastighetsmeny visas inte + Återställ gammal uppspelningshastighetsmeny + Den gamla hastighetsmenyn visas + Den moderna hastighetsmenyn visas Anpassade uppspelningshastigheter Lägg till eller ändra de anpassade uppspelningshastigheterna Anpassade hastigheter måste vara mindre än %s diff --git a/patches/src/main/resources/addresources/values-th-rTH/strings.xml b/patches/src/main/resources/addresources/values-th-rTH/strings.xml index 37df021ea2..241280d7b0 100644 --- a/patches/src/main/resources/addresources/values-th-rTH/strings.xml +++ b/patches/src/main/resources/addresources/values-th-rTH/strings.xml @@ -1471,6 +1471,9 @@ User id ของคุณเหมือนกับรหัสผ่าน เมนูกำหนดความเร็วในการเล่นแบบกำหนดเอง แสดงเมนูกำหนดความเร็ว ไม่แสดงเมนูกำหนดความเร็ว + คืนค่าเมนูความเร็วในการเล่นแบบเก่า + แสดงเมนูความเร็วแบบเก่า + แสดงเมนูความเร็วแบบใหม่ ความเร็วในการเล่นแบบกำหนดเอง เพิ่มหรือเปลี่ยนความเร็วในการเล่นแบบกำหนดเอง ความเร็วที่กําหนดเองต้องน้อยกว่า %s diff --git a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml index ab474ae585..13d59c6b78 100644 --- a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml +++ b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml @@ -1476,6 +1476,9 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Özel oynatma hızı menüsü Özel oynatma hızı menüsü gösterilir Özel oynatma hızı menüsü gösterilmez + Eski oynatma hızı menüsünü geri yükle + Eski hız menüsü gösterilir + Modern hız menüsü gösterilir Özel oynatma hızları Özel oynatma hızları ekle veya değiştir Özel hızlar %s\'den az olmalıdır diff --git a/patches/src/main/resources/addresources/values-uk-rUA/strings.xml b/patches/src/main/resources/addresources/values-uk-rUA/strings.xml index 40a72b3cd5..00f7390aa4 100644 --- a/patches/src/main/resources/addresources/values-uk-rUA/strings.xml +++ b/patches/src/main/resources/addresources/values-uk-rUA/strings.xml @@ -1468,6 +1468,9 @@ Second \"item\" text" Користувацьке меню швидкості відтворення Користувацьке меню швидкості відтворення показується Користувацьке меню швидкості відтворення не показується + Відновити старе меню швидкості відтворення + Показується старе меню швидкості + Показується сучасне меню швидкості Користувацькі швидкості відтворення Додавання або зміна користувацьких швидкостей відтворення Користувацькі швидкості повинні бути менші ніж %s diff --git a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml index 320bee2674..e67c038ab4 100644 --- a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml +++ b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml @@ -70,7 +70,7 @@ Second \"item\" text" MicroG GmsCore chưa được cài đặt. Hãy cài đặt ngay. - Hành động cần thiết + Cần thực hiện "MicroG GmsCore không có quyền chạy nền. Hãy làm theo hướng dẫn \"Don't kill my app\" dành cho điện thoại của bạn và áp dụng các bước đó để cài đặt MicroG. @@ -90,7 +90,7 @@ Nhấn nút tiếp tục và cho phép thay đổi lựa chọn tối ưu hóa." Giới thiệu Quảng cáo Hình thu nhỏ thay thế - Bảng tin + Trang video Chung Trình phát Thanh tiến trình @@ -281,9 +281,9 @@ Nếu cài đặt này được bật và Doodle đang hiển thị tại khu v Ẩn hoặc hiện các thành phần mô tả video Thanh bộ lọc Ẩn hoặc hiện thanh bộ lọc trong trang video, video liên quan, kết quả tìm kiếm và nhật ký xem - Ẩn trong bảng tin - Đã ẩn trong bảng tin - Đã hiển thị trong bảng tin + Ẩn trong các trang video + Đã ẩn trong trang video + Đã hiển thị trong trang video Ẩn trong video liên quan Đã ẩn trong video liên quan Đã hiển thị trong video liên quan @@ -355,10 +355,10 @@ Nếu cài đặt này được bật và Doodle đang hiển thị tại khu v Danh sách các chuỗi dựng đường dẫn thành phần để lọc được ngăn cách bởi dòng mới Bộ lọc tuỳ chỉnh không hợp lệ: %s Ẩn nội dung từ khóa - Ẩn video trong tìm kiếm và bảng tin bằng bộ lọc từ khóa - Ẩn video trang chủ bằng từ khóa - Video ở thẻ trang chủ đã được lọc bằng từ khóa - Video ở thẻ trang chủ không được lọc bằng từ khóa + Ẩn video trong trang video và tìm kiếm bằng bộ lọc từ khóa + Ẩn video Trang chủ theo từ khóa + Video trong thẻ Trang chủ được lọc theo từ khóa + Video trong thẻ Trang chủ không được lọc theo từ khóa Ẩn kết quả tìm kiếm bằng từ khóa Kết quả tìm kiếm đã được lọc bằng từ khóa Kết quả tìm kiếm không được lọc bằng từ khóa @@ -374,7 +374,7 @@ Từ khóa có thể là tên kênh hoặc bất kỳ văn bản nào hiển th Từ có chữ in hoa ở giữa phải được nhập cùng với chữ viết hoa (ví dụ: iPhone, TikTok, LeBlanc)" Giới thiệu về bộ lọc từ khóa - "Trang chủ/Đăng ký/Kết quả tìm kiếm được lọc để ẩn nội dung khớp với cụm từ khóa + "Trang chủ/Kênh đăng ký/Kết quả tìm kiếm được lọc để ẩn nội dung khớp với cụm từ khóa Hạn chế • Video ngắn không thể bị ẩn theo tên kênh @@ -752,7 +752,7 @@ Nếu thay đổi cài đặt này không có hiệu lực, hãy thử chuyển Đã ẩn trong thẻ Trang chủ và video liên quan Đã hiển thị trong thẻ Trang chủ và video liên quan Ẩn Shorts trong kết quả tìm kiếm - Bị ẩn trong kết quả tìm kiếm + Đã ẩn trong kết quả tìm kiếm Được hiển thị trong kết quả tìm kiếm Ẩn Shorts trong thẻ Kênh đăng ký @@ -907,7 +907,7 @@ Cài đặt → Phát → Tự động phát video tiếp theo" Tải lại video để bình chọn bằng Return YouTube Dislike - Bị ẩn bởi chủ sở hữu + Đã ẩn bởi chủ sở hữu Số lượt không thích được hiển thị Số lượt không thích không được hiển thị Hiện số lượt không thích trong Shorts @@ -1099,7 +1099,7 @@ ID người dùng của bạn giống như mật khẩu và không bao giờ đ Tự động bỏ qua Tự động bỏ qua một lần Hiện nút Bỏ qua - Hiển thị trên thanh tiến trình + Đã hiển thị trên thanh tiến trình Tắt Không thể gửi phân đoạn: %s SponsorBlock bị sập tạm thời @@ -1205,7 +1205,7 @@ Nếu tắt đi sau đó, bạn nên xóa dữ liệu ứng dụng để tránh Thay đổi trang bắt đầu Mặc định - Tất cả đăng ký + Tất cả kênh đăng ký Duyệt kênh Khóa học / Học tập Khám phá @@ -1223,7 +1223,7 @@ Nếu tắt đi sau đó, bạn nên xóa dữ liệu ứng dụng để tránh Tìm kiếm Mua sắm Thể thao - Đăng ký + Kênh đăng ký Xu hướng Thực tế ảo Xem sau @@ -1269,11 +1269,11 @@ Hạn chế: Nút quay lại trên thanh công cụ có thể không hoạt đ Góc được bo tròn Góc vuông Bật chạm hai lần và chụm để thay đổi kích thước - "Đã bật thao tác chạm hai lần và chụm để thay đổi kích thước + "Thao tác chạm hai lần và chụm để thay đổi kích thước đã bật • Chạm hai lần để tăng kích thước trình phát thu nhỏ • Chạm hai lần nữa để khôi phục kích thước ban đầu" - Đã tắt thao tác chạm hai lần và chụm để thay đổi kích thước + Thao tác chạm hai lần và chụm để thay đổi kích thước đã tắt Bật kéo và thả "Kéo và thả đã được bật @@ -1475,6 +1475,9 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Trình đơn tốc độ phát tùy chỉnh Trình đơn tốc độ phát tùy chỉnh được hiển thị Trình đơn tốc độ phát tùy chỉnh không được hiển thị + Khôi phục trình đơn tốc độ phát cũ + Trình đơn tốc độ cũ được hiển thị + Trình đơn tốc độ hiện đại được hiển thị Tốc độ phát tùy chỉnh Thêm hoặc thay đổi tốc độ phát tùy chỉnh Tốc độ tùy chỉnh phải nhỏ hơn %s diff --git a/patches/src/main/resources/addresources/values-zh-rCN/strings.xml b/patches/src/main/resources/addresources/values-zh-rCN/strings.xml index e5128929fa..6c9bf91748 100644 --- a/patches/src/main/resources/addresources/values-zh-rCN/strings.xml +++ b/patches/src/main/resources/addresources/values-zh-rCN/strings.xml @@ -1474,6 +1474,9 @@ Second \"item\" text" 自定义播放速度菜单 显示自定义速度菜单 不显示自定义速度菜单 + 恢复旧版播放速度菜单 + 显示旧版速度菜单 + 显示新版速度菜单 自定义播放速度 添加或更改自定义播放速度 自定义速度必须小于 %s From d92362b0d9803f00af6ba9700eccc7afd69a619a Mon Sep 17 00:00:00 2001 From: abichinger Date: Tue, 29 Jul 2025 10:30:43 +0200 Subject: [PATCH 04/33] feat(ORF ON): Add `Remove root detection` patch (#5551) --- patches/api/patches.api | 4 ++++ .../patches/orfon/detection/root/Fingerprints.kt | 13 +++++++++++++ .../detection/root/RemoveRootDetectionPatch.kt | 16 ++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/Fingerprints.kt create mode 100644 patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatch.kt diff --git a/patches/api/patches.api b/patches/api/patches.api index f976256beb..559de899f8 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -424,6 +424,10 @@ public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatc public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatchKt { + public static final fun getRemoveRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/pandora/ads/DisableAudioAdsPatchKt { public static final fun getDisableAudioAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/Fingerprints.kt new file mode 100644 index 0000000000..525d4f37d2 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/Fingerprints.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.orfon.detection.root + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal val isDeviceRootedFingeprint = fingerprint { + accessFlags(AccessFlags.PUBLIC) + returns("Z") + custom { method, classDef -> + method.name == "isDeviceRooted" && + classDef.endsWith("/RootChecker;") + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatch.kt new file mode 100644 index 0000000000..5940833372 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatch.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.orfon.detection.root + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val removeRootDetectionPatch = bytecodePatch( + name = "Remove root detection", + description = "Removes the check for root permissions.", +) { + compatibleWith("com.nousguide.android.orftvthek") + + execute { + isDeviceRootedFingeprint.method.returnEarly(false) + } +} \ No newline at end of file From d4f05351e1b96dc68ecbdf0f88e191611d24e371 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 29 Jul 2025 08:33:08 +0000 Subject: [PATCH 05/33] chore: Release v5.33.0-dev.2 [skip ci] # [5.33.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.1...v5.33.0-dev.2) (2025-07-29) ### Features * **ORF ON:** Add `Remove root detection` patch ([#5551](https://github.com/ReVanced/revanced-patches/issues/5551)) ([d92362b](https://github.com/ReVanced/revanced-patches/commit/d92362b0d9803f00af6ba9700eccc7afd69a619a)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8c6054a6..afb07162f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.1...v5.33.0-dev.2) (2025-07-29) + + +### Features + +* **ORF ON:** Add `Remove root detection` patch ([#5551](https://github.com/ReVanced/revanced-patches/issues/5551)) ([6c6aa35](https://github.com/ReVanced/revanced-patches/commit/6c6aa35411a139dddc3a15dd757fbeded5d1a0a3)) + # [5.33.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0-dev.1) (2025-07-28) diff --git a/gradle.properties b/gradle.properties index 65e70b74a5..1de4abcf5b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.1 +version = 5.33.0-dev.2 From a4817dfdd0ab806c1ca857e3003609f8a88920f0 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:03:21 -0400 Subject: [PATCH 06/33] fix(YouTube - Playback speed): Use old speed menu for player button if enabled --- .../patches/components/PlaybackSpeedMenuFilter.java | 3 +-- .../youtube/videoplayer/PlaybackSpeedDialogButton.java | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java index 78ce3595d5..852b33a6d0 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java @@ -34,8 +34,7 @@ public final class PlaybackSpeedMenuFilter extends Filter { Settings.CUSTOM_SPEED_MENU, "playback_speed_sheet_content.eml-js"); - - addPathCallbacks(playbackRateSelectorGroup); + addPathCallbacks(playbackRateSelectorGroup, oldPlaybackMenuGroup); } @Override diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java index a365222e0d..cb4545cfbe 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java @@ -9,9 +9,6 @@ import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.extension.youtube.settings.Settings; -import static app.revanced.extension.shared.StringRef.str; -import static app.revanced.extension.shared.Utils.showToastShort; - @SuppressWarnings("unused") public class PlaybackSpeedDialogButton { @Nullable @@ -29,7 +26,11 @@ public class PlaybackSpeedDialogButton { Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get, view -> { try { - CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext()); + if (Settings.RESTORE_OLD_SPEED_MENU.get()) { + CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu(); + } else { + CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext()); + } } catch (Exception ex) { Logger.printException(() -> "speed button onClick failure", ex); } From 98114e5bde283dac3ae409b4ee90ea55aef49b97 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 30 Jul 2025 10:06:04 +0000 Subject: [PATCH 07/33] chore: Release v5.33.0-dev.3 [skip ci] # [5.33.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.2...v5.33.0-dev.3) (2025-07-30) ### Bug Fixes * **YouTube - Playback speed:** Use old speed menu for player button if enabled ([a4817df](https://github.com/ReVanced/revanced-patches/commit/a4817dfdd0ab806c1ca857e3003609f8a88920f0)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afb07162f2..9332d32eb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.2...v5.33.0-dev.3) (2025-07-30) + + +### Bug Fixes + +* **YouTube - Playback speed:** Use old speed menu for player button if enabled ([1e8f436](https://github.com/ReVanced/revanced-patches/commit/1e8f4368e117f4b278c24709231cb32546e46dc0)) + # [5.33.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.1...v5.33.0-dev.2) (2025-07-29) diff --git a/gradle.properties b/gradle.properties index 1de4abcf5b..d0815b20f1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.2 +version = 5.33.0-dev.3 From 5d08fdddb8cc690ddf1811ef608b3fdbf7651fe1 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 30 Jul 2025 09:18:20 -0400 Subject: [PATCH 08/33] perf(YouTube): Filter identifier callback only on root component creation (#5558) --- .../youtube/patches/components/AdsFilter.java | 6 +-- .../AdvancedVideoQualityMenuFilter.java | 4 +- .../patches/components/ButtonsFilter.java | 6 +-- .../patches/components/CommentsFilter.java | 6 +-- .../patches/components/CustomFilter.java | 5 +-- .../DescriptionComponentsFilter.java | 8 ++-- .../youtube/patches/components/Filter.java | 7 ++-- .../components/KeywordContentFilter.java | 4 +- .../components/LayoutComponentsFilter.java | 8 ++-- .../patches/components/LithoFilterPatch.java | 39 +++++++++---------- .../components/PlaybackSpeedMenuFilter.java | 4 +- .../PlayerFlyoutMenuItemsFilter.java | 8 ++-- .../ReturnYouTubeDislikeFilter.java | 6 +-- .../patches/components/ShortsFilter.java | 15 +++---- .../misc/litho/filter/LithoFilterPatch.kt | 2 +- 15 files changed, 55 insertions(+), 73 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java index 6128af0a6a..027fdd84a3 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java @@ -6,8 +6,6 @@ import android.app.Instrumentation; import android.view.KeyEvent; import android.view.View; -import androidx.annotation.Nullable; - import java.util.List; import app.revanced.extension.shared.Logger; @@ -155,10 +153,10 @@ public final class AdsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (matchedGroup == playerShoppingShelf) { - return contentIndex == 0 && playerShoppingShelfBuffer.check(protobufBufferArray).isFiltered(); + return contentIndex == 0 && playerShoppingShelfBuffer.check(buffer).isFiltered(); } if (exceptions.matches(path)) { diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdvancedVideoQualityMenuFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdvancedVideoQualityMenuFilter.java index 9027db5dbc..fb64dd81d3 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdvancedVideoQualityMenuFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdvancedVideoQualityMenuFilter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import app.revanced.extension.youtube.patches.playback.quality.AdvancedVideoQualityMenuPatch; import app.revanced.extension.youtube.settings.Settings; @@ -21,7 +19,7 @@ public final class AdvancedVideoQualityMenuFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { isVideoQualityMenuVisible = true; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ButtonsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ButtonsFilter.java index 5773baa28a..42e428fe98 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ButtonsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ButtonsFilter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import app.revanced.extension.youtube.settings.Settings; @SuppressWarnings("unused") @@ -100,7 +98,7 @@ final class ButtonsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (matchedGroup == likeSubscribeGlow) { return (path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX)) @@ -117,7 +115,7 @@ final class ButtonsFilter extends Filter { // Make sure the current path is the right one // to avoid false positives. return path.startsWith(VIDEO_ACTION_BAR_PATH) - && bufferButtonsGroupList.check(protobufBufferArray).isFiltered(); + && bufferButtonsGroupList.check(buffer).isFiltered(); } return true; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CommentsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CommentsFilter.java index b2aabe03ee..5fc04bc742 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CommentsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CommentsFilter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.shared.PlayerType; @@ -87,12 +85,12 @@ final class CommentsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (matchedGroup == chipBar) { // Playlist sort button uses same components and must only filter if the player is opened. return PlayerType.getCurrent().isMaximizedOrFullscreen() - && aiCommentsSummary.check(protobufBufferArray).isFiltered(); + && aiCommentsSummary.check(buffer).isFiltered(); } return true; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CustomFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CustomFilter.java index 263921fff5..cd6950717a 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CustomFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CustomFilter.java @@ -3,7 +3,6 @@ package app.revanced.extension.youtube.patches.components; import static app.revanced.extension.shared.StringRef.str; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import java.util.Arrays; import java.util.Collection; @@ -146,7 +145,7 @@ final class CustomFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { // All callbacks are custom filter groups. CustomFilterGroup custom = (CustomFilterGroup) matchedGroup; @@ -158,6 +157,6 @@ final class CustomFilter extends Filter { return true; // No buffer filter, only path filtering. } - return custom.bufferSearch.matches(protobufBufferArray); + return custom.bufferSearch.matches(buffer); } } \ No newline at end of file diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/DescriptionComponentsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/DescriptionComponentsFilter.java index 873fc9a968..c5f4ac33f9 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/DescriptionComponentsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/DescriptionComponentsFilter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import app.revanced.extension.youtube.StringTrieSearch; import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.shared.PlayerType; @@ -105,7 +103,7 @@ final class DescriptionComponentsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (matchedGroup == aiGeneratedVideoSummarySection) { @@ -116,11 +114,11 @@ final class DescriptionComponentsFilter extends Filter { if (exceptions.matches(path)) return false; if (matchedGroup == macroMarkersCarousel) { - return contentIndex == 0 && macroMarkersCarouselGroupList.check(protobufBufferArray).isFiltered(); + return contentIndex == 0 && macroMarkersCarouselGroupList.check(buffer).isFiltered(); } if (matchedGroup == horizontalShelf) { - return cellVideoAttribute.check(protobufBufferArray).isFiltered(); + return cellVideoAttribute.check(buffer).isFiltered(); } return true; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java index ddec956f03..c478e9c19a 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -42,6 +40,9 @@ abstract class Filter { /** * Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)} * if any of the groups are found. + *

+ * Note: This callback is done only during the initial component creation, + * and the path will always be an empty string. */ protected final void addIdentifierCallbacks(StringFilterGroup... groups) { identifierCallbacks.addAll(Arrays.asList(groups)); @@ -68,7 +69,7 @@ abstract class Filter { * @param contentIndex Matched index of the identifier or path. * @return True if the litho component should be filtered out. */ - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { return true; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/KeywordContentFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/KeywordContentFilter.java index 45fdcd7d28..470b650bb1 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/KeywordContentFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/KeywordContentFilter.java @@ -554,7 +554,7 @@ final class KeywordContentFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (contentIndex != 0 && matchedGroup == startsWithFilter) { return false; @@ -574,7 +574,7 @@ final class KeywordContentFilter extends Filter { } MutableReference matchRef = new MutableReference<>(); - if (bufferSearch.matches(protobufBufferArray, matchRef)) { + if (bufferSearch.matches(buffer, matchRef)) { updateStats(true, matchRef.value); return true; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java index 59b02ecdcf..311e991632 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java @@ -304,7 +304,7 @@ public final class LayoutComponentsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { // This identifier is used not only in players but also in search results: // https://github.com/ReVanced/revanced-patches/issues/3245 @@ -322,7 +322,7 @@ public final class LayoutComponentsFilter extends Filter { } if (matchedGroup == channelProfile) { - return channelProfileBuffer.check(protobufBufferArray).isFiltered(); + return channelProfileBuffer.check(buffer).isFiltered(); } if (exceptions.matches(path)) return false; // Exceptions are not filtered. @@ -331,11 +331,11 @@ public final class LayoutComponentsFilter extends Filter { return compactChannelBarInnerButton.check(path).isFiltered() // The filter may be broad, but in the context of a compactChannelBarInnerButton, // it's safe to assume that the button is the only thing that should be hidden. - && joinMembershipButton.check(protobufBufferArray).isFiltered(); + && joinMembershipButton.check(buffer).isFiltered(); } if (matchedGroup == horizontalShelves) { - return contentIndex == 0 && (hideShelves() || ticketShelf.check(protobufBufferArray).isFiltered()); + return contentIndex == 0 && (hideShelves() || ticketShelf.check(buffer).isFiltered()); } if (matchedGroup == chipBar) { diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java index 4f9e4ef329..b1dc866bf7 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java @@ -17,29 +17,28 @@ public final class LithoFilterPatch { * Simple wrapper to pass the litho parameters through the prefix search. */ private static final class LithoFilterParameters { - @Nullable final String identifier; final String path; - final byte[] protoBuffer; + final byte[] buffer; - LithoFilterParameters(@Nullable String lithoIdentifier, String lithoPath, byte[] protoBuffer) { + LithoFilterParameters(String lithoIdentifier, String lithoPath, byte[] buffer) { this.identifier = lithoIdentifier; this.path = lithoPath; - this.protoBuffer = protoBuffer; + this.buffer = buffer; } @NonNull @Override public String toString() { // Estimate the percentage of the buffer that are Strings. - StringBuilder builder = new StringBuilder(Math.max(100, protoBuffer.length / 2)); + StringBuilder builder = new StringBuilder(Math.max(100, buffer.length / 2)); builder.append( "ID: "); builder.append(identifier); builder.append(" Path: "); builder.append(path); if (Settings.DEBUG_PROTOBUFFER.get()) { builder.append(" BufferStrings: "); - findAsciiStrings(builder, protoBuffer); + findAsciiStrings(builder, buffer); } return builder.toString(); @@ -142,7 +141,7 @@ public final class LithoFilterPatch { LithoFilterParameters parameters = (LithoFilterParameters) callbackParameter; final boolean isFiltered = filter.isFiltered(parameters.identifier, - parameters.path, parameters.protoBuffer, group, type, matchedStartIndex); + parameters.path, parameters.buffer, group, type, matchedStartIndex); if (isFiltered && BaseSettings.DEBUG.get()) { if (type == Filter.FilterContentType.IDENTIFIER) { @@ -193,12 +192,8 @@ public final class LithoFilterPatch { /** * Injection point. */ - public static boolean shouldFilter(@Nullable String lithoIdentifier, StringBuilder pathBuilder) { + public static boolean isFiltered(String lithoIdentifier, StringBuilder pathBuilder) { try { - if (pathBuilder.length() == 0) { - return false; - } - byte[] buffer = bufferThreadLocal.get(); // Potentially the buffer may have been null or never set up until now. // Use an empty buffer so the litho id/path filters still work correctly. @@ -206,16 +201,20 @@ public final class LithoFilterPatch { buffer = EMPTY_BYTE_ARRAY; } - LithoFilterParameters parameter = new LithoFilterParameters( - lithoIdentifier, pathBuilder.toString(), buffer); + String path = pathBuilder.toString(); + LithoFilterParameters parameter = new LithoFilterParameters(lithoIdentifier, path, buffer); Logger.printDebug(() -> "Searching " + parameter); - if (parameter.identifier != null && identifierSearchTree.matches(parameter.identifier, parameter)) { - return true; - } - - if (pathSearchTree.matches(parameter.path, parameter)) { - return true; + if (path.isEmpty()) { + // Identifier is filtered only if there is no path, + // meaning no component or sub components have been created yet. + if (identifierSearchTree.matches(parameter.identifier, parameter)) { + return true; + } + } else { + if (pathSearchTree.matches(parameter.path, parameter)) { + return true; + } } } catch (Exception ex) { Logger.printException(() -> "Litho filter failure", ex); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java index 852b33a6d0..fc2b78ceb5 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.extension.youtube.settings.Settings; @@ -38,7 +36,7 @@ public final class PlaybackSpeedMenuFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (matchedGroup == oldPlaybackMenuGroup) { isOldPlaybackSpeedMenuVisible = true; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java index e1401f3ae9..fc2cc80992 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlayerFlyoutMenuItemsFilter.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches.components; -import androidx.annotation.Nullable; - import app.revanced.extension.shared.settings.Setting; import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch; import app.revanced.extension.youtube.settings.Settings; @@ -96,7 +94,7 @@ public class PlayerFlyoutMenuItemsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (matchedGroup == videoQualityMenuFooter) { return true; @@ -107,10 +105,10 @@ public class PlayerFlyoutMenuItemsFilter extends Filter { } // Shorts also use this player flyout panel - if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(protobufBufferArray).isFiltered()) { + if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(buffer).isFiltered()) { return false; } - return flyoutFilterGroupList.check(protobufBufferArray).isFiltered(); + return flyoutFilterGroupList.check(buffer).isFiltered(); } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java index 2164e4331b..b82cb5f563 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter.java @@ -84,15 +84,15 @@ public final class ReturnYouTubeDislikeFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (!Settings.RYD_ENABLED.get() || !Settings.RYD_SHORTS.get()) { return false; } - FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(protobufBufferArray); + FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(buffer); if (result.isFiltered()) { - String matchedVideoId = findVideoId(protobufBufferArray); + String matchedVideoId = findVideoId(buffer); // Matched video will be null if in incognito mode. // Must pass a null id to correctly clear out the current video data. // Otherwise if a Short is opened in non-incognito, then incognito is enabled and another Short is opened, diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java index f38959a193..f4fae4d32c 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java @@ -4,8 +4,6 @@ import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButt import android.view.View; -import androidx.annotation.Nullable; - import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar; import java.lang.ref.WeakReference; @@ -13,7 +11,6 @@ import java.util.Arrays; import java.util.List; import app.revanced.extension.shared.Logger; -import app.revanced.extension.shared.Utils; import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.shared.NavigationBar; import app.revanced.extension.youtube.shared.PlayerType; @@ -321,7 +318,7 @@ public final class ShortsFilter extends Filter { } @Override - boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, + boolean isFiltered(String identifier, String path, byte[] buffer, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { if (contentType == FilterContentType.PATH) { if (matchedGroup == subscribeButton || matchedGroup == joinButton || matchedGroup == paidPromotionButton) { @@ -330,22 +327,22 @@ public final class ShortsFilter extends Filter { } if (matchedGroup == useSoundButton) { - return useSoundButtonBuffer.check(protobufBufferArray).isFiltered(); + return useSoundButtonBuffer.check(buffer).isFiltered(); } if (matchedGroup == useTemplateButton) { - return useTemplateButtonBuffer.check(protobufBufferArray).isFiltered(); + return useTemplateButtonBuffer.check(buffer).isFiltered(); } if (matchedGroup == shortsCompactFeedVideo) { - return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered(); + return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(buffer).isFiltered(); } // Video action buttons (comment, share, remix) have the same path. // Like and dislike are separate path filters and don't require buffer searching. if (matchedGroup == shortsActionBar) { return videoActionButton.check(path).isFiltered() - && videoActionButtonBuffer.check(protobufBufferArray).isFiltered(); + && videoActionButtonBuffer.check(buffer).isFiltered(); } if (matchedGroup == suggestedAction) { @@ -356,7 +353,7 @@ public final class ShortsFilter extends Filter { return true; } - return suggestedActionsBuffer.check(protobufBufferArray).isFiltered(); + return suggestedActionsBuffer.check(buffer).isFiltered(); } return true; diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt index 90fcbef8f7..81ae57cbb2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt @@ -156,7 +156,7 @@ val lithoFilterPatch = bytecodePatch( move-object/from16 v$freeRegister, p2 iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField iget-object v$pathRegister, v$freeRegister, $conversionContextPathBuilderField - invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->shouldFilter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z + invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->isFiltered(Ljava/lang/String;Ljava/lang/StringBuilder;)Z move-result v$freeRegister if-eqz v$freeRegister, :unfiltered From 1549ac12aaeb0fdfb552277997fe8583ab9d3184 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 30 Jul 2025 13:21:43 +0000 Subject: [PATCH 09/33] chore: Release v5.33.0-dev.4 [skip ci] # [5.33.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.3...v5.33.0-dev.4) (2025-07-30) ### Performance Improvements * **YouTube:** Filter identifier callback only on root component creation ([#5558](https://github.com/ReVanced/revanced-patches/issues/5558)) ([5d08fdd](https://github.com/ReVanced/revanced-patches/commit/5d08fdddb8cc690ddf1811ef608b3fdbf7651fe1)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9332d32eb8..31bcfe3705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.3...v5.33.0-dev.4) (2025-07-30) + + +### Performance Improvements + +* **YouTube:** Filter identifier callback only on root component creation ([#5558](https://github.com/ReVanced/revanced-patches/issues/5558)) ([ccac46e](https://github.com/ReVanced/revanced-patches/commit/ccac46eebc2e14b094454e37ef4461d48a62c53f)) + # [5.33.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.2...v5.33.0-dev.3) (2025-07-30) diff --git a/gradle.properties b/gradle.properties index d0815b20f1..7ebf7ac25f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.3 +version = 5.33.0-dev.4 From 87c39dd485017e7f6dd14083b10a90bbe9332356 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 10:31:08 -0400 Subject: [PATCH 10/33] chore(deps-dev): Bump semantic-release from 24.2.6 to 24.2.7 (#5545) --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 326563459e..0637b7a453 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "gradle-semantic-release-plugin": "^1.10.1", - "semantic-release": "^24.2.6" + "semantic-release": "^24.2.7" } }, "node_modules/@babel/code-frame": { @@ -6889,10 +6889,11 @@ "license": "MIT" }, "node_modules/semantic-release": { - "version": "24.2.6", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.6.tgz", - "integrity": "sha512-D0cwjlO5RZzHHxAcsoF1HxiRLfC3ehw+ay+zntzFs6PNX6aV0JzKNG15mpxPipBYa/l4fHly88dHvgDyqwb1Ww==", + "version": "24.2.7", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.7.tgz", + "integrity": "sha512-g7RssbTAbir1k/S7uSwSVZFfFXwpomUB9Oas0+xi9KStSCmeDXcA7rNhiskjLqvUe/Evhx8fVCT16OSa34eM5g==", "dev": true, + "license": "MIT", "dependencies": { "@semantic-release/commit-analyzer": "^13.0.0-beta.1", "@semantic-release/error": "^4.0.0", diff --git a/package.json b/package.json index 51374afe04..4ce37d34ee 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,6 @@ "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "gradle-semantic-release-plugin": "^1.10.1", - "semantic-release": "^24.2.6" + "semantic-release": "^24.2.7" } } From b1d164b4466f7225fae6ade4685560c4b1d6a504 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 31 Jul 2025 06:33:12 -0400 Subject: [PATCH 11/33] fix(YouTube - Litho filter): Correctly filter identifier of older YouTube targets --- .../youtube/patches/components/Filter.java | 2 -- .../patches/components/LithoFilterPatch.java | 31 ++++++++++--------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java index c478e9c19a..454c03338b 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/Filter.java @@ -41,8 +41,6 @@ abstract class Filter { * Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)} * if any of the groups are found. *

- * Note: This callback is done only during the initial component creation, - * and the path will always be an empty string. */ protected final void addIdentifierCallbacks(StringFilterGroup... groups) { identifierCallbacks.addAll(Arrays.asList(groups)); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java index b1dc866bf7..e2ed04e631 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java @@ -127,14 +127,14 @@ public final class LithoFilterPatch { private static void filterUsingCallbacks(StringTrieSearch pathSearchTree, Filter filter, List groups, Filter.FilterContentType type) { + String filterSimpleName = filter.getClass().getSimpleName(); + for (StringFilterGroup group : groups) { if (!group.includeInSearch()) { continue; } for (String pattern : group.filters) { - String filterSimpleName = filter.getClass().getSimpleName(); - pathSearchTree.addPattern(pattern, (textSearched, matchedStartIndex, matchedLength, callbackParameter) -> { if (!group.isEnabled()) return false; @@ -162,6 +162,7 @@ public final class LithoFilterPatch { /** * Injection point. Called off the main thread. + * Targets 20.22+ */ public static void setProtoBuffer(byte[] buffer) { // Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes. @@ -194,6 +195,10 @@ public final class LithoFilterPatch { */ public static boolean isFiltered(String lithoIdentifier, StringBuilder pathBuilder) { try { + if (lithoIdentifier.isEmpty() && pathBuilder.length() == 0) { + return false; + } + byte[] buffer = bufferThreadLocal.get(); // Potentially the buffer may have been null or never set up until now. // Use an empty buffer so the litho id/path filters still work correctly. @@ -201,23 +206,19 @@ public final class LithoFilterPatch { buffer = EMPTY_BYTE_ARRAY; } - String path = pathBuilder.toString(); - LithoFilterParameters parameter = new LithoFilterParameters(lithoIdentifier, path, buffer); + LithoFilterParameters parameter = new LithoFilterParameters( + lithoIdentifier, pathBuilder.toString(), buffer); Logger.printDebug(() -> "Searching " + parameter); - if (path.isEmpty()) { - // Identifier is filtered only if there is no path, - // meaning no component or sub components have been created yet. - if (identifierSearchTree.matches(parameter.identifier, parameter)) { - return true; - } - } else { - if (pathSearchTree.matches(parameter.path, parameter)) { - return true; - } + if (identifierSearchTree.matches(parameter.identifier, parameter)) { + return true; + } + + if (pathSearchTree.matches(parameter.path, parameter)) { + return true; } } catch (Exception ex) { - Logger.printException(() -> "Litho filter failure", ex); + Logger.printException(() -> "isFiltered failure", ex); } return false; From ae6dd23d0898e6d5ca24e24939f294a668f82801 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 06:33:31 -0400 Subject: [PATCH 12/33] chore: Sync translations (#5564) --- .../addresources/values-az-rAZ/strings.xml | 3 +++ .../addresources/values-ja-rJP/strings.xml | 26 +++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml index 455d53835e..d73054e6e6 100644 --- a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml +++ b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml @@ -1468,6 +1468,9 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər Fərdi oynatma sürəti siyahısı Fərdi sürət siyahısı göstərilir Fərdi sürət siyahısı göstərilmir + Köhnə oynatma sürəti menyusunu bərpa et + Köhnə sürət menyusu göstərilir + Müasir sürət menyusu göstərilir Fərdi oynatma sürəti Fərdi oynatma sürətlərini əlavə et və ya dəyiş Fərdi sürətlər %s dəyərindən az olmalıdır diff --git a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml index 172f3c2455..043f12f7b2 100644 --- a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml +++ b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml @@ -965,7 +965,7 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に シークバー サムネイルは、動画の再生中の画質と同じ画質になります。 この機能は、非常に高速なインターネット接続を使用して 720P 以下の画質で動画を視聴する場合に最適です。" - シーク中のサムネイルを旧バージョンに戻す + 古いシークバー サムネイルを復元 シーク中のサムネイルはシークバーの上に表示されます シーク中のサムネイルはプレーヤー画面全体に表示されます @@ -1199,8 +1199,8 @@ Automotive レイアウト 再び無効にする場合には、UI のバグを防ぐためにアプリデータを消去することをお勧めします。" アプリバージョン - 19.35.36 - ショート動画プレーヤーのアイコンが旧バージョン - 19.01.34 - ナビゲーション アイコンが旧バージョン + 19.35.36 - 古いショート プレーヤーのアイコンを復元 + 19.01.34 - 古いナビゲーション アイコンを復元 スタート画面を変更 @@ -1466,16 +1466,16 @@ Automotive レイアウト ボタンはオーバーレイに表示されません - カスタムした再生速度リストを使用する - カスタムした再生速度リストが表示されます - デフォルトの再生速度リストが表示されます + カスタム再生速度メニュー + カスタム再生速度リストが再生速度メニューに表示されます + デフォルトの再生速度リストが再生速度メニューに表示されます 古い再生速度メニューを復元 - 古い速度メニューが表示されます - 最新の速度メニューが表示されます + 古いスタイルの再生速度メニューが表示されます + 新しいスタイルの再生速度メニューが表示されます カスタム再生速度リスト - カスタム再生速度リストを編集します + カスタム再生速度を追加または変更します 再生速度は %s 未満である必要があります - カスタム再生速度リストが無効です + カスタム再生速度が無効です 自動 長押し倍速再生の速度 再生速度の範囲は 0-8 で、0 および 8 は含まれません @@ -1496,9 +1496,9 @@ Automotive レイアウト HDR 動画は有効です - 画質の詳細設定メニューを使用する - 画質設定メニューとして詳細設定メニューが表示されます - 通常の画質設定メニューが表示されます + 画質の詳細設定メニューを表示 + 画質メニューとして詳細設定メニューが表示されます + 通常の画質メニューが表示されます スライドしてシークする機能を有効にする From 7b8ca9c01860088213265555142b4a930f412606 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 31 Jul 2025 10:35:51 +0000 Subject: [PATCH 13/33] chore: Release v5.33.0-dev.5 [skip ci] # [5.33.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.4...v5.33.0-dev.5) (2025-07-31) ### Bug Fixes * **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([b1d164b](https://github.com/ReVanced/revanced-patches/commit/b1d164b4466f7225fae6ade4685560c4b1d6a504)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31bcfe3705..acec8b671c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.4...v5.33.0-dev.5) (2025-07-31) + + +### Bug Fixes + +* **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([bf29d69](https://github.com/ReVanced/revanced-patches/commit/bf29d6909e389819bad878ad3b94bbc90d823cc9)) + # [5.33.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.3...v5.33.0-dev.4) (2025-07-30) diff --git a/gradle.properties b/gradle.properties index 7ebf7ac25f..e378c12354 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.4 +version = 5.33.0-dev.5 From 9ccf13b6805e669fce81453422c92bc1cbf6a060 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 14:27:05 -0400 Subject: [PATCH 14/33] chore: Sync translations (#5567) --- .../addresources/values-fi-rFI/strings.xml | 3 + .../addresources/values-tr-rTR/strings.xml | 148 +++++++++--------- 2 files changed, 77 insertions(+), 74 deletions(-) diff --git a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml index edd6a975db..565c2707fa 100644 --- a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml +++ b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml @@ -1469,6 +1469,9 @@ Tämä voi avata korkealaatuisemmat videot" Mukautettu toistonopeusvalikko Mukautettu nopeusvalikko näytetään Mukautettua nopeusvalikkoa ei näytetä + Palauta vanha toistonopeusvalikko + Vanha nopeusvalikko näytetään + Moderni nopeusvalikko näytetään Mukautetut toistonopeudet Lisää tai muuta mukautettuja toistonopeuksia Mukautettujen nopeuksien tulee olla alle %s diff --git a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml index 13d59c6b78..b1fb862156 100644 --- a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml +++ b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml @@ -299,28 +299,28 @@ Bir Doodle şu anda bölgenizde gösteriliyorsa ve bu gizleme ayarı açıksa, a \'Sizin için\' rafını gizle Sizin İçin rafı gizli Sizin İçin rafı görünür - Bağlantı önizlemesini gizle - Bağlantı önizlemesi gizli - Bağlantı önizlemesi görünür + Bağlantı ön izlemesini gizle + Bağlantı ön izlemesi gizli + Bağlantı ön izlemesi görünür Üyeler rafını gizle Üyeler rafı gizli - Üyeler rafı gösteriliyor + Üyeler rafı görünür \'Topluluğu Ziyaret Et\' düğmesini gizle Topluluğu Ziyaret Et düğmesi gizli Topluluğu Ziyaret Et düğmesi görünür - Kanal sayfalarındaki \'Mağazayı ziyaret et\' düğmesini gizle - Mağazayı Ziyaret Et düğmesi gizli - Mağazayı Ziyaret Et düğmesi görünür + \'Mağazayı ziyaret et\' düğmesini gizle + Mağazayı ziyaret et düğmesi gizli + Mağazayı ziyaret et düğmesi görünür Yorumlar Yorumlar kısmı bileşenlerini gizle veya göster Yapay zeka sohbet özetini gizle Yapay zeka sohbet özeti gizli - Yapay zeka sohbet özeti gösteriliyor - Yapay zeka yorumlar özetini gizle - Yapay zeka yorum özeti gizli - Yapay zeka yorum özeti gösteriliyor + Yapay zeka sohbet özeti görünür + Yapay zeka yorumların özetini gizle + Yapay zeka yorumların özeti gizli + Yapay zeka yorumların özeti görünür Kanal yönergelerini gizle Kanal yönergeleri gizli Kanal yönergeleri görünür @@ -342,7 +342,7 @@ Bir Doodle şu anda bölgenizde gösteriliyorsa ve bu gizleme ayarı açıksa, a Teşekkürler düğmesini gizle Teşekkürler düğmesi gizli Teşekkürler düğmesi görünür - Zaman Damgası düğmesini gizle + Zaman damgası düğmesini gizle Zaman damgası düğmesi gizli Zaman damgası düğmesi görünür Özel filtre @@ -555,43 +555,43 @@ Ekranın sağ tarafında dikey olarak kaydırarak sesi ayarlayın" Beğenme ve Beğenmeme düğmeleri gizli Beğenme ve Beğenmeme düğmeleri görünür - Paylaşmayı gizle - Paylaşma düğmesi gizli - Paylaşma düğmesi görünür + Paylaş\'ı gizle + Paylaş düğmesi gizli + Paylaş düğmesi görünür - Reklamları Durdur\'u Gizle - Reklamları durdur düğmesi gizlendi - Reklamları durdur düğmesi gösterildi + Reklamları durdur\'u Gizle + Reklamları durdur düğmesi gizli + Reklamları durdur düğmesi görünür - Bildirmeyi gizle - Bildirme düğmesi gizli - Bildirme düğmesi görünür + Bildir\'i gizle + Bildir düğmesi gizli + Bildir düğmesi görünür - Remix düğmesini gizle + Remix\'i gizle Remix düğmesi gizli Remix düğmesi görünür - İndirmeyi gizle - İndirme düğmesi gizli - İndirme düğmesi görünür + İndir\'i gizle + İndir düğmesi gizli + İndir düğmesi görünür - Teşekkürler düğmesini gizle + Teşekkürler\'i gizle Teşekkürler düğmesi gizli Teşekkürler düğmesi görünür - \'Sor\'u gizle + Sor\'u gizle Sor düğmesi gizli Sor düğmesi görünür - Klip düğmesini gizle + Klip\'i gizle Klip düğmesi gizli Klip düğmesi görünür Kaydet\'i Gizle - Kaydet düğmesi gizlendi - Kaydet düğmesi gösterildi + Kaydet düğmesi gizli + Kaydet düğmesi görünür Gezinme düğmeleri @@ -722,8 +722,8 @@ Ses parçası menüsünü göstermek için 'Video akışlarını taklit et' ayar Tam ekranda ambiyans modunu devre dışı bırak - Tam ekranda ambiyans modu devre dışı - Tam ekranda ambiyans modu etkin + Ambiyans modu devre dışı + Ambiyans modu etkin Bilgi kartlarını gizle @@ -736,13 +736,13 @@ Ses parçası menüsünü göstermek için 'Video akışlarını taklit et' ayar Kayan sayı animasyonları etkin - Video oynatıcı kaydırma çubuğunu gizle - Video oynatıcısındaki zaman çubuğu gizli - Video oynatıcısındaki zaman çubuğu görünür + Video oynatıcısı zaman çubuğunu gizle + Video oynatıcısı zaman çubuğu gizli + Video oynatıcısı zaman çubuğu görünür - Video küçük resimleri kaydırma çubuğunu gizle - Video küçük resimleri kaydırma çubuğu gizli - Video küçük resimleri kaydırma çubuğu gösteriliyor + Video kapak fotoğrafı zaman çubuğunu gizle + Video kapak fotoğrafı zaman çubuğu gizli + Video kapak fotoğrafı zaman çubuğu gösteriliyor Shorts oynatıcı @@ -751,22 +751,22 @@ Ses parçası menüsünü göstermek için 'Video akışlarını taklit et' ayar Ana Sayfa akışında Shorts\'u gizle Ana Sayfa akışında ve ilgili videolarda gizli Ana Sayfa akışında ve ilgili videolarda görünür - Arama sonuçlarında Shorts videolarını gizle + Arama sonuçlarında Shorts\'u gizle Arama sonuçlarında gizli Arama sonuçlarında görünür Abonelikler akışında Shorts\'u gizle Abonelikler akışında gizli Abonelikler akışında görünür - Shorts\'u izleme geçmişinde gizle + İzleme geçmişinde Shorts\'u gizle İzleme geçmişinde gizli İzleme geçmişinde görünür Süper Teşekkürler düğmesini gizle - Süper Teşekkürler satın al düğmesi gizli - Süper Teşekkürler satın al düğmesi görünür + Süper Teşekkürler düğmesi gizli + Süper Teşekkürler düğmesi görünür Efekt düğmesini gizle Efekt düğmesi gizli - Efekt düğmesi gösteriliyor + Efekt düğmesi görünür Yeşil ekran düğmesini gizle Yeşil ekran düğmesi gizli Yeşil ekran düğmesi görünür @@ -849,9 +849,9 @@ Ses parçası menüsünü göstermek için 'Video akışlarını taklit et' ayar Video başlığı gizli Video başlığı görünür Ses bilgisi etiketini gizle - Ses meta veri etiketi gizli - Ses meta veri etiketi görünür - Video bağlantı etiketini gizle + Ses bilgisi etiketi gizli + Ses bilgisi etiketi görünür + Video bağlantısı etiketini gizle Video bağlantısı etiketi gizli Video bağlantısı etiketi görünür Gezinme çubuğunu gizle @@ -864,12 +864,12 @@ Ses parçası menüsünü göstermek için 'Video akışlarını taklit et' ayar Otomatik oynatma YouTube ayarlarından değiştirilebilir: Ayarlar → Oynatma → Sonraki videoyu otomatik oynat" - Bitiş ekranı önerilen videosu gösteriliyor + Bitiş ekranı önerilen videosu görünür - İlgili videolar bindirmesini gizle - Tam ekrandaki ilgili videolar bindirmesi gizli - Tam ekrandaki ilgili videolar bindirmesi görünür + İlgili videolar katmanını gizle + Tam ekrandaki ilgili videolar katmanı gizli + Tam ekrandaki ilgili videolar katmanı görünür Video zaman damgasını gizle @@ -894,7 +894,7 @@ Ayarlar → Oynatma → Sonraki videoyu otomatik oynat" Videolar tam ekranda açılmaz - Oynatıcı paneli opaklığı + Oynatıcı katmanı opaklığı 0-100 arasında opaklık değeri, 0 şeffaftır Oynatıcı katmanı opaklığı 0-100 arasında olmalıdır @@ -984,13 +984,13 @@ Bu özellik, 720p veya daha düşük video kalitesi ve çok hızlı bir internet Atlama düğmesini otomatik olarak gizle Atlama düğmesi birkaç saniye sonra gizlenir Atlama düğmesi bütün kısım boyunca gösterilir - Atla düğmesi süresi - Atla ve öne çıkanlara atla düğmelerini otomatik olarak gizlemeden önce ne kadar süreyle göster + Atlama düğmesi süresi + Atla ve vurguya atla düğmelerinin otomatik olarak gizlenmeden önce ne kadar süre gösterileceği Atlamayı geri al bildirimini göster - Bildirim, bir segment otomatik olarak atlandığında gösterilir. Atlamayı geri almak için bildirimine dokunun - Toast gösterilmiyor - Atlama toast süresi - Geri al atla bildirimini ne kadar süreyle göster + Bir kısım otomatik olarak atlandığında bildirim gösterilir. Atlamayı geri almak için bildirime dokunun + Bildirim gösterilmez + Atlama bildirimi süresi + Atlamayı geri alma bildiriminin ne kadar süre gösterileceği 1 saniye 2 saniye 3 saniye @@ -1001,14 +1001,14 @@ Bu özellik, 720p veya daha düşük video kalitesi ve çok hızlı bir internet 8 saniye 9 saniye 10 saniye - Kısımlar çıkarıldığında kalan video süresini göster - Tüm segmentler çıkarıldıktan sonra video uzunluğu arama çubuğunda gösterilir - Tam video uzunluğu gösterilir + Kısımlar olmadan video süresini göster + Video süresi eksi bütün kısımların süresi zaman çubuğunda görünür + Tam video süresi görünür Yeni kısım oluşturma Yeni kısım oluşturma düğmesini göster Yeni kısım oluşturma düğmesi gösterilir Yeni kısım oluşturma düğmesi gösterilmez - Yeni kısım oluştururken atlama süresi + Yeni kısım oluştururkenki atlama süresi Yeni bölüm oluştururkenki atlama düğmelerinin atlayacağı milisaniye miktarı Değer pozitif bir sayı olmalıdır Yönergeleri görüntüle @@ -1018,10 +1018,10 @@ Bu özellik, 720p veya daha düşük video kalitesi ve çok hızlı bir internet Okudum Göster Genel - API kullanılamadığında bir tost bildirimi göster - SponsorBlock kullanılamadığında tost bildirimi gösterilir - SponsorBlock kullanılamadığında tost bildirimi gösterilmez - Atlama sayısı izlemeyi etkinleştir + API kullanılamadığında bir bildirim göster + SponsorBlock kullanılamadığında bir bildirim gösterilir + SponsorBlock kullanılamadığında bildirim gösterilmez + Atlama sayısı takibini etkinleştir SponsorBlock liderlik tablosunun ne kadar zaman kazanıldığını bilmesini sağlar. Her bir kısım atlandığında liderlik tablosuna bir mesaj gönderilir Atlama sayısı izleme etkin değil En az kısım süresi @@ -1103,7 +1103,7 @@ Kullanıcı kimliğiniz bir parola gibidir ve asla paylaşılmamalıdır. Zaman çubuğunda göster Devre dışı bırak Kısım gönderilemedi: %s - SponsorBlock geçici olarak kullanılamıyor + SponsorBlock geçici olarak kapalı Kısım gönderilemedi (durum: %1$d %2$s) Kısım gönderilemiyor. Kullanıcı veya IP\'den çok fazla istek Kısım gönderilemiyor: %s @@ -1120,7 +1120,7 @@ Aynısı mevcut" Olumlu oy Olumsuz oy Kategori değiştir - Oylanılacak bir kısım yok + Oylanılacak kısım bulunmuyor %1$s - %2$s Kısım kategorisini seçin @@ -1218,7 +1218,7 @@ Daha sonra kapatılırsa, arayüz hatalarını önlemek için uygulama verilerin Canlı yayın Filmler Müzik - Habercilik + Haberler Bildirimler Oynatma listeleri Arama @@ -1228,7 +1228,7 @@ Daha sonra kapatılırsa, arayüz hatalarını önlemek için uygulama verilerin Trendler Sanal Gerçeklik Daha sonra izle - Sizin klipleriniz + Klipleriniz Başlangıç sayfasını her zaman değiştir "Başlangıç sayfası her zaman değiştirilir @@ -1248,8 +1248,8 @@ Kısıtlama: Araç çubuğundaki geri düğmesini kullanmak işe yaramayabilir"< Shorts\'u otomatik oynat - Sıradaki Shorts videosu otomatik olarak oynatılacak - Aynı Shorts videosu sürekli döngü yapacak + Shorts otomatik oynatılacak + Aynı Shorts videosu sürekli yeniden oynayacak Arka planda Shorts\'u otomatik oynat Shorts arka planda otomatik oynatılacak Shorts arka planda döngüde olacak @@ -1476,7 +1476,7 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Özel oynatma hızı menüsü Özel oynatma hızı menüsü gösterilir Özel oynatma hızı menüsü gösterilmez - Eski oynatma hızı menüsünü geri yükle + Eski oynatma hızı menüsünü geri getir Eski hız menüsü gösterilir Modern hız menüsü gösterilir Özel oynatma hızları @@ -1490,10 +1490,10 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Oynatma hızı değişikliklerini hatırla Oynatma hızı değişiklikleri tüm videolara uygulanır - Oynatma hızı değişiklikleri yalnızca geçerli videoya uygulanır + Oynatma hızı değişiklikleri yalnızca mevcut videoya uygulanır Oynatma hızı değişikliklerinde bildirim göster Varsayılan oynatma hızı değiştirildiğinde bir bildirim gösterilir - Varsayılan oynatma hızı değiştirildiğinde bir bildirim gösterilmez. + Varsayılan oynatma hızı değiştirildiğinde bir bildirim gösterilmez Varsayılan oynatma hızı Varsayılan hız %s olarak ayarlandı From 1adbd563b21b84bf19cb9eb87bb76bef00d40316 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 31 Jul 2025 14:27:17 -0400 Subject: [PATCH 15/33] fix(YouTube - Video quality): Use 1080p enhanced bitrate for Premium users (#5565) --- .../quality/RememberVideoQualityPatch.java | 128 ++++++++----- .../innertube/model/media/VideoQuality.java | 12 ++ .../patches/youtube/shared/Fingerprints.kt | 2 +- .../youtube/video/information/Fingerprints.kt | 4 +- .../information/VideoInformationPatch.kt | 4 +- .../youtube/video/quality/Fingerprints.kt | 32 +++- .../quality/RememberVideoQualityPatch.kt | 175 +++++++++++++----- 7 files changed, 256 insertions(+), 101 deletions(-) create mode 100644 extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java index 82e75058b3..59d76324e9 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java @@ -5,9 +5,9 @@ import static app.revanced.extension.shared.Utils.NetworkType; import androidx.annotation.Nullable; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; +import com.google.android.libraries.youtube.innertube.model.media.VideoQuality; + +import java.util.Arrays; import java.util.List; import app.revanced.extension.shared.Logger; @@ -20,6 +20,14 @@ import app.revanced.extension.youtube.shared.ShortsPlayerState; @SuppressWarnings("unused") public class RememberVideoQualityPatch { + + /** + * Interface to use obfuscated methods. + */ + public interface VideoQualityMenuInterface { + void patch_setMenuIndexFromQuality(VideoQuality quality); + } + private static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2; private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI; private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE; @@ -30,7 +38,8 @@ public class RememberVideoQualityPatch { /** * If the user selected a new quality from the flyout menu, - * and {@link Settings#REMEMBER_VIDEO_QUALITY_LAST_SELECTED} is enabled. + * and {@link Settings#REMEMBER_VIDEO_QUALITY_LAST_SELECTED} + * or {@link Settings#REMEMBER_SHORTS_QUALITY_LAST_SELECTED} is enabled. */ private static boolean userChangedDefaultQuality; @@ -40,10 +49,10 @@ public class RememberVideoQualityPatch { private static int userSelectedQualityIndex; /** - * The available qualities of the current video in human readable form: [1080, 720, 480] + * The available qualities of the current video. */ @Nullable - private static List videoQualities; + private static List videoQualities; private static boolean shouldRememberVideoQuality() { BooleanSetting preference = ShortsPlayerState.isOpen() ? @@ -52,23 +61,27 @@ public class RememberVideoQualityPatch { return preference.get(); } - private static void changeDefaultQuality(int defaultQuality) { + private static void changeDefaultQuality(int qualityResolution) { + final boolean shortPlayerOpen = ShortsPlayerState.isOpen(); String networkTypeMessage; - boolean useShortsPreference = ShortsPlayerState.isOpen(); + IntegerSetting qualitySetting; if (Utils.getNetworkType() == NetworkType.MOBILE) { - if (useShortsPreference) shortsQualityMobile.save(defaultQuality); - else videoQualityMobile.save(defaultQuality); networkTypeMessage = str("revanced_remember_video_quality_mobile"); + qualitySetting = shortPlayerOpen ? shortsQualityMobile : videoQualityMobile; } else { - if (useShortsPreference) shortsQualityWifi.save(defaultQuality); - else videoQualityWifi.save(defaultQuality); networkTypeMessage = str("revanced_remember_video_quality_wifi"); + qualitySetting = shortPlayerOpen ? shortsQualityWifi : videoQualityWifi; } + qualitySetting.save(qualityResolution); + if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get()) Utils.showToastShort(str( - useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast", - networkTypeMessage, (defaultQuality + "p") - )); + shortPlayerOpen + ? "revanced_remember_video_quality_toast_shorts" + : "revanced_remember_video_quality_toast", + networkTypeMessage, + (qualityResolution + "p")) + ); } /** @@ -77,9 +90,11 @@ public class RememberVideoQualityPatch { * @param qualities Video qualities available, ordered from largest to smallest, with index 0 being the 'automatic' value of -2 * @param originalQualityIndex quality index to use, as chosen by YouTube */ - public static int setVideoQuality(Object[] qualities, final int originalQualityIndex, Object qInterface, String qIndexMethod) { + public static int setVideoQuality(VideoQuality[] qualities, VideoQualityMenuInterface menu, int originalQualityIndex) { try { - boolean useShortsPreference = ShortsPlayerState.isOpen(); + Utils.verifyOnMainThread(); + + final boolean useShortsPreference = ShortsPlayerState.isOpen(); final int preferredQuality = Utils.getNetworkType() == NetworkType.MOBILE ? (useShortsPreference ? shortsQualityMobile : videoQualityMobile).get() : (useShortsPreference ? shortsQualityWifi : videoQualityWifi).get(); @@ -89,16 +104,8 @@ public class RememberVideoQualityPatch { } if (videoQualities == null || videoQualities.size() != qualities.length) { - videoQualities = new ArrayList<>(qualities.length); - for (Object streamQuality : qualities) { - for (Field field : streamQuality.getClass().getFields()) { - if (field.getType().isAssignableFrom(Integer.TYPE) - && field.getName().length() <= 2) { - videoQualities.add(field.getInt(streamQuality)); - } - } - } - + videoQualities = Arrays.asList(qualities); + // After changing videos the qualities can initially be for the prior video. // So if the qualities have changed an update is needed. qualityNeedsUpdating = true; @@ -107,9 +114,9 @@ public class RememberVideoQualityPatch { if (userChangedDefaultQuality) { userChangedDefaultQuality = false; - final int quality = videoQualities.get(userSelectedQualityIndex); + VideoQuality quality = videoQualities.get(userSelectedQualityIndex); Logger.printDebug(() -> "User changed default quality to: " + quality); - changeDefaultQuality(quality); + changeDefaultQuality(quality.patch_getResolution()); return userSelectedQualityIndex; } @@ -119,65 +126,86 @@ public class RememberVideoQualityPatch { qualityNeedsUpdating = false; // Find the highest quality that is equal to or less than the preferred. - int qualityToUse = videoQualities.get(0); // first element is automatic mode + VideoQuality qualityToUse = videoQualities.get(0); // First element is automatic mode. int qualityIndexToUse = 0; int i = 0; - for (Integer quality : videoQualities) { - if (quality <= preferredQuality && qualityToUse < quality) { + for (VideoQuality quality : videoQualities) { + final int qualityResolution = quality.patch_getResolution(); + if (qualityResolution > qualityToUse.patch_getResolution() && qualityResolution <= preferredQuality) { qualityToUse = quality; qualityIndexToUse = i; + break; } i++; } // If the desired quality index is equal to the original index, // then the video is already set to the desired default quality. - final int qualityToUseFinal = qualityToUse; + String qualityToUseName = qualityToUse.patch_getQualityName(); if (qualityIndexToUse == originalQualityIndex) { - // On first load of a new video, if the UI video quality flyout menu - // is not updated then it will still show 'Auto' (ie: Auto (480p)), - // even though it's already set to the desired resolution. - // - // To prevent confusion, set the video index anyways (even if it matches the existing index) - // as that will force the UI picker to not display "Auto". - Logger.printDebug(() -> "Video is already preferred quality: " + qualityToUseFinal); + Logger.printDebug(() -> "Video is already preferred quality: " + qualityToUseName); } else { Logger.printDebug(() -> "Changing video quality from: " - + videoQualities.get(originalQualityIndex) + " to: " + qualityToUseFinal); + + videoQualities.get(originalQualityIndex).patch_getQualityName() + + " to: " + qualityToUseName); } - Method m = qInterface.getClass().getMethod(qIndexMethod, Integer.TYPE); - m.invoke(qInterface, qualityToUse); + // On first load of a new video, if the video is already the desired quality + // then the quality flyout will show 'Auto' (ie: Auto (720p)). + // + // To prevent user confusion, set the video index even if the + // quality is already correct so the UI picker will not display "Auto". + menu.patch_setMenuIndexFromQuality(qualities[qualityIndexToUse]); + return qualityIndexToUse; } catch (Exception ex) { - Logger.printException(() -> "Failed to set quality", ex); + Logger.printException(() -> "setVideoQuality failure", ex); return originalQualityIndex; } } /** - * Injection point. Old quality menu. + * Injection point. Fixes bad data used by YouTube. */ - public static void userChangedQuality(int selectedQualityIndex) { + public static int fixVideoQualityResolution(String name, int quality) { + final int correctQuality = 480; + if (name.equals("480p") && quality != correctQuality) { + Logger.printDebug(() -> "Fixing bad data of " + name + " from: " + quality + + " to: " + correctQuality); + return correctQuality; + } + + return quality; + } + + /** + * Injection point. + * @param qualityIndex Element index of {@link #videoQualities}. + */ + public static void userChangedQuality(int qualityIndex) { if (shouldRememberVideoQuality()) { - userSelectedQualityIndex = selectedQualityIndex; + userSelectedQualityIndex = qualityIndex; userChangedDefaultQuality = true; } } /** - * Injection point. New quality menu. + * Injection point. + * @param videoResolution Human readable resolution: 480, 720, 1080. */ - public static void userChangedQualityInNewFlyout(int selectedQuality) { + public static void userChangedQualityInFlyout(int videoResolution) { + Utils.verifyOnMainThread(); if (!shouldRememberVideoQuality()) return; - changeDefaultQuality(selectedQuality); // Quality is human readable resolution (ie: 1080). + changeDefaultQuality(videoResolution); } /** * Injection point. */ public static void newVideoStarted(VideoInformation.PlaybackController ignoredPlayerController) { + Utils.verifyOnMainThread(); + Logger.printDebug(() -> "newVideoStarted"); qualityNeedsUpdating = true; videoQualities = null; diff --git a/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java b/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java new file mode 100644 index 0000000000..67dbc6873b --- /dev/null +++ b/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java @@ -0,0 +1,12 @@ +package com.google.android.libraries.youtube.innertube.model.media; + +public class VideoQuality { + public final String patch_getQualityName() { + throw new UnsupportedOperationException("Stub"); + } + + public final int patch_getResolution() { + throw new UnsupportedOperationException("Stub"); + } +} + diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt index 82eb0f7a94..4a9f3a020b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt @@ -121,7 +121,7 @@ internal val subtitleButtonControllerFingerprint = fingerprint { ) } -internal val newVideoQualityChangedFingerprint = fingerprint { +internal val videoQualityChangedFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt index 5157f9823e..7d711aec84 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt @@ -1,7 +1,7 @@ package app.revanced.patches.youtube.video.information import app.revanced.patcher.fingerprint -import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint +import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint import app.revanced.util.getReference import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -110,7 +110,7 @@ internal val seekRelativeFingerprint = fingerprint { } /** - * Resolves with the class found in [newVideoQualityChangedFingerprint]. + * Resolves with the class found in [videoQualityChangedFingerprint]. */ internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index 5a9c5e7406..99f0c75dea 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint +import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint import app.revanced.patches.youtube.video.playerresponse.Hook import app.revanced.patches.youtube.video.playerresponse.addPlayerResponseMethodHook import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHookPatch @@ -263,7 +263,7 @@ val videoInformationPatch = bytecodePatch( // Handle new playback speed menu. playbackSpeedMenuSpeedChangedFingerprint.match( - newVideoQualityChangedFingerprint.originalClassDef, + videoQualityChangedFingerprint.originalClassDef, ).method.apply { val index = indexOfFirstInstructionOrThrow(Opcode.IGET) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt index 5ce6da9c11..c98bdac633 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt @@ -5,6 +5,21 @@ import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;" + +internal val videoQualityFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) + parameters( + "I", // Resolution. + "Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc + "Z", + "L" + ) + custom { _, classDef -> + classDef.type == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE + } +} + /** * Matches with the class found in [videoQualitySetterFingerprint]. */ @@ -23,6 +38,22 @@ internal val videoQualityItemOnClickParentFingerprint = fingerprint { strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT") } +/** + * Resolves to class found in [videoQualityItemOnClickFingerprint]. + */ +internal val videoQualityItemOnClickFingerprint = fingerprint { + returns("V") + parameters( + "Landroid/widget/AdapterView;", + "Landroid/view/View;", + "I", + "J" + ) + custom { method, _ -> + method.name == "onItemClick" + } +} + internal val videoQualitySetterFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") @@ -37,7 +68,6 @@ internal val videoQualitySetterFingerprint = fingerprint { strings("menu_item_video_quality") } - internal val videoQualityMenuOptionsFingerprint = fingerprint { accessFlags(AccessFlags.STATIC) returns("[L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index 79e2fade40..1e42048ba6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -3,8 +3,8 @@ package app.revanced.patches.youtube.video.quality import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.ListPreference @@ -12,15 +12,21 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint +import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint import app.revanced.patches.youtube.video.information.onCreateHook import app.revanced.patches.youtube.video.information.videoInformationPatch +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.immutable.ImmutableMethod +import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch;" +private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE = + "Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch\$VideoQualityMenuInterface;" val rememberVideoQualityPatch = bytecodePatch { dependsOn( @@ -70,72 +76,151 @@ val rememberVideoQualityPatch = bytecodePatch { */ onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted") + videoQualityFingerprint.let { + // Fix bad data used by YouTube. + it.method.addInstructions( + 0, + """ + invoke-static { p2, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I + move-result p1 + """ + ) + + // Add methods to access obfuscated quality fields. + it.classDef.apply { + methods.add( + ImmutableMethod( + type, + "patch_getQualityName", + listOf(), + "Ljava/lang/String;", + AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, + null, + null, + MutableMethodImplementation(2), + ).toMutable().apply { + // Only one string field. + val qualityNameField = fields.single { field -> + field.type == "Ljava/lang/String;" + } + + addInstructions( + 0, + """ + iget-object v0, p0, $qualityNameField + return-object v0 + """ + ) + } + ) + + methods.add( + ImmutableMethod( + type, + "patch_getResolution", + listOf(), + "I", + AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, + null, + null, + MutableMethodImplementation(2), + ).toMutable().apply { + val resolutionField = fields.single { field -> + field.type == "I" + } + + addInstructions( + 0, + """ + iget v0, p0, $resolutionField + return v0 + """ + ) + } + ) + } + } + // Inject a call to set the remembered quality once a video loads. setQualityByIndexMethodClassFieldReferenceFingerprint.match( - videoQualitySetterFingerprint.originalClassDef, + videoQualitySetterFingerprint.originalClassDef ).let { match -> // This instruction refers to the field with the type that contains the setQualityByIndex method. val instructions = match.method.implementation!!.instructions - - val getOnItemClickListenerClassReference = + val onItemClickListenerClassReference = (instructions.elementAt(0) as ReferenceInstruction).reference - val getSetQualityByIndexMethodClassFieldReference = - (instructions.elementAt(1) as ReferenceInstruction).reference + val setQualityFieldReference = + ((instructions.elementAt(1) as ReferenceInstruction).reference) as FieldReference - val setQualityByIndexMethodClassFieldReference = - getSetQualityByIndexMethodClassFieldReference as FieldReference + proxy( + classes.find { classDef -> + classDef.type == setQualityFieldReference.type + }!! + ).mutableClass.apply { + // Add interface and helper methods to allow extension code to call obfuscated methods. + interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE) - val setQualityByIndexMethodClass = classes - .find { classDef -> classDef.type == setQualityByIndexMethodClassFieldReference.type }!! + // Get the name of the setQualityByIndex method. + val setQualityMenuIndexMethod = methods.single { + method -> method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE + } - // Get the name of the setQualityByIndex method. - val setQualityByIndexMethod = setQualityByIndexMethodClass.methods - .find { method -> method.parameterTypes.first() == "I" } - ?: throw PatchException("Could not find setQualityByIndex method") + methods.add( + ImmutableMethod( + type, + "patch_setMenuIndexFromQuality", + listOf( + ImmutableMethodParameter(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE, null, null) + ), + "V", + AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, + null, + null, + MutableMethodImplementation(2), + ).toMutable().apply { + addInstructions( + 0, + """ + invoke-virtual { p0, p1 }, $setQualityMenuIndexMethod + return-void + """ + ) + } + ) + } videoQualitySetterFingerprint.method.addInstructions( 0, """ # Get the object instance to invoke the setQualityByIndex method on. - iget-object v0, p0, $getOnItemClickListenerClassReference - iget-object v0, v0, $getSetQualityByIndexMethodClassFieldReference + iget-object v0, p0, $onItemClickListenerClassReference + iget-object v0, v0, $setQualityFieldReference - # Get the method name. - const-string v1, "${setQualityByIndexMethod.name}" - - # Set the quality. - # The first parameter is the array list of video qualities. - # The second parameter is the index of the selected quality. - # The register v0 stores the object instance to invoke the setQualityByIndex method on. - # The register v1 stores the name of the setQualityByIndex method. - invoke-static { p1, p2, v0, v1 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I + invoke-static { p1, v0, p2 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([$YOUTUBE_VIDEO_QUALITY_CLASS_TYPE${EXTENSION_VIDEO_QUALITY_MENU_INTERFACE}I)I move-result p2 - """, + """ ) } // Inject a call to remember the selected quality. - videoQualityItemOnClickParentFingerprint.classDef.methods.find { it.name == "onItemClick" } - ?.apply { - val listItemIndexParameter = 3 + videoQualityItemOnClickFingerprint.match( + videoQualityItemOnClickParentFingerprint.classDef + ).method.addInstruction( + 0, + "invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V" + ) + + // Inject a call to remember the user selected quality. + videoQualityChangedFingerprint.let { + it.method.apply { + val index = it.patternMatch!!.startIndex + val register = getInstruction(index).registerA addInstruction( - 0, - "invoke-static { p$listItemIndexParameter }, " + - "$EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V", + index + 1, + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQualityInFlyout(I)V", ) - } ?: throw PatchException("Failed to find onItemClick method") - - // Remember video quality if not using old layout menu. - newVideoQualityChangedFingerprint.method.apply { - val index = newVideoQualityChangedFingerprint.patternMatch!!.startIndex - val qualityRegister = getInstruction(index).registerA - - addInstruction( - index + 1, - "invoke-static { v$qualityRegister }, " + - "$EXTENSION_CLASS_DESCRIPTOR->userChangedQualityInNewFlyout(I)V", - ) + } } } } From 6e60ac6963b836d0245810bf54397db89d34d9fd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 31 Jul 2025 18:30:03 +0000 Subject: [PATCH 16/33] chore: Release v5.33.0-dev.6 [skip ci] # [5.33.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.5...v5.33.0-dev.6) (2025-07-31) ### Bug Fixes * **YouTube - Video quality:** Use 1080p enhanced bitrate for Premium users ([#5565](https://github.com/ReVanced/revanced-patches/issues/5565)) ([1adbd56](https://github.com/ReVanced/revanced-patches/commit/1adbd563b21b84bf19cb9eb87bb76bef00d40316)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acec8b671c..8e5bddf293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.5...v5.33.0-dev.6) (2025-07-31) + + +### Bug Fixes + +* **YouTube - Video quality:** Use 1080p enhanced bitrate for Premium users ([#5565](https://github.com/ReVanced/revanced-patches/issues/5565)) ([bd3ace0](https://github.com/ReVanced/revanced-patches/commit/bd3ace0bd04ccd0369adb49d63aa0cf986402346)) + # [5.33.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.4...v5.33.0-dev.5) (2025-07-31) diff --git a/gradle.properties b/gradle.properties index e378c12354..23ef8274e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.5 +version = 5.33.0-dev.6 From 7bdc32867aeefe011fdc432b52ac6165205eee9b Mon Sep 17 00:00:00 2001 From: MarcaD <152095496+MarcaDian@users.noreply.github.com> Date: Sun, 3 Aug 2025 18:23:46 +0300 Subject: [PATCH 17/33] feat(YouTube): Add player button to change video quality (#5435) Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> --- .../app/revanced/extension/shared/Utils.java | 10 + .../AdvancedVideoQualityMenuPatch.java | 24 +- .../quality/RememberVideoQualityPatch.java | 242 +++++---- .../speed/CustomPlaybackSpeedPatch.java | 8 +- .../extension/youtube/settings/Settings.java | 1 + .../ReVancedPreferenceFragment.java | 6 +- .../videoplayer/PlayerControlButton.java | 54 +- .../videoplayer/VideoQualityDialogButton.java | 476 ++++++++++++++++++ .../innertube/model/media/VideoQuality.java | 10 +- patches/api/patches.api | 4 + .../hook/RecyclerViewTreeHookPatch.kt | 1 - .../quality/AdvancedVideoQualityMenuPatch.kt | 3 +- .../youtube/video/quality/Fingerprints.kt | 2 +- .../quality/RememberVideoQualityPatch.kt | 34 +- .../video/quality/VideoQualityPatch.kt | 2 + .../button/VideoQualityDialogButtonPatch.kt | 64 +++ .../resources/addresources/values/strings.xml | 5 + ...evanced_video_quality_dialog_button_4k.xml | 9 + ...vanced_video_quality_dialog_button_fhd.xml | 9 + ...d_video_quality_dialog_button_fhd_plus.xml | 9 + ...evanced_video_quality_dialog_button_hd.xml | 9 + ...evanced_video_quality_dialog_button_ld.xml | 9 + ...vanced_video_quality_dialog_button_qhd.xml | 9 + ...evanced_video_quality_dialog_button_sd.xml | 9 + ...ed_video_quality_dialog_button_unknown.xml | 11 + .../youtube_controls_bottom_ui_container.xml | 27 + .../youtube_controls_bottom_ui_container.xml | 1 - 27 files changed, 896 insertions(+), 152 deletions(-) create mode 100644 extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java create mode 100644 patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatch.kt create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_4k.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd_plus.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_hd.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_ld.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_qhd.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_sd.xml create mode 100644 patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_unknown.xml create mode 100644 patches/src/main/resources/qualitybutton/host/layout/youtube_controls_bottom_ui_container.xml diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java index e84ac36a23..c015c06105 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java @@ -1460,6 +1460,16 @@ public class Utils { return (int) (metrics.widthPixels * (percentage / 100.0f)); } + /** + * Uses {@link #adjustColorBrightness(int, float)} depending if light or dark mode is active. + */ + @ColorInt + public static int adjustColorBrightness(@ColorInt int baseColor, float lightThemeFactor, float darkThemeFactor) { + return isDarkModeEnabled() + ? adjustColorBrightness(baseColor, darkThemeFactor) + : adjustColorBrightness(baseColor, lightThemeFactor); + } + /** * Adjusts the brightness of a color by lightening or darkening it based on the given factor. *

diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/AdvancedVideoQualityMenuPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/AdvancedVideoQualityMenuPatch.java index 6722c4cb7c..89f221b3be 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/AdvancedVideoQualityMenuPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/AdvancedVideoQualityMenuPatch.java @@ -18,7 +18,7 @@ import app.revanced.extension.youtube.settings.Settings; public final class AdvancedVideoQualityMenuPatch { /** - * Injection point. + * Injection point. Regular videos. */ public static void onFlyoutMenuCreate(RecyclerView recyclerView) { if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return; @@ -61,22 +61,12 @@ public final class AdvancedVideoQualityMenuPatch { }); } - - /** - * Injection point. - * - * Used to force the creation of the advanced menu item for the Shorts quality flyout. - */ - public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) { - return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original; - } - /** * Injection point. * * Shorts video quality flyout. */ - public static void showAdvancedVideoQualityMenu(ListView listView) { + public static void addVideoQualityListMenuListener(ListView listView) { if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return; listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { @@ -91,7 +81,6 @@ public final class AdvancedVideoQualityMenuPatch { listView.setSoundEffectsEnabled(false); final var qualityItemMenuPosition = 4; listView.performItemClick(null, qualityItemMenuPosition, 0); - } catch (Exception ex) { Logger.printException(() -> "showAdvancedVideoQualityMenu failure", ex); } @@ -102,4 +91,13 @@ public final class AdvancedVideoQualityMenuPatch { } }); } + + /** + * Injection point. + * + * Used to force the creation of the advanced menu item for the Shorts quality flyout. + */ + public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) { + return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original; + } } \ No newline at end of file diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java index 59d76324e9..dcbad858bc 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java @@ -17,6 +17,7 @@ import app.revanced.extension.shared.settings.IntegerSetting; import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.shared.ShortsPlayerState; +import app.revanced.extension.youtube.videoplayer.VideoQualityDialogButton; @SuppressWarnings("unused") public class RememberVideoQualityPatch { @@ -25,10 +26,20 @@ public class RememberVideoQualityPatch { * Interface to use obfuscated methods. */ public interface VideoQualityMenuInterface { - void patch_setMenuIndexFromQuality(VideoQuality quality); + void patch_setQuality(VideoQuality quality); } - private static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2; + /** + * Video resolution of the automatic quality option.. + */ + public static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2; + + /** + * All quality names are the same for all languages. + * VideoQuality also has a resolution enum that can be used if needed. + */ + public static final String VIDEO_QUALITY_1080P_PREMIUM_NAME = "1080p Premium"; + private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI; private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE; private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI; @@ -36,32 +47,56 @@ public class RememberVideoQualityPatch { private static boolean qualityNeedsUpdating; - /** - * If the user selected a new quality from the flyout menu, - * and {@link Settings#REMEMBER_VIDEO_QUALITY_LAST_SELECTED} - * or {@link Settings#REMEMBER_SHORTS_QUALITY_LAST_SELECTED} is enabled. - */ - private static boolean userChangedDefaultQuality; - - /** - * Index of the video quality chosen by the user from the flyout menu. - */ - private static int userSelectedQualityIndex; - /** * The available qualities of the current video. */ @Nullable - private static List videoQualities; + private static List currentQualities; - private static boolean shouldRememberVideoQuality() { - BooleanSetting preference = ShortsPlayerState.isOpen() ? - Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED + /** + * The current quality of the video playing. + * This is always the actual quality even if Automatic quality is active. + */ + @Nullable + private static VideoQuality currentQuality; + + /** + * The current VideoQualityMenuInterface, set during setVideoQuality. + */ + @Nullable + private static VideoQualityMenuInterface currentMenuInterface; + + @Nullable + public static List getCurrentQualities() { + return currentQualities; + } + + @Nullable + public static VideoQuality getCurrentQuality() { + return currentQuality; + } + + @Nullable + public static VideoQualityMenuInterface getCurrentMenuInterface() { + return currentMenuInterface; + } + + public static boolean shouldRememberVideoQuality() { + BooleanSetting preference = ShortsPlayerState.isOpen() + ? Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED : Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED; return preference.get(); } - private static void changeDefaultQuality(int qualityResolution) { + public static int getDefaultQualityResolution() { + final boolean isShorts = ShortsPlayerState.isOpen(); + IntegerSetting preference = Utils.getNetworkType() == NetworkType.MOBILE + ? (isShorts ? shortsQualityMobile : videoQualityMobile) + : (isShorts ? shortsQualityWifi : videoQualityWifi); + return preference.get(); + } + + public static void saveDefaultQuality(int qualityResolution) { final boolean shortPlayerOpen = ShortsPlayerState.isOpen(); String networkTypeMessage; IntegerSetting qualitySetting; @@ -72,16 +107,24 @@ public class RememberVideoQualityPatch { networkTypeMessage = str("revanced_remember_video_quality_wifi"); qualitySetting = shortPlayerOpen ? shortsQualityWifi : videoQualityWifi; } + + if (qualitySetting.get() == qualityResolution) { + // User clicked the same video quality as the current video, + // or changed between 1080p Premium and non-Premium. + return; + } qualitySetting.save(qualityResolution); - if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get()) + if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get()) { + String qualityLabel = qualityResolution + "p"; Utils.showToastShort(str( shortPlayerOpen ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast", networkTypeMessage, - (qualityResolution + "p")) + qualityLabel) ); + } } /** @@ -93,111 +136,101 @@ public class RememberVideoQualityPatch { public static int setVideoQuality(VideoQuality[] qualities, VideoQualityMenuInterface menu, int originalQualityIndex) { try { Utils.verifyOnMainThread(); + currentMenuInterface = menu; - final boolean useShortsPreference = ShortsPlayerState.isOpen(); - final int preferredQuality = Utils.getNetworkType() == NetworkType.MOBILE - ? (useShortsPreference ? shortsQualityMobile : videoQualityMobile).get() - : (useShortsPreference ? shortsQualityWifi : videoQualityWifi).get(); + final boolean availableQualitiesChanged = currentQualities == null + || currentQualities.size() != qualities.length; + if (availableQualitiesChanged) { + currentQualities = Arrays.asList(qualities); + Logger.printDebug(() -> "VideoQualities: " + currentQualities); + } - if (!userChangedDefaultQuality && preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) { + VideoQuality updatedCurrentQuality = qualities[originalQualityIndex]; + if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE && + (currentQuality == null + || !currentQuality.patch_getQualityName().equals(updatedCurrentQuality.patch_getQualityName()))) { + currentQuality = updatedCurrentQuality; + Logger.printDebug(() -> "Current quality changed to: " + updatedCurrentQuality); + + VideoQualityDialogButton.updateButtonIcon(updatedCurrentQuality); + } + + final int preferredQuality = getDefaultQualityResolution(); + if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) { return originalQualityIndex; // Nothing to do. } - if (videoQualities == null || videoQualities.size() != qualities.length) { - videoQualities = Arrays.asList(qualities); - - // After changing videos the qualities can initially be for the prior video. - // So if the qualities have changed an update is needed. - qualityNeedsUpdating = true; - Logger.printDebug(() -> "VideoQualities: " + videoQualities); - } - - if (userChangedDefaultQuality) { - userChangedDefaultQuality = false; - VideoQuality quality = videoQualities.get(userSelectedQualityIndex); - Logger.printDebug(() -> "User changed default quality to: " + quality); - changeDefaultQuality(quality.patch_getResolution()); - return userSelectedQualityIndex; - } - - if (!qualityNeedsUpdating) { + // After changing videos the qualities can initially be for the prior video. + // If the qualities have changed and the default is not auto then an update is needed. + if (!qualityNeedsUpdating && !availableQualitiesChanged) { return originalQualityIndex; } qualityNeedsUpdating = false; // Find the highest quality that is equal to or less than the preferred. - VideoQuality qualityToUse = videoQualities.get(0); // First element is automatic mode. - int qualityIndexToUse = 0; int i = 0; - for (VideoQuality quality : videoQualities) { + for (VideoQuality quality : qualities) { final int qualityResolution = quality.patch_getResolution(); - if (qualityResolution > qualityToUse.patch_getResolution() && qualityResolution <= preferredQuality) { - qualityToUse = quality; - qualityIndexToUse = i; - break; + if (qualityResolution != AUTOMATIC_VIDEO_QUALITY_VALUE && qualityResolution <= preferredQuality) { + final boolean qualityNeedsChange = (i != originalQualityIndex); + Logger.printDebug(() -> qualityNeedsChange + ? "Changing video quality from: " + updatedCurrentQuality + " to: " + quality + : "Video is already the preferred quality: " + quality + ); + + // On first load of a new regular video, if the video is already the + // desired quality then the quality flyout will show 'Auto' (ie: Auto (720p)). + // + // To prevent user confusion, set the video index even if the + // quality is already correct so the UI picker will not display "Auto". + // + // Only change Shorts quality if the quality actually needs to change, + // because the "auto" option is not shown in the flyout + // and setting the same quality again can cause the Short to restart. + if (qualityNeedsChange || !ShortsPlayerState.isOpen()) { + menu.patch_setQuality(qualities[i]); + return i; + } + + return originalQualityIndex; } i++; } - - // If the desired quality index is equal to the original index, - // then the video is already set to the desired default quality. - String qualityToUseName = qualityToUse.patch_getQualityName(); - if (qualityIndexToUse == originalQualityIndex) { - Logger.printDebug(() -> "Video is already preferred quality: " + qualityToUseName); - } else { - Logger.printDebug(() -> "Changing video quality from: " - + videoQualities.get(originalQualityIndex).patch_getQualityName() - + " to: " + qualityToUseName); - } - - // On first load of a new video, if the video is already the desired quality - // then the quality flyout will show 'Auto' (ie: Auto (720p)). - // - // To prevent user confusion, set the video index even if the - // quality is already correct so the UI picker will not display "Auto". - menu.patch_setMenuIndexFromQuality(qualities[qualityIndexToUse]); - - return qualityIndexToUse; } catch (Exception ex) { Logger.printException(() -> "setVideoQuality failure", ex); - return originalQualityIndex; } - } - - /** - * Injection point. Fixes bad data used by YouTube. - */ - public static int fixVideoQualityResolution(String name, int quality) { - final int correctQuality = 480; - if (name.equals("480p") && quality != correctQuality) { - Logger.printDebug(() -> "Fixing bad data of " + name + " from: " + quality - + " to: " + correctQuality); - return correctQuality; - } - - return quality; + return originalQualityIndex; } /** * Injection point. - * @param qualityIndex Element index of {@link #videoQualities}. + * @param userSelectedQualityIndex Element index of {@link #currentQualities}. */ - public static void userChangedQuality(int qualityIndex) { - if (shouldRememberVideoQuality()) { - userSelectedQualityIndex = qualityIndex; - userChangedDefaultQuality = true; + public static void userChangedShortsQuality(int userSelectedQualityIndex) { + try { + if (shouldRememberVideoQuality()) { + if (currentQualities == null) { + Logger.printDebug(() -> "Cannot save default quality, qualities is null"); + return; + } + VideoQuality quality = currentQualities.get(userSelectedQualityIndex); + saveDefaultQuality(quality.patch_getResolution()); + } + } catch (Exception ex) { + Logger.printException(() -> "userChangedShortsQuality failure", ex); } } /** - * Injection point. + * Injection point. Regular videos. * @param videoResolution Human readable resolution: 480, 720, 1080. */ - public static void userChangedQualityInFlyout(int videoResolution) { + public static void userChangedQuality(int videoResolution) { Utils.verifyOnMainThread(); - if (!shouldRememberVideoQuality()) return; - changeDefaultQuality(videoResolution); + if (shouldRememberVideoQuality()) { + saveDefaultQuality(videoResolution); + } } /** @@ -207,7 +240,24 @@ public class RememberVideoQualityPatch { Utils.verifyOnMainThread(); Logger.printDebug(() -> "newVideoStarted"); + currentQualities = null; + currentQuality = null; + currentMenuInterface = null; qualityNeedsUpdating = true; - videoQualities = null; + + // Hide the quality button until playback starts and the qualities are available. + VideoQualityDialogButton.updateButtonIcon(null); + } + + /** + * Injection point. Fixes bad data used by YouTube. + */ + public static int fixVideoQualityResolution(String name, int quality) { + final int correctQuality = 480; + if (name.equals("480p") && quality != correctQuality) { + return correctQuality; + } + + return quality; } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java index 88eae4a0d3..e738be34dc 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -671,11 +671,9 @@ public class CustomPlaybackSpeedPatch { */ public static int getAdjustedBackgroundColor(boolean isHandleBar) { final int baseColor = Utils.getDialogBackgroundColor(); - float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme. - float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme. - return Utils.isDarkModeEnabled() - ? Utils.adjustColorBrightness(baseColor, darkThemeFactor) // Lighten for dark theme. - : Utils.adjustColorBrightness(baseColor, lightThemeFactor); // Darken for light theme. + final float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme. + final float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme. + return Utils.adjustColorBrightness(baseColor, lightThemeFactor, darkThemeFactor); } } 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 2f51b13475..d279287f05 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 @@ -172,6 +172,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_VIDEO_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE); public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE); public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE); + public static final BooleanSetting VIDEO_QUALITY_DIALOG_BUTTON = new BooleanSetting("revanced_video_quality_dialog_button", FALSE); public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true); public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java index 02f8db6cb7..c4cb423137 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java @@ -333,10 +333,8 @@ class AbstractPreferenceSearchData { return text; } - final int baseColor = Utils.getAppBackgroundColor(); - final int adjustedColor = Utils.isDarkModeEnabled() - ? Utils.adjustColorBrightness(baseColor, 1.20f) // Lighten for dark theme. - : Utils.adjustColorBrightness(baseColor, 0.95f); // Darken for light theme. + final int adjustedColor = Utils.adjustColorBrightness(Utils.getAppBackgroundColor(), + 0.95f, 1.20f); BackgroundColorSpan highlightSpan = new BackgroundColorSpan(adjustedColor); SpannableStringBuilder spannable = new SpannableStringBuilder(text); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlayerControlButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlayerControlButton.java index 6d3c320171..94c92b738c 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlayerControlButton.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlayerControlButton.java @@ -187,4 +187,56 @@ public class PlayerControlButton { if (view != null) view.setVisibility(View.GONE); isVisible = false; } -} \ No newline at end of file + + /** + * Sets the icon of the button. + * @param resourceId Drawable identifier, or zero to hide the icon. + */ + public void setIcon(int resourceId) { + try { + View button = buttonRef.get(); + if (button instanceof ImageView imageButton) { + imageButton.setImageResource(resourceId); + } + } catch (Exception ex) { + Logger.printException(() -> "setIcon failure", ex); + } + } + + /** + * Starts an animation on the button. + * @param animation The animation to apply. + */ + public void startAnimation(Animation animation) { + try { + View button = buttonRef.get(); + if (button != null) { + button.startAnimation(animation); + } + } catch (Exception ex) { + Logger.printException(() -> "startAnimation failure", ex); + } + } + + /** + * Clears any animation on the button. + */ + public void clearAnimation() { + try { + View button = buttonRef.get(); + if (button != null) { + button.clearAnimation(); + } + } catch (Exception ex) { + Logger.printException(() -> "clearAnimation failure", ex); + } + } + + /** + * Returns the View associated with this button. + * @return The button View. + */ + public View getView() { + return buttonRef.get(); + } +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java new file mode 100644 index 0000000000..924f1ce7b1 --- /dev/null +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java @@ -0,0 +1,476 @@ +package app.revanced.extension.youtube.videoplayer; + +import static app.revanced.extension.shared.StringRef.str; +import static app.revanced.extension.shared.Utils.dipToPixels; +import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.AUTOMATIC_VIDEO_QUALITY_VALUE; +import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VIDEO_QUALITY_1080P_PREMIUM_NAME; +import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VideoQualityMenuInterface; + +import android.app.Dialog; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.TranslateAnimation; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.libraries.youtube.innertube.model.media.VideoQuality; + +import java.util.ArrayList; +import java.util.List; + +import app.revanced.extension.shared.Logger; +import app.revanced.extension.shared.Utils; +import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch; +import app.revanced.extension.youtube.settings.Settings; + +@SuppressWarnings("unused") +public class VideoQualityDialogButton { + + private static final int DRAWABLE_LD = getDrawableIdentifier("revanced_video_quality_dialog_button_ld"); + private static final int DRAWABLE_SD = getDrawableIdentifier("revanced_video_quality_dialog_button_sd"); + private static final int DRAWABLE_HD = getDrawableIdentifier("revanced_video_quality_dialog_button_hd"); + private static final int DRAWABLE_FHD = getDrawableIdentifier("revanced_video_quality_dialog_button_fhd"); + private static final int DRAWABLE_FHD_PLUS = getDrawableIdentifier("revanced_video_quality_dialog_button_fhd_plus"); + private static final int DRAWABLE_QHD = getDrawableIdentifier("revanced_video_quality_dialog_button_qhd"); + private static final int DRAWABLE_4K = getDrawableIdentifier("revanced_video_quality_dialog_button_4k"); + private static final int DRAWABLE_UNKNOWN = getDrawableIdentifier("revanced_video_quality_dialog_button_unknown"); + + @Nullable + private static PlayerControlButton instance; + + /** + * The current resource name of the button icon. + */ + private static int currentIconResource; + + private static int getDrawableIdentifier(String resourceName) { + final int resourceId = Utils.getResourceIdentifier(resourceName, "drawable"); + if (resourceId == 0) Logger.printException(() -> "Could not find resource: " + resourceName); + return resourceId; + } + + /** + * Updates the button icon based on the current video quality. + */ + public static void updateButtonIcon(@Nullable VideoQuality quality) { + try { + Utils.verifyOnMainThread(); + if (instance == null) return; + + final int resolution = quality == null + ? AUTOMATIC_VIDEO_QUALITY_VALUE // Video is still loading. + : quality.patch_getResolution(); + + final int iconResource = switch (resolution) { + case 144, 240, 360 -> DRAWABLE_LD; + case 480 -> DRAWABLE_SD; + case 720 -> DRAWABLE_HD; + case 1080 -> VIDEO_QUALITY_1080P_PREMIUM_NAME.equals(quality.patch_getQualityName()) + ? DRAWABLE_FHD_PLUS + : DRAWABLE_FHD; + case 1440 -> DRAWABLE_QHD; + case 2160 -> DRAWABLE_4K; + default -> DRAWABLE_UNKNOWN; + }; + + if (iconResource != currentIconResource) { + currentIconResource = iconResource; + + Utils.runOnMainThreadDelayed(() -> { + if (iconResource != currentIconResource) { + Logger.printDebug(() -> "Ignoring stale button update to: " + quality); + return; + } + instance.setIcon(iconResource); + }, 100); + } + } catch (Exception ex) { + Logger.printException(() -> "updateButtonIcon failure", ex); + } + } + + /** + * Injection point. + */ + public static void initializeButton(View controlsView) { + try { + instance = new PlayerControlButton( + controlsView, + "revanced_video_quality_dialog_button", + "revanced_video_quality_dialog_button_placeholder", + Settings.VIDEO_QUALITY_DIALOG_BUTTON::get, + view -> { + try { + showVideoQualityDialog(view.getContext()); + } catch (Exception ex) { + Logger.printException(() -> "Video quality button onClick failure", ex); + } + }, + view -> { + try { + List qualities = RememberVideoQualityPatch.getCurrentQualities(); + VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface(); + if (qualities == null || menu == null) { + Logger.printDebug(() -> "Cannot reset quality, videoQualities is null"); + return true; + } + + // Reset to default quality. + final int defaultResolution = RememberVideoQualityPatch.getDefaultQualityResolution(); + for (VideoQuality quality : qualities) { + final int resolution = quality.patch_getResolution(); + if (resolution != AUTOMATIC_VIDEO_QUALITY_VALUE && resolution <= defaultResolution) { + Logger.printDebug(() -> "Resetting quality to: " + quality); + menu.patch_setQuality(quality); + return true; + } + } + + // Existing hook cannot set default quality to auto. + // Instead show the quality dialog. + showVideoQualityDialog(view.getContext()); + return true; + } catch (Exception ex) { + Logger.printException(() -> "Video quality button reset failure", ex); + } + return false; + } + ); + + // Set initial icon. + updateButtonIcon(RememberVideoQualityPatch.getCurrentQuality()); + } catch (Exception ex) { + Logger.printException(() -> "initializeButton failure", ex); + } + } + + /** + * Injection point. + */ + public static void setVisibilityImmediate(boolean visible) { + if (instance != null) { + instance.setVisibilityImmediate(visible); + } + } + + /** + * Injection point. + */ + public static void setVisibility(boolean visible, boolean animated) { + if (instance != null) { + instance.setVisibility(visible, animated); + } + } + + /** + * Shows a dialog with available video qualities, excluding Auto, with a title showing the current quality. + */ + private static void showVideoQualityDialog(Context context) { + try { + List currentQualities = RememberVideoQualityPatch.getCurrentQualities(); + VideoQuality currentQuality = RememberVideoQualityPatch.getCurrentQuality(); + if (currentQualities == null || currentQuality == null) { + Logger.printDebug(() -> "Cannot show qualities dialog, videoQualities is null"); + return; + } + if (currentQualities.size() < 2) { + // Should never happen. + Logger.printException(() -> "Cannot show qualities dialog, no qualities available"); + return; + } + + VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface(); + if (menu == null) { + Logger.printDebug(() -> "Cannot show qualities dialog, menu is null"); + return; + } + + // -1 adjustment for automatic quality at first index. + final int listViewSelectedIndex = currentQualities.indexOf(currentQuality) - 1; + + List qualityLabels = new ArrayList<>(currentQualities.size() - 1); + for (VideoQuality availableQuality : currentQualities) { + if (availableQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE) { + qualityLabels.add(availableQuality.patch_getQualityName()); + } + } + + Dialog dialog = new Dialog(context); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setCanceledOnTouchOutside(true); + dialog.setCancelable(true); + + final int dip4 = dipToPixels(4); // Height for handle bar. + final int dip5 = dipToPixels(5); // Padding for mainLayout. + final int dip6 = dipToPixels(6); // Bottom margin. + final int dip8 = dipToPixels(8); // Side padding. + final int dip16 = dipToPixels(16); // Left padding for ListView. + final int dip20 = dipToPixels(20); // Margin below handle. + final int dip40 = dipToPixels(40); // Width for handle bar. + + LinearLayout mainLayout = new LinearLayout(context); + mainLayout.setOrientation(LinearLayout.VERTICAL); + mainLayout.setPadding(dip5, dip8, dip5, dip8); + + ShapeDrawable background = new ShapeDrawable(new RoundRectShape( + Utils.createCornerRadii(12), null, null)); + background.getPaint().setColor(Utils.getDialogBackgroundColor()); + mainLayout.setBackground(background); + + View handleBar = new View(context); + ShapeDrawable handleBackground = new ShapeDrawable(new RoundRectShape( + Utils.createCornerRadii(4), null, null)); + final int baseColor = Utils.getDialogBackgroundColor(); + final int adjustedHandleBarBackgroundColor = Utils.adjustColorBrightness( + baseColor, 0.9f, 1.25f); + handleBackground.getPaint().setColor(adjustedHandleBarBackgroundColor); + handleBar.setBackground(handleBackground); + LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(dip40, dip4); + handleParams.gravity = Gravity.CENTER_HORIZONTAL; + handleParams.setMargins(0, 0, 0, dip20); + handleBar.setLayoutParams(handleParams); + mainLayout.addView(handleBar); + + // Create SpannableStringBuilder for formatted text. + SpannableStringBuilder spannableTitle = new SpannableStringBuilder(); + String titlePart = str("video_quality_quick_menu_title"); + String separatorPart = str("video_quality_title_seperator"); + + // Append title part with default foreground color. + spannableTitle.append(titlePart); + spannableTitle.setSpan( + new ForegroundColorSpan(Utils.getAppForegroundColor()), + 0, + titlePart.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ); + spannableTitle.append(" "); // Space after title. + + // Append separator part with adjusted title color. + int separatorStart = spannableTitle.length(); + spannableTitle.append(separatorPart); + final int adjustedTitleForegroundColor = Utils.adjustColorBrightness( + Utils.getAppForegroundColor(), 1.6f, 0.6f); + spannableTitle.setSpan( + new ForegroundColorSpan(adjustedTitleForegroundColor), + separatorStart, + separatorStart + separatorPart.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ); + spannableTitle.append(" "); // Space after separator. + + // Append quality label with adjusted title color. + final int qualityStart = spannableTitle.length(); + spannableTitle.append(currentQuality.patch_getQualityName()); + spannableTitle.setSpan( + new ForegroundColorSpan(adjustedTitleForegroundColor), + qualityStart, + qualityStart + currentQuality.patch_getQualityName().length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ); + + // Add title with current quality. + TextView titleView = new TextView(context); + titleView.setText(spannableTitle); + titleView.setTextSize(16); + // Remove setTextColor since color is handled by SpannableStringBuilder. + LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + titleParams.setMargins(dip8, 0, 0, dip20); + titleView.setLayoutParams(titleParams); + mainLayout.addView(titleView); + + ListView listView = new ListView(context); + CustomQualityAdapter adapter = new CustomQualityAdapter(context, qualityLabels); + adapter.setSelectedPosition(listViewSelectedIndex); + listView.setAdapter(adapter); + listView.setDivider(null); + listView.setPadding(dip16, 0, 0, 0); + + listView.setOnItemClickListener((parent, view, which, id) -> { + try { + final int originalIndex = which + 1; // Adjust for automatic. + VideoQuality selectedQuality = currentQualities.get(originalIndex); + Logger.printDebug(() -> "User clicked on quality: " + selectedQuality); + + if (RememberVideoQualityPatch.shouldRememberVideoQuality()) { + RememberVideoQualityPatch.saveDefaultQuality(selectedQuality.patch_getResolution()); + } + // Don't update button icon now. Icon will update when the actual + // quality is changed by YT. This is needed to ensure the icon is correct + // if YT ignores changing from 1080p Premium to regular 1080p. + menu.patch_setQuality(selectedQuality); + + dialog.dismiss(); + } catch (Exception ex) { + Logger.printException(() -> "Video quality selection failure", ex); + } + }); + + LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + listViewParams.setMargins(0, 0, 0, dip5); + listView.setLayoutParams(listViewParams); + mainLayout.addView(listView); + + LinearLayout wrapperLayout = new LinearLayout(context); + wrapperLayout.setOrientation(LinearLayout.VERTICAL); + wrapperLayout.setPadding(dip8, 0, dip8, 0); + wrapperLayout.addView(mainLayout); + dialog.setContentView(wrapperLayout); + + Window window = dialog.getWindow(); + if (window != null) { + WindowManager.LayoutParams params = window.getAttributes(); + params.gravity = Gravity.BOTTOM; + params.y = dip6; + int portraitWidth = context.getResources().getDisplayMetrics().widthPixels; + if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + portraitWidth = Math.min( + portraitWidth, + context.getResources().getDisplayMetrics().heightPixels); + } + params.width = portraitWidth; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + window.setBackgroundDrawable(null); + } + + final int fadeDurationFast = Utils.getResourceInteger("fade_duration_fast"); + Animation slideInABottomAnimation = Utils.getResourceAnimation("slide_in_bottom"); + slideInABottomAnimation.setDuration(fadeDurationFast); + mainLayout.startAnimation(slideInABottomAnimation); + + // noinspection ClickableViewAccessibility + mainLayout.setOnTouchListener(new View.OnTouchListener() { + final float dismissThreshold = dipToPixels(100); + float touchY; + float translationY; + + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + touchY = event.getRawY(); + translationY = mainLayout.getTranslationY(); + return true; + case MotionEvent.ACTION_MOVE: + final float deltaY = event.getRawY() - touchY; + if (deltaY >= 0) { + mainLayout.setTranslationY(translationY + deltaY); + } + return true; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mainLayout.getTranslationY() > dismissThreshold) { + //noinspection ExtractMethodRecommender + final float remainingDistance = context.getResources().getDisplayMetrics().heightPixels + - mainLayout.getTop(); + TranslateAnimation slideOut = new TranslateAnimation( + 0, 0, mainLayout.getTranslationY(), remainingDistance); + slideOut.setDuration(fadeDurationFast); + slideOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) {} + @Override + public void onAnimationEnd(Animation animation) { + dialog.dismiss(); + } + @Override + public void onAnimationRepeat(Animation animation) {} + }); + mainLayout.startAnimation(slideOut); + } else { + TranslateAnimation slideBack = new TranslateAnimation( + 0, 0, mainLayout.getTranslationY(), 0); + slideBack.setDuration(fadeDurationFast); + mainLayout.startAnimation(slideBack); + mainLayout.setTranslationY(0); + } + return true; + default: + return false; + } + } + }); + + dialog.show(); + } catch (Exception ex) { + Logger.printException(() -> "showVideoQualityDialog failure", ex); + } + } + + private static class CustomQualityAdapter extends ArrayAdapter { + private int selectedPosition = -1; + + public CustomQualityAdapter(@NonNull Context context, @NonNull List objects) { + super(context, 0, objects); + } + + private void setSelectedPosition(int position) { + this.selectedPosition = position; + notifyDataSetChanged(); + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + ViewHolder viewHolder; + + if (convertView == null) { + convertView = LayoutInflater.from(getContext()).inflate( + Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"), + parent, + false + ); + viewHolder = new ViewHolder(); + viewHolder.checkIcon = convertView.findViewById( + Utils.getResourceIdentifier("revanced_check_icon", "id") + ); + viewHolder.placeholder = convertView.findViewById( + Utils.getResourceIdentifier("revanced_check_icon_placeholder", "id") + ); + viewHolder.textView = convertView.findViewById( + Utils.getResourceIdentifier("revanced_item_text", "id") + ); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + + viewHolder.textView.setText(getItem(position)); + final boolean isSelected = position == selectedPosition; + viewHolder.checkIcon.setVisibility(isSelected ? View.VISIBLE : View.GONE); + viewHolder.placeholder.setVisibility(isSelected ? View.GONE : View.INVISIBLE); + + return convertView; + } + + private static class ViewHolder { + ImageView checkIcon; + View placeholder; + TextView textView; + } + } +} diff --git a/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java b/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java index 67dbc6873b..628c423abe 100644 --- a/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java +++ b/extensions/youtube/stub/src/main/java/com/google/android/libraries/youtube/innertube/model/media/VideoQuality.java @@ -1,12 +1,8 @@ package com.google.android.libraries.youtube.innertube.model.media; -public class VideoQuality { - public final String patch_getQualityName() { - throw new UnsupportedOperationException("Stub"); - } +public abstract class VideoQuality implements Comparable { + public abstract String patch_getQualityName(); - public final int patch_getResolution() { - throw new UnsupportedOperationException("Stub"); - } + public abstract int patch_getResolution(); } diff --git a/patches/api/patches.api b/patches/api/patches.api index 559de899f8..91f78e8db7 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -1664,6 +1664,10 @@ public final class app/revanced/patches/youtube/video/quality/VideoQualityPatchK public static final fun getVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatchKt { + public static final fun getVideoQualityButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatchKt { public static final fun getPlaybackSpeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt index 86588df099..58033a223e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt @@ -11,7 +11,6 @@ val recyclerViewTreeHookPatch = bytecodePatch { dependsOn(sharedExtensionPatch) execute { - recyclerViewTreeObserverFingerprint.method.apply { val insertIndex = recyclerViewTreeObserverFingerprint.patternMatch!!.startIndex + 1 val recyclerViewParameter = 2 diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt index 55285a56e3..3e8aa23a17 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt @@ -68,7 +68,6 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { // region Patch for the old type of the video quality menu. // Used for regular videos when spoofing to old app version, // and for the Shorts quality flyout on newer app versions. - videoQualityMenuViewInflateFingerprint.let { it.method.apply { val checkCastIndex = it.patternMatch!!.endIndex @@ -77,7 +76,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { addInstruction( checkCastIndex + 1, "invoke-static { v$listViewRegister }, $EXTENSION_CLASS_DESCRIPTOR->" + - "showAdvancedVideoQualityMenu(Landroid/widget/ListView;)V", + "addVideoQualityListMenuListener(Landroid/widget/ListView;)V", ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt index c98bdac633..f040796325 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt @@ -23,7 +23,7 @@ internal val videoQualityFingerprint = fingerprint { /** * Matches with the class found in [videoQualitySetterFingerprint]. */ -internal val setQualityByIndexMethodClassFieldReferenceFingerprint = fingerprint { +internal val setVideoQualityFingerprint = fingerprint { returns("V") parameters("L") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index 1e42048ba6..7a31a6b74c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -67,13 +67,6 @@ val rememberVideoQualityPatch = bytecodePatch { SwitchPreference("revanced_remember_video_quality_last_selected_toast") )) - /* - * The following code works by hooking the method which is called when the user selects a video quality - * to remember the last selected video quality. - * - * It also hooks the method which is called when the video quality to set is determined. - * Conveniently, at this point the video quality is overridden to the remembered playback speed. - */ onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted") videoQualityFingerprint.let { @@ -82,7 +75,7 @@ val rememberVideoQualityPatch = bytecodePatch { 0, """ invoke-static { p2, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I - move-result p1 + move-result p1 """ ) @@ -142,10 +135,10 @@ val rememberVideoQualityPatch = bytecodePatch { } // Inject a call to set the remembered quality once a video loads. - setQualityByIndexMethodClassFieldReferenceFingerprint.match( + setVideoQualityFingerprint.match( videoQualitySetterFingerprint.originalClassDef ).let { match -> - // This instruction refers to the field with the type that contains the setQualityByIndex method. + // This instruction refers to the field with the type that contains the setQuality method. val instructions = match.method.implementation!!.instructions val onItemClickListenerClassReference = (instructions.elementAt(0) as ReferenceInstruction).reference @@ -160,15 +153,10 @@ val rememberVideoQualityPatch = bytecodePatch { // Add interface and helper methods to allow extension code to call obfuscated methods. interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE) - // Get the name of the setQualityByIndex method. - val setQualityMenuIndexMethod = methods.single { - method -> method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE - } - methods.add( ImmutableMethod( type, - "patch_setMenuIndexFromQuality", + "patch_setQuality", listOf( ImmutableMethodParameter(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE, null, null) ), @@ -178,6 +166,10 @@ val rememberVideoQualityPatch = bytecodePatch { null, MutableMethodImplementation(2), ).toMutable().apply { + val setQualityMenuIndexMethod = methods.single { method -> + method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE + } + addInstructions( 0, """ @@ -192,7 +184,7 @@ val rememberVideoQualityPatch = bytecodePatch { videoQualitySetterFingerprint.method.addInstructions( 0, """ - # Get the object instance to invoke the setQualityByIndex method on. + # Get object instance to invoke setQuality method. iget-object v0, p0, $onItemClickListenerClassReference iget-object v0, v0, $setQualityFieldReference @@ -202,15 +194,15 @@ val rememberVideoQualityPatch = bytecodePatch { ) } - // Inject a call to remember the selected quality. + // Inject a call to remember the selected quality for Shorts. videoQualityItemOnClickFingerprint.match( videoQualityItemOnClickParentFingerprint.classDef ).method.addInstruction( 0, - "invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V" + "invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V" ) - // Inject a call to remember the user selected quality. + // Inject a call to remember the user selected quality for regular videos. videoQualityChangedFingerprint.let { it.method.apply { val index = it.patternMatch!!.startIndex @@ -218,7 +210,7 @@ val rememberVideoQualityPatch = bytecodePatch { addInstruction( index + 1, - "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQualityInFlyout(I)V", + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V", ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt index 2fb92c848c..432b4f8f39 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt @@ -5,6 +5,7 @@ import app.revanced.patches.shared.misc.settings.preference.BasePreference import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.youtube.misc.settings.PreferenceScreen +import app.revanced.patches.youtube.video.quality.button.videoQualityButtonPatch /** * Video quality settings. Used to organize all speed related settings together. @@ -19,6 +20,7 @@ val videoQualityPatch = bytecodePatch( dependsOn( rememberVideoQualityPatch, advancedVideoQualityMenuPatch, + videoQualityButtonPatch, ) compatibleWith( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatch.kt new file mode 100644 index 0000000000..aaa42c8271 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatch.kt @@ -0,0 +1,64 @@ +package app.revanced.patches.youtube.video.quality.button + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patcher.patch.resourcePatch +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.misc.extension.sharedExtensionPatch +import app.revanced.patches.youtube.misc.playercontrols.* +import app.revanced.patches.youtube.misc.settings.PreferenceScreen +import app.revanced.patches.youtube.misc.settings.settingsPatch +import app.revanced.patches.youtube.video.quality.rememberVideoQualityPatch +import app.revanced.util.ResourceGroup +import app.revanced.util.copyResources + +private val videoQualityButtonResourcePatch = resourcePatch { + dependsOn(playerControlsResourcePatch) + + execute { + copyResources( + "qualitybutton", + ResourceGroup( + "drawable", + "revanced_video_quality_dialog_button_ld.xml", + "revanced_video_quality_dialog_button_sd.xml", + "revanced_video_quality_dialog_button_hd.xml", + "revanced_video_quality_dialog_button_fhd.xml", + "revanced_video_quality_dialog_button_fhd_plus.xml", + "revanced_video_quality_dialog_button_qhd.xml", + "revanced_video_quality_dialog_button_4k.xml", + "revanced_video_quality_dialog_button_unknown.xml", + ), + ) + + addBottomControl("qualitybutton") + } +} + +private const val QUALITY_BUTTON_CLASS_DESCRIPTOR = + "Lapp/revanced/extension/youtube/videoplayer/VideoQualityDialogButton;" + +val videoQualityButtonPatch = bytecodePatch( + description = "Adds the option to display video quality dialog button in the video player.", +) { + dependsOn( + sharedExtensionPatch, + settingsPatch, + addResourcesPatch, + rememberVideoQualityPatch, + videoQualityButtonResourcePatch, + playerControlsPatch, + ) + + execute { + addResources("youtube", "video.quality.button.videoQualityButtonPatch") + + PreferenceScreen.PLAYER.addPreferences( + SwitchPreference("revanced_video_quality_dialog_button"), + ) + + initializeBottomControl(QUALITY_BUTTON_CLASS_DESCRIPTOR) + injectVisibilityCheckCall(QUALITY_BUTTON_CLASS_DESCRIPTOR) + } +} diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 8a356d06d0..3624d7f226 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -1543,6 +1543,11 @@ Enabling this can unlock higher video qualities" Button is shown. Tap and hold to reset playback speed to default Button is not shown + + Show video quality button + Button is shown. Tap and hold to reset quality to default + Button is not shown + Custom playback speed menu Custom speed menu is shown diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_4k.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_4k.xml new file mode 100644 index 0000000000..22051e3fb8 --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_4k.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd.xml new file mode 100644 index 0000000000..b7a8f5c73e --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd_plus.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd_plus.xml new file mode 100644 index 0000000000..18e163ca2b --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_fhd_plus.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_hd.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_hd.xml new file mode 100644 index 0000000000..db2bad1b1f --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_hd.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_ld.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_ld.xml new file mode 100644 index 0000000000..a49f5a200c --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_ld.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_qhd.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_qhd.xml new file mode 100644 index 0000000000..7609d368ec --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_qhd.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_sd.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_sd.xml new file mode 100644 index 0000000000..150ede8502 --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_sd.xml @@ -0,0 +1,9 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_unknown.xml b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_unknown.xml new file mode 100644 index 0000000000..4e5750cfe3 --- /dev/null +++ b/patches/src/main/resources/qualitybutton/drawable/revanced_video_quality_dialog_button_unknown.xml @@ -0,0 +1,11 @@ + + + diff --git a/patches/src/main/resources/qualitybutton/host/layout/youtube_controls_bottom_ui_container.xml b/patches/src/main/resources/qualitybutton/host/layout/youtube_controls_bottom_ui_container.xml new file mode 100644 index 0000000000..deb534fbaf --- /dev/null +++ b/patches/src/main/resources/qualitybutton/host/layout/youtube_controls_bottom_ui_container.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/patches/src/main/resources/speedbutton/host/layout/youtube_controls_bottom_ui_container.xml b/patches/src/main/resources/speedbutton/host/layout/youtube_controls_bottom_ui_container.xml index 315251b0c0..c0109ebc59 100644 --- a/patches/src/main/resources/speedbutton/host/layout/youtube_controls_bottom_ui_container.xml +++ b/patches/src/main/resources/speedbutton/host/layout/youtube_controls_bottom_ui_container.xml @@ -13,7 +13,6 @@ android:layout_height="60.0dip" android:paddingTop="6.0dp" android:paddingBottom="0dp" - android:longClickable="false" android:scaleType="center" android:src="@drawable/revanced_playback_speed_dialog_button" yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container" From f4950ec2ea77fa69f89780576c12c57b55048c67 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Aug 2025 15:26:39 +0000 Subject: [PATCH 18/33] chore: Release v5.33.0-dev.7 [skip ci] # [5.33.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.6...v5.33.0-dev.7) (2025-08-03) ### Features * **YouTube:** Add player button to change video quality ([#5435](https://github.com/ReVanced/revanced-patches/issues/5435)) ([7bdc328](https://github.com/ReVanced/revanced-patches/commit/7bdc32867aeefe011fdc432b52ac6165205eee9b)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e5bddf293..42cfa0c028 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.6...v5.33.0-dev.7) (2025-08-03) + + +### Features + +* **YouTube:** Add player button to change video quality ([#5435](https://github.com/ReVanced/revanced-patches/issues/5435)) ([d5f51bf](https://github.com/ReVanced/revanced-patches/commit/d5f51bf400dd22626ff65d7563b6fde70d53fb25)) + # [5.33.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.5...v5.33.0-dev.6) (2025-07-31) diff --git a/gradle.properties b/gradle.properties index 23ef8274e9..8fb806d0a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.6 +version = 5.33.0-dev.7 From 37aab8382e5209d41c7dda59946649f28c02961e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 3 Aug 2025 19:38:17 -0400 Subject: [PATCH 19/33] chore: Sync translations (#5585) --- .../addresources/values-af-rZA/strings.xml | 2 + .../addresources/values-am-rET/strings.xml | 2 + .../addresources/values-ar-rSA/strings.xml | 5 + .../addresources/values-as-rIN/strings.xml | 2 + .../addresources/values-az-rAZ/strings.xml | 2 + .../addresources/values-be-rBY/strings.xml | 5 + .../addresources/values-bg-rBG/strings.xml | 5 + .../addresources/values-bn-rBD/strings.xml | 5 + .../addresources/values-bs-rBA/strings.xml | 2 + .../addresources/values-ca-rES/strings.xml | 2 + .../addresources/values-cs-rCZ/strings.xml | 5 + .../addresources/values-da-rDK/strings.xml | 5 + .../addresources/values-de-rDE/strings.xml | 5 + .../addresources/values-el-rGR/strings.xml | 5 + .../addresources/values-es-rES/strings.xml | 5 + .../addresources/values-et-rEE/strings.xml | 5 + .../addresources/values-eu-rES/strings.xml | 2 + .../addresources/values-fa-rIR/strings.xml | 2 + .../addresources/values-fi-rFI/strings.xml | 2 + .../addresources/values-fil-rPH/strings.xml | 5 + .../addresources/values-fr-rFR/strings.xml | 5 + .../addresources/values-ga-rIE/strings.xml | 5 + .../addresources/values-gl-rES/strings.xml | 2 + .../addresources/values-gu-rIN/strings.xml | 2 + .../addresources/values-hi-rIN/strings.xml | 2 + .../addresources/values-hr-rHR/strings.xml | 2 + .../addresources/values-hu-rHU/strings.xml | 5 + .../addresources/values-hy-rAM/strings.xml | 5 + .../addresources/values-in-rID/strings.xml | 5 + .../addresources/values-is-rIS/strings.xml | 2 + .../addresources/values-it-rIT/strings.xml | 5 + .../addresources/values-iw-rIL/strings.xml | 5 + .../addresources/values-ja-rJP/strings.xml | 13 +- .../addresources/values-ka-rGE/strings.xml | 2 + .../addresources/values-kk-rKZ/strings.xml | 2 + .../addresources/values-km-rKH/strings.xml | 2 + .../addresources/values-kn-rIN/strings.xml | 2 + .../addresources/values-ko-rKR/strings.xml | 5 + .../addresources/values-ky-rKG/strings.xml | 2 + .../addresources/values-lo-rLA/strings.xml | 2 + .../addresources/values-lt-rLT/strings.xml | 5 + .../addresources/values-lv-rLV/strings.xml | 5 + .../addresources/values-mk-rMK/strings.xml | 2 + .../addresources/values-ml-rIN/strings.xml | 2 + .../addresources/values-mn-rMN/strings.xml | 2 + .../addresources/values-mr-rIN/strings.xml | 2 + .../addresources/values-ms-rMY/strings.xml | 2 + .../addresources/values-my-rMM/strings.xml | 2 + .../addresources/values-nb-rNO/strings.xml | 2 + .../addresources/values-ne-rIN/strings.xml | 2 + .../addresources/values-nl-rNL/strings.xml | 5 + .../addresources/values-or-rIN/strings.xml | 2 + .../addresources/values-pa-rIN/strings.xml | 2 + .../addresources/values-pl-rPL/strings.xml | 5 + .../addresources/values-pt-rBR/strings.xml | 5 + .../addresources/values-pt-rPT/strings.xml | 5 + .../addresources/values-ro-rRO/strings.xml | 6 + .../addresources/values-ru-rRU/strings.xml | 5 + .../addresources/values-si-rLK/strings.xml | 2 + .../addresources/values-sk-rSK/strings.xml | 5 + .../addresources/values-sl-rSI/strings.xml | 5 + .../addresources/values-sq-rAL/strings.xml | 5 + .../addresources/values-sr-rCS/strings.xml | 5 + .../addresources/values-sr-rSP/strings.xml | 5 + .../addresources/values-sv-rSE/strings.xml | 5 + .../addresources/values-sw-rKE/strings.xml | 2 + .../addresources/values-ta-rIN/strings.xml | 2 + .../addresources/values-te-rIN/strings.xml | 2 + .../addresources/values-th-rTH/strings.xml | 5 + .../addresources/values-tr-rTR/strings.xml | 5 + .../addresources/values-uk-rUA/strings.xml | 7 +- .../addresources/values-ur-rIN/strings.xml | 2 + .../addresources/values-uz-rUZ/strings.xml | 2 + .../addresources/values-vi-rVN/strings.xml | 170 +++++++++--------- .../addresources/values-zh-rCN/strings.xml | 5 + .../addresources/values-zh-rTW/strings.xml | 5 + .../addresources/values-zu-rZA/strings.xml | 2 + 77 files changed, 363 insertions(+), 87 deletions(-) diff --git a/patches/src/main/resources/addresources/values-af-rZA/strings.xml b/patches/src/main/resources/addresources/values-af-rZA/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-af-rZA/strings.xml +++ b/patches/src/main/resources/addresources/values-af-rZA/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-am-rET/strings.xml b/patches/src/main/resources/addresources/values-am-rET/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-am-rET/strings.xml +++ b/patches/src/main/resources/addresources/values-am-rET/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ar-rSA/strings.xml b/patches/src/main/resources/addresources/values-ar-rSA/strings.xml index 2ce5dc22d5..ba26d65f8c 100644 --- a/patches/src/main/resources/addresources/values-ar-rSA/strings.xml +++ b/patches/src/main/resources/addresources/values-ar-rSA/strings.xml @@ -1465,6 +1465,11 @@ Second \"item\" text" الزر معروض. انقر مع الاستمرار لإعادة ضبط سرعة التشغيل إلى الوضع الافتراضي لا يتم عرض الزر + + عرض زر جودة الفيديو + الزر معروض. انقر مع الاستمرار لإعادة تعيين الجودة إلى الافتراضي + الزر غير معروض + قائمة سرعة التشغيل المخصصة يتم عرض قائمة سرعة التشغيل المخصصة diff --git a/patches/src/main/resources/addresources/values-as-rIN/strings.xml b/patches/src/main/resources/addresources/values-as-rIN/strings.xml index 37f8500cf6..cc515ffae8 100644 --- a/patches/src/main/resources/addresources/values-as-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-as-rIN/strings.xml @@ -224,6 +224,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml index d73054e6e6..978b72faeb 100644 --- a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml +++ b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml @@ -1464,6 +1464,8 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər Düymə göstərilir. Oynatma sürətin standart olaraq qaytarmaq üçün toxunub saxla Düymə göstərilmir + + Fərdi oynatma sürəti siyahısı Fərdi sürət siyahısı göstərilir diff --git a/patches/src/main/resources/addresources/values-be-rBY/strings.xml b/patches/src/main/resources/addresources/values-be-rBY/strings.xml index a2f8c5ccb3..c1a1c8bb13 100644 --- a/patches/src/main/resources/addresources/values-be-rBY/strings.xml +++ b/patches/src/main/resources/addresources/values-be-rBY/strings.xml @@ -1466,6 +1466,11 @@ Second \"item\" text" Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць хуткасць прайгравання да стандартнай Кнопка не паказваецца + + Паказаць кнопку якасці відэа + Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць якасць да па змаўчанні + Кнопка не паказваецца + Меню пользовательской скорости воспроизведения Меню пользовательской скорости отображается diff --git a/patches/src/main/resources/addresources/values-bg-rBG/strings.xml b/patches/src/main/resources/addresources/values-bg-rBG/strings.xml index 1b2cf1ba25..f49cc43659 100644 --- a/patches/src/main/resources/addresources/values-bg-rBG/strings.xml +++ b/patches/src/main/resources/addresources/values-bg-rBG/strings.xml @@ -1465,6 +1465,11 @@ Second \"item\" text" Бутонът е показан. Докоснете и задръжте, за да върнете скоростта на възпроизвеждане към стойността по подразбиране Бутонът не е показан + + Покажи бутона за качество на видеото + Бутонът е показан. Докоснете и задръжте, за да възстановите качеството до подразбиране + Бутонът не е показан + Менюто за потребителска скорост Менюто за потребителска скорост се показва diff --git a/patches/src/main/resources/addresources/values-bn-rBD/strings.xml b/patches/src/main/resources/addresources/values-bn-rBD/strings.xml index e37a42269c..bfce746b8b 100644 --- a/patches/src/main/resources/addresources/values-bn-rBD/strings.xml +++ b/patches/src/main/resources/addresources/values-bn-rBD/strings.xml @@ -1461,6 +1461,11 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট বোতামটি দেখানো হয়েছে। প্লেব্যাক স্পীড ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন। বোতাম প্রদর্শিত হয়নি + + ভিডিও গুণমান বোতাম দেখান + বোতামটি দেখানো হয়েছে। গুণমান ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন। + বোতামটি দেখানো হয়নি। + কাস্টম প্লেব্যাক গতি মেনু কাস্টম স্পিড মেনু দেখানো হচ্ছে diff --git a/patches/src/main/resources/addresources/values-bs-rBA/strings.xml b/patches/src/main/resources/addresources/values-bs-rBA/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-bs-rBA/strings.xml +++ b/patches/src/main/resources/addresources/values-bs-rBA/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ca-rES/strings.xml b/patches/src/main/resources/addresources/values-ca-rES/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ca-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-ca-rES/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml b/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml index 8dc89881b6..c74ddf9cf9 100644 --- a/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml +++ b/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml @@ -1465,6 +1465,11 @@ Povolením této funkce lze odemknout vyšší kvality videa" Tlačítko je zobrazeno. Klepnutím a podržením obnovíte výchozí rychlost přehrávání Tlačítko se nezobrazuje + + Zobrazit tlačítko kvality videa + Tlačítko je zobrazeno. Klepnutím a podržením obnovíte kvalitu na výchozí + Tlačítko není zobrazeno. + Menu vlastní rychlosti přehrávání Menu vlastní rychlosti se zobrazuje diff --git a/patches/src/main/resources/addresources/values-da-rDK/strings.xml b/patches/src/main/resources/addresources/values-da-rDK/strings.xml index 6ff8941f30..2cba9544fb 100644 --- a/patches/src/main/resources/addresources/values-da-rDK/strings.xml +++ b/patches/src/main/resources/addresources/values-da-rDK/strings.xml @@ -1467,6 +1467,11 @@ Aktivering af dette kan låse op for højere videokvalitet" Knappen vises. Tryk og hold for at nulstille afspilningshastigheden til standard. Knap vises ikke + + Vis videokvalitetsknap + Knap vises. Tryk og hold nede for at nulstille kvaliteten til standard + Knappen vises ikke + Tilpasset afspilningshastighed menu Tilpasset hastighed menu er vist diff --git a/patches/src/main/resources/addresources/values-de-rDE/strings.xml b/patches/src/main/resources/addresources/values-de-rDE/strings.xml index 88865eddf3..698cccf97b 100644 --- a/patches/src/main/resources/addresources/values-de-rDE/strings.xml +++ b/patches/src/main/resources/addresources/values-de-rDE/strings.xml @@ -1460,6 +1460,11 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w Die Schaltfläche wird angezeigt. Tippen und halten, um die Wiedergabegeschwindigkeit auf die Standardeinstellung zurückzusetzen. Button wird nicht angezeigt + + Videoqualität-Schaltfläche anzeigen + Schaltfläche wird angezeigt. Tippen und halten, um die Qualität auf Standard zurückzusetzen + Schaltfläche wird nicht angezeigt + Benutzerdefiniertes Wiedergabegeschwindigkeitsmenü Benutzerdefiniertes Geschwindigkeitsmenü wird angezeigt diff --git a/patches/src/main/resources/addresources/values-el-rGR/strings.xml b/patches/src/main/resources/addresources/values-el-rGR/strings.xml index c6c8a31728..1d8a2729ba 100644 --- a/patches/src/main/resources/addresources/values-el-rGR/strings.xml +++ b/patches/src/main/resources/addresources/values-el-rGR/strings.xml @@ -1464,6 +1464,11 @@ Second \"item\" text" Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ταχύτητας αναπαραγωγής στην προεπιλογή Το κουμπί δεν εμφανίζεται + + Εμφάνιση κουμπιού αλλαγής ποιότητας βίντεο + Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ποιότητας στην προεπιλογή + Το κουμπί δεν εμφανίζεται + Μενού προσαρμοσμένης ταχύτητας αναπαραγωγής Το μενού προσαρμοσμένης ταχύτητας αναπαραγωγής εμφανίζεται diff --git a/patches/src/main/resources/addresources/values-es-rES/strings.xml b/patches/src/main/resources/addresources/values-es-rES/strings.xml index 8486373b48..e54453127b 100644 --- a/patches/src/main/resources/addresources/values-es-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-es-rES/strings.xml @@ -1456,6 +1456,11 @@ Habilitar esto puede desbloquear calidades de vídeo más altas" Se muestra el botón. Mantén pulsado para restablecer la velocidad de reproducción predeterminada El botón no se muestra + + Mostrar botón de calidad de video + Botón visible. Toca y mantén para restablecer la calidad a los valores predeterminados + Botón no visible + Menú de velocidad de reproducción personalizada Menú de velocidad personalizado se muestra diff --git a/patches/src/main/resources/addresources/values-et-rEE/strings.xml b/patches/src/main/resources/addresources/values-et-rEE/strings.xml index cdd7773899..720e43dd9d 100644 --- a/patches/src/main/resources/addresources/values-et-rEE/strings.xml +++ b/patches/src/main/resources/addresources/values-et-rEE/strings.xml @@ -1465,6 +1465,11 @@ Selle lubamine võib avada kõrgema video kvaliteedi" Nupp on nähtaval. Puudutage ja hoidke all, et taastada taasesituse kiirus vaikeväärtusele Nuppi ei kuvata + + Näita video kvaliteedi nuppu + Nupp on nähtaval. Kvaliteedi lähtestamiseks vaikeseadeteks puudutage ja hoidke + Nuppu ei kuvata + Kohandatud taasesituse kiiruse menüü Kohandatud kiiruse menüü kuvatakse diff --git a/patches/src/main/resources/addresources/values-eu-rES/strings.xml b/patches/src/main/resources/addresources/values-eu-rES/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-eu-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-eu-rES/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-fa-rIR/strings.xml b/patches/src/main/resources/addresources/values-fa-rIR/strings.xml index a231e65ccd..f95959ae4e 100644 --- a/patches/src/main/resources/addresources/values-fa-rIR/strings.xml +++ b/patches/src/main/resources/addresources/values-fa-rIR/strings.xml @@ -272,6 +272,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml index 565c2707fa..8cb1418cf6 100644 --- a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml +++ b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml @@ -1465,6 +1465,8 @@ Tämä voi avata korkealaatuisemmat videot" Painike näytetään. Napauta ja pidä pohjassa palauttaaksesi soiton nopeuden oletukseksi Painiketta ei näytetä + + Mukautettu toistonopeusvalikko Mukautettu nopeusvalikko näytetään diff --git a/patches/src/main/resources/addresources/values-fil-rPH/strings.xml b/patches/src/main/resources/addresources/values-fil-rPH/strings.xml index 2282434406..b770c938ae 100644 --- a/patches/src/main/resources/addresources/values-fil-rPH/strings.xml +++ b/patches/src/main/resources/addresources/values-fil-rPH/strings.xml @@ -1463,6 +1463,11 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video"Ipinapakita ang button. I-tap at i-hold para i-reset ang bilis ng pag-playback sa default Hindi ipinapakita ang button + + Ipakita ang button ng kalidad ng video + Nakalabas ang button. Pindutin nang matagal para ibalik sa default ang kalidad + Hindi ipinapakita ang buton + Menu ng pasadyang bilis ng pag-playback Ipinapakita ang menu ng pasadyang bilis diff --git a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml index 21c5274ccc..9929abd00e 100644 --- a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml +++ b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml @@ -1466,6 +1466,11 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures"Le bouton est affiché. Appuyez longuement dessus pour rétablir la vitesse de lecture par défaut. Le bouton n\'est pas affiché + + Afficher le bouton de qualité vidéo + Le bouton est affiché. Appuyez longuement pour réinitialiser la qualité par défaut + Le bouton n\'est pas affiché + Menu de vitesse de lecture personnalisée Le menu de vitesse personnalisée est affiché diff --git a/patches/src/main/resources/addresources/values-ga-rIE/strings.xml b/patches/src/main/resources/addresources/values-ga-rIE/strings.xml index 9573625b88..9a4fe8f466 100644 --- a/patches/src/main/resources/addresources/values-ga-rIE/strings.xml +++ b/patches/src/main/resources/addresources/values-ga-rIE/strings.xml @@ -1465,6 +1465,11 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil" Taispeántar an cnaipe. Tapáil agus coinnigh chun luas athsheinm a athshocrú go réamhshocrú Ní thaispeántar an cnaipe + + Taispeáin cnaipe cáilíochta físeáin + Tá cnaipe le feiceáil. Tapáil agus coinnigh chun cáilíocht a athshocrú mar réamhshocrú + Níl cnaipe le feiceáil + Roghchlár luas athsheinm saincheaptha Taispeántar roghchlár luais saincheaptha diff --git a/patches/src/main/resources/addresources/values-gl-rES/strings.xml b/patches/src/main/resources/addresources/values-gl-rES/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-gl-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-gl-rES/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-gu-rIN/strings.xml b/patches/src/main/resources/addresources/values-gu-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-gu-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-gu-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-hi-rIN/strings.xml b/patches/src/main/resources/addresources/values-hi-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-hi-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-hi-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-hr-rHR/strings.xml b/patches/src/main/resources/addresources/values-hr-rHR/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-hr-rHR/strings.xml +++ b/patches/src/main/resources/addresources/values-hr-rHR/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-hu-rHU/strings.xml b/patches/src/main/resources/addresources/values-hu-rHU/strings.xml index b8f2658f46..47ec578cb6 100644 --- a/patches/src/main/resources/addresources/values-hu-rHU/strings.xml +++ b/patches/src/main/resources/addresources/values-hu-rHU/strings.xml @@ -1462,6 +1462,11 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását"A gomb látható. Tartsa lenyomva a lejátszási sebesség alapértelmezettre állításához A gomb nem látható + + Videóminőség gomb megjelenítése + A gomb látható. Tartsa lenyomva a minőséget az alapértelmezettre visszaállításához + A gomb nem látható + Egyedi lejátszási sebesség menü Megjelenik az egyéni sebesség menü diff --git a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml index ab28a8803a..95b6ca296a 100644 --- a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml +++ b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml @@ -1466,6 +1466,11 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի Կոճակը ցուցադրվում է: Հպեք և պահեք՝ նվագարկման արագությունը լռելյայնի վերականգնելու համար Կոճակը չի ցուցադրվում + + Ցուցադրել տեսանյութի որակի կոճակը + Կոճակը ցուցադրված է։ Սեղմեք և պահեք՝ որակը լռելյայն վիճակի վերականգնելու համար + Կոճակը ցուցադրված չէ։ + Տեսանյութի արագության հարմարեցված մենյու Հարմարեցված արագության մենյուը ցուցադրվում է diff --git a/patches/src/main/resources/addresources/values-in-rID/strings.xml b/patches/src/main/resources/addresources/values-in-rID/strings.xml index 75312dd02e..b971cb89de 100644 --- a/patches/src/main/resources/addresources/values-in-rID/strings.xml +++ b/patches/src/main/resources/addresources/values-in-rID/strings.xml @@ -1464,6 +1464,11 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kecepatan pemutaran ke bawaan Tombol tidak ditampilkan + + Tampilkan tombol kualitas video + Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kualitas ke default + Tombol tidak ditampilkan + Menu kecepatan pemutaran khusus Menu kecepatan khusus ditampilkan diff --git a/patches/src/main/resources/addresources/values-is-rIS/strings.xml b/patches/src/main/resources/addresources/values-is-rIS/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-is-rIS/strings.xml +++ b/patches/src/main/resources/addresources/values-is-rIS/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-it-rIT/strings.xml b/patches/src/main/resources/addresources/values-it-rIT/strings.xml index a3db099e8a..cc38025361 100644 --- a/patches/src/main/resources/addresources/values-it-rIT/strings.xml +++ b/patches/src/main/resources/addresources/values-it-rIT/strings.xml @@ -1464,6 +1464,11 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Il pulsante è visualizzato. Tieni premuto per ripristinare la velocità di riproduzione predefinita Il pulsante non è visibile + + Mostra il pulsante qualità video + Il pulsante è visibile. Tocca e tieni premuto per ripristinare la qualità predefinita. + Il pulsante non è visibile. + Menu di velocità di riproduzione personalizzato Il menu di velocità personalizzato è visibile diff --git a/patches/src/main/resources/addresources/values-iw-rIL/strings.xml b/patches/src/main/resources/addresources/values-iw-rIL/strings.xml index e6a586018b..dffb5d3403 100644 --- a/patches/src/main/resources/addresources/values-iw-rIL/strings.xml +++ b/patches/src/main/resources/addresources/values-iw-rIL/strings.xml @@ -1467,6 +1467,11 @@ Second \"item\" text" הלחצן מוצג. יש להקיש ולהחזיק כדי לאפס את מהירות ההפעלה לברירת מחדל הלחצן אינו מוצג + + הצג כפתור איכות וידאו + הלחצן מוצג. גע והחזק כדי לאפס את האיכות לברירת מחדל + הלחצן אינו מוצג + תפריט מהירות הפעלה מותאם אישית תפריט מהירות מותאם אישית מוצג diff --git a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml index 043f12f7b2..8ec1cf7bd1 100644 --- a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml +++ b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml @@ -475,9 +475,9 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に その他 アプリがインストールされていません %s はインストールされていません。インストールしてください。 - "パッケージ名 %s のインストール済みアプリが見つかりませんでした + "パッケージ名「%s」のインストール済みアプリが見つかりませんでした -パッケージ名が正しいこと、およびアプリがインストールされていることを確認してください" +パッケージ名が正しいこと、アプリがインストールされていることを確認してください" パッケージ名は空欄にはできません @@ -1461,10 +1461,15 @@ Automotive レイアウト ショートの画質 (%1$s): %2$s - 再生速度設定ボタンを表示する - ボタンはオーバーレイに表示されます。長押しすると、再生速度がデフォルトの値にリセットされます + 再生速度設定ボタンを表示 + ボタンがオーバーレイに表示されます。長押しすると、再生速度がデフォルトの値にリセットされます ボタンはオーバーレイに表示されません + + 画質設定ボタンを表示 + ボタンがオーバーレイに表示されます。長押しすると、画質がデフォルトの値にリセットされます + ボタンはオーバーレイに表示されません + カスタム再生速度メニュー カスタム再生速度リストが再生速度メニューに表示されます diff --git a/patches/src/main/resources/addresources/values-ka-rGE/strings.xml b/patches/src/main/resources/addresources/values-ka-rGE/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ka-rGE/strings.xml +++ b/patches/src/main/resources/addresources/values-ka-rGE/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml b/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml +++ b/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-km-rKH/strings.xml b/patches/src/main/resources/addresources/values-km-rKH/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-km-rKH/strings.xml +++ b/patches/src/main/resources/addresources/values-km-rKH/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-kn-rIN/strings.xml b/patches/src/main/resources/addresources/values-kn-rIN/strings.xml index f97427db6c..b02eb27462 100644 --- a/patches/src/main/resources/addresources/values-kn-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-kn-rIN/strings.xml @@ -237,6 +237,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ko-rKR/strings.xml b/patches/src/main/resources/addresources/values-ko-rKR/strings.xml index 6feaea9336..b00e3ac5d1 100644 --- a/patches/src/main/resources/addresources/values-ko-rKR/strings.xml +++ b/patches/src/main/resources/addresources/values-ko-rKR/strings.xml @@ -1472,6 +1472,11 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요" 버튼을 표시합니다\n\n• 버튼을 길게 누르면 동영상 재생 속도가 기본값으로 초기화됩니다 버튼을 표시하지 않습니다 + + 동영상 화질 버튼 표시하기 + 버튼을 표시합니다\n\n• 버튼을 길게 누르면 화질이 기본값으로 초기화됩니다 + 버튼을 표시하지 않습니다 + 사용자 정의 동영상 재생 속도 활성화하기 사용자 정의 동영상 재생 속도를 활성화합니다 diff --git a/patches/src/main/resources/addresources/values-ky-rKG/strings.xml b/patches/src/main/resources/addresources/values-ky-rKG/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ky-rKG/strings.xml +++ b/patches/src/main/resources/addresources/values-ky-rKG/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-lo-rLA/strings.xml b/patches/src/main/resources/addresources/values-lo-rLA/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-lo-rLA/strings.xml +++ b/patches/src/main/resources/addresources/values-lo-rLA/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-lt-rLT/strings.xml b/patches/src/main/resources/addresources/values-lt-rLT/strings.xml index 7998220f24..20e2d8801d 100644 --- a/patches/src/main/resources/addresources/values-lt-rLT/strings.xml +++ b/patches/src/main/resources/addresources/values-lt-rLT/strings.xml @@ -1464,6 +1464,11 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v Mygtukas rodomas. Palieskite ir palaikykite, kad atkūrimo greitį nustatytumėte į numatytąjį. Mygtukas nerodomas + + Rodyti vaizdo kokybės mygtuką + Mygtukas rodomas. Palaikykite nuspaudę, kad atstatytumėte kokybę į numatytąją + Mygtukas nerodomas + Tinkintas atkūrimo greičio meniu Tinkintas greičio meniu rodomas diff --git a/patches/src/main/resources/addresources/values-lv-rLV/strings.xml b/patches/src/main/resources/addresources/values-lv-rLV/strings.xml index a9b83e6624..a9189360fe 100644 --- a/patches/src/main/resources/addresources/values-lv-rLV/strings.xml +++ b/patches/src/main/resources/addresources/values-lv-rLV/strings.xml @@ -1466,6 +1466,11 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk Poga ir redzama. Pieskarieties un turiet, lai atiestatītu atskaņošanas ātrumu uz noklusējuma Poga netiek rādīta + + Rādīt video kvalitātes pogu + Poga tiek rādīta. Pieskarieties un turiet, lai atiestatītu kvalitāti uz noklusējuma + Poga netiek rādīta + Pielāgotas atskaņošanas ātruma izvēlne Pielāgotas ātruma izvēlne tiek rādīta diff --git a/patches/src/main/resources/addresources/values-mk-rMK/strings.xml b/patches/src/main/resources/addresources/values-mk-rMK/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-mk-rMK/strings.xml +++ b/patches/src/main/resources/addresources/values-mk-rMK/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ml-rIN/strings.xml b/patches/src/main/resources/addresources/values-ml-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ml-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ml-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-mn-rMN/strings.xml b/patches/src/main/resources/addresources/values-mn-rMN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-mn-rMN/strings.xml +++ b/patches/src/main/resources/addresources/values-mn-rMN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-mr-rIN/strings.xml b/patches/src/main/resources/addresources/values-mr-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-mr-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-mr-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ms-rMY/strings.xml b/patches/src/main/resources/addresources/values-ms-rMY/strings.xml index 030cd27fb0..8a05db94e9 100644 --- a/patches/src/main/resources/addresources/values-ms-rMY/strings.xml +++ b/patches/src/main/resources/addresources/values-ms-rMY/strings.xml @@ -223,6 +223,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-my-rMM/strings.xml b/patches/src/main/resources/addresources/values-my-rMM/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-my-rMM/strings.xml +++ b/patches/src/main/resources/addresources/values-my-rMM/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-nb-rNO/strings.xml b/patches/src/main/resources/addresources/values-nb-rNO/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-nb-rNO/strings.xml +++ b/patches/src/main/resources/addresources/values-nb-rNO/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ne-rIN/strings.xml b/patches/src/main/resources/addresources/values-ne-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ne-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ne-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-nl-rNL/strings.xml b/patches/src/main/resources/addresources/values-nl-rNL/strings.xml index 0fb4251ae5..43ddc32b8a 100644 --- a/patches/src/main/resources/addresources/values-nl-rNL/strings.xml +++ b/patches/src/main/resources/addresources/values-nl-rNL/strings.xml @@ -1463,6 +1463,11 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen" De knop wordt weergegeven. Tik en houd vast om de afspeelsnelheid terug te zetten naar de standaardwaarde Knop wordt niet weergegeven + + Toon videokwaliteitknop + Knop wordt weergegeven. Tik en houd vast om de kwaliteit terug te zetten naar standaard + Knop wordt niet weergegeven + Menu voor aangepaste afspeelsnelheid Menu voor aangepaste snelheid wordt weergegeven diff --git a/patches/src/main/resources/addresources/values-or-rIN/strings.xml b/patches/src/main/resources/addresources/values-or-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-or-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-or-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-pa-rIN/strings.xml b/patches/src/main/resources/addresources/values-pa-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-pa-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-pa-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-pl-rPL/strings.xml b/patches/src/main/resources/addresources/values-pl-rPL/strings.xml index e5fe980263..76e5de4ac4 100644 --- a/patches/src/main/resources/addresources/values-pl-rPL/strings.xml +++ b/patches/src/main/resources/addresources/values-pl-rPL/strings.xml @@ -1461,6 +1461,11 @@ Włączenie tego może odblokować wyższe jakości wideo" Przycisk jest widoczny. Dotknij i przytrzymaj, aby zresetować prędkość odtwarzania do domyślnej Przycisk nie jest widoczny + + Pokaż przycisk jakości wideo + Przycisk jest widoczny. Dotknij i przytrzymaj, aby zresetować jakość do wartości domyślnych + Przycisk nie jest widoczny + Niestandardowe menu prędkości odtwarzania Niestandardowe menu prędkości jest widoczne diff --git a/patches/src/main/resources/addresources/values-pt-rBR/strings.xml b/patches/src/main/resources/addresources/values-pt-rBR/strings.xml index 7ac040cb92..ecaebb0abd 100644 --- a/patches/src/main/resources/addresources/values-pt-rBR/strings.xml +++ b/patches/src/main/resources/addresources/values-pt-rBR/strings.xml @@ -1464,6 +1464,11 @@ Habilitar isso pode desbloquear qualidades de vídeo mais altas" O botão é exibido. Toque e mantenha pressionado para redefinir a velocidade de reprodução para o padrão Botão não está visível + + Mostrar botão de qualidade de vídeo + O botão é exibido. Toque e segure para redefinir a qualidade para o padrão + O botão não é exibido + Menu de velocidade de reprodução personalizado O menu de velocidade personalizado é mostrado diff --git a/patches/src/main/resources/addresources/values-pt-rPT/strings.xml b/patches/src/main/resources/addresources/values-pt-rPT/strings.xml index fefff758e3..e8a9d139a4 100644 --- a/patches/src/main/resources/addresources/values-pt-rPT/strings.xml +++ b/patches/src/main/resources/addresources/values-pt-rPT/strings.xml @@ -1465,6 +1465,11 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"O botão é mostrado. Toque e segure para redefinir a velocidade de reprodução para o padrão O botão não está visível + + Mostrar botão de qualidade de vídeo + O botão é exibido. Toque e segure para redefinir a qualidade para o padrão + O botão não é exibido + Menu personalizado de velocidade de reprodução O menu de velocidade personalizado é exibido diff --git a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml index 1f133df404..545a10b805 100644 --- a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml +++ b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml @@ -1464,6 +1464,12 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Butonul este afișat. Atingeți și mențineți apăsat pentru a reseta viteza de redare la cea implicită Butonul nu este afișat + + Afi +tr + Butonul este afișat. Atingeți și mențineți apăsat pentru a reseta calitatea la valoarea implicită + Butonul nu este afișat. + Meniu de redare personalizat Meniul de viteză personalizat este afișat diff --git a/patches/src/main/resources/addresources/values-ru-rRU/strings.xml b/patches/src/main/resources/addresources/values-ru-rRU/strings.xml index e1709b745f..0c25ad385e 100644 --- a/patches/src/main/resources/addresources/values-ru-rRU/strings.xml +++ b/patches/src/main/resources/addresources/values-ru-rRU/strings.xml @@ -1472,6 +1472,11 @@ Second \"item\" text" Кнопка показана. Нажмите и удерживайте, чтобы сбросить скорость воспроизведения до значения по умолчанию Кнопка выбора скорости воспроизведения скрыта + + Показать кнопку качества видео + Кнопка показана. Нажмите и удерживайте, чтобы сбросить качество до значения по умолчанию + Кнопка выбора скорости воспроизведения скрыта + Показать кастомное меню скорости Кастомное меню скорости воспроизведения показано diff --git a/patches/src/main/resources/addresources/values-si-rLK/strings.xml b/patches/src/main/resources/addresources/values-si-rLK/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-si-rLK/strings.xml +++ b/patches/src/main/resources/addresources/values-si-rLK/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-sk-rSK/strings.xml b/patches/src/main/resources/addresources/values-sk-rSK/strings.xml index 7aa9fbcaf3..7edf222f5d 100644 --- a/patches/src/main/resources/addresources/values-sk-rSK/strings.xml +++ b/patches/src/main/resources/addresources/values-sk-rSK/strings.xml @@ -1458,6 +1458,11 @@ Povolením tejto možnosti môžete odomknúť vyššie kvality videa" Zobrazuje sa tlačidlo. Ťuknite a podržte, ak chcete obnoviť predvolenú rýchlosť prehrávania Tlačidlo nie je zobrazené + + Zobraziť tlačidlo kvality videa + Tlačidlo sa zobrazí. Klepnite a podržte pre resetovanie kvality na predvolenú + Tlačidlo sa nezobrazuje + Menu vlastnej rýchlosti prehrávania Menu vlastnej rýchlosti sa zobrazuje diff --git a/patches/src/main/resources/addresources/values-sl-rSI/strings.xml b/patches/src/main/resources/addresources/values-sl-rSI/strings.xml index ff591f3ee9..503ce3a85d 100644 --- a/patches/src/main/resources/addresources/values-sl-rSI/strings.xml +++ b/patches/src/main/resources/addresources/values-sl-rSI/strings.xml @@ -1465,6 +1465,11 @@ Omogočanje tega lahko odklene višje kakovosti videa" Gumb je prikazan. Dotaknite se ga in ga pridržite, da ponastavite hitrost predvajanja na privzeto. Gumb ni prikazan + + Prikaži gumb za kakovost videa + Prikazan je gumb. Dotaknite se in držite, da ponastavite kakovost na privzeto + Gumb ni prikazan + Meni za nastavitev hitrosti predvajanja Meni za nastavitev hitrosti je prikazan diff --git a/patches/src/main/resources/addresources/values-sq-rAL/strings.xml b/patches/src/main/resources/addresources/values-sq-rAL/strings.xml index 6b6d629c62..fefafa9d4a 100644 --- a/patches/src/main/resources/addresources/values-sq-rAL/strings.xml +++ b/patches/src/main/resources/addresources/values-sq-rAL/strings.xml @@ -1463,6 +1463,11 @@ Aktivizimi i kësaj mund të zhbllokojë cilësi më të larta video" Butoni shfaqet. Prekni dhe mbani për të rivendosur shpejtësinë e riprodhimit në atë të parazgjedhur Butoni nuk shfaqet + + Shfaq butonin e cilësisë së videos + Butoni shfaqet. Prekni dhe mbani shtypur për të rivendosur cilësinë në parazgjedhur + Butoni nuk shfaqet + Menyja e shpejtësisë së përsëritjes së përshtatshme Menyja e shpejtësisë së përshtatshme shfaqet diff --git a/patches/src/main/resources/addresources/values-sr-rCS/strings.xml b/patches/src/main/resources/addresources/values-sr-rCS/strings.xml index 8d4dcccb08..f562a083fe 100644 --- a/patches/src/main/resources/addresources/values-sr-rCS/strings.xml +++ b/patches/src/main/resources/addresources/values-sr-rCS/strings.xml @@ -1464,6 +1464,11 @@ Ako ovo omogućite, mogu biti otključani viši kvaliteti videa" Dugme je prikazano. Dodirnite i zadržite da biste vratili brzinu reprodukcije na podrazumevanu vrednost Dugme dijaloga za brzinu nije prikazano + + Prikaži dugme za kvalitet video zapisa + Dugme je prikazano. Dodirnite i zadržite za resetovanje kvaliteta na podrazumevano + Dugme nije prikazano + Meni prilagođene brzine reprodukcije Meni prilagođene brzine reprodukcije je prikazan diff --git a/patches/src/main/resources/addresources/values-sr-rSP/strings.xml b/patches/src/main/resources/addresources/values-sr-rSP/strings.xml index 3ad3b49a48..16d76c8a2f 100644 --- a/patches/src/main/resources/addresources/values-sr-rSP/strings.xml +++ b/patches/src/main/resources/addresources/values-sr-rSP/strings.xml @@ -1467,6 +1467,11 @@ Second \"item\" text" Дугме је приказано. Додирните и задржите да бисте вратили брзину репродукције на подразумевану вредност Дугме дијалога за брзину није приказано + + Прикажи дугме за квалитет видеа + Дугме је приказано. Притисните и држите да бисте ресетовали квалитет на подразумевани + Дугме није приказано + Мени прилагођене брзине репродукције Мени прилагођене брзине репродукције је приказан diff --git a/patches/src/main/resources/addresources/values-sv-rSE/strings.xml b/patches/src/main/resources/addresources/values-sv-rSE/strings.xml index 2a8cca521a..cc580ebd37 100644 --- a/patches/src/main/resources/addresources/values-sv-rSE/strings.xml +++ b/patches/src/main/resources/addresources/values-sv-rSE/strings.xml @@ -1464,6 +1464,11 @@ Om du aktiverar detta kan högre videokvaliteter låsas upp" Knappen visas. Tryck länge för att återställa uppspelningshastigheten till standardhastigheten Knappen visas inte + + Visa videokvalitetsknapp + Knappen visas. Tryck länge för att återställa kvaliteten till standardkvaliteten + Knappen visas inte + Anpassad meny för uppspelningshastighet Anpassad hastighetsmeny visas diff --git a/patches/src/main/resources/addresources/values-sw-rKE/strings.xml b/patches/src/main/resources/addresources/values-sw-rKE/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-sw-rKE/strings.xml +++ b/patches/src/main/resources/addresources/values-sw-rKE/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-ta-rIN/strings.xml b/patches/src/main/resources/addresources/values-ta-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ta-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ta-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-te-rIN/strings.xml b/patches/src/main/resources/addresources/values-te-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-te-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-te-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-th-rTH/strings.xml b/patches/src/main/resources/addresources/values-th-rTH/strings.xml index 241280d7b0..a4245b734f 100644 --- a/patches/src/main/resources/addresources/values-th-rTH/strings.xml +++ b/patches/src/main/resources/addresources/values-th-rTH/strings.xml @@ -1467,6 +1467,11 @@ User id ของคุณเหมือนกับรหัสผ่าน ปุ่มจะปรากฏขึ้น แตะค้างไว้เพื่อรีเซ็ตความเร็วในการเล่นเป็นค่าเริ่มต้น ไม่แสดงปุ่ม + + แสดงปุ่มคุณภาพวิดีโอ + แสดงปุ่มแล้ว แตะค้างไว้เพื่อรีเซ็ตคุณภาพเป็นค่าเริ่มต้น + ไม่ได้แสดงปุ่ม + เมนูกำหนดความเร็วในการเล่นแบบกำหนดเอง แสดงเมนูกำหนดความเร็ว diff --git a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml index b1fb862156..362176aee9 100644 --- a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml +++ b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml @@ -1472,6 +1472,11 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Düğme görünür. Oynatma hızını varsayılana sıfırlamak için dokunup basılı tutun Düğme gösterilmez + + Video kalitesi düğmesini göster + Düğme görünür. Kaliteyi varsayılana sıfırlamak için dokunup basılı tutun + Düğme gösterilmez + Özel oynatma hızı menüsü Özel oynatma hızı menüsü gösterilir diff --git a/patches/src/main/resources/addresources/values-uk-rUA/strings.xml b/patches/src/main/resources/addresources/values-uk-rUA/strings.xml index 00f7390aa4..b9f11c10d9 100644 --- a/patches/src/main/resources/addresources/values-uk-rUA/strings.xml +++ b/patches/src/main/resources/addresources/values-uk-rUA/strings.xml @@ -1464,13 +1464,18 @@ Second \"item\" text" Кнопка показується. Натисніть і утримуйте, щоб відновити стандартну швидкість відтворення Кнопка швидкості відтворення не показується + + Кнопка якості відео + Кнопка показується. Натисніть і утримуйте, щоб відновити стандартну якість + Кнопка швидкості відтворення не показується + Користувацьке меню швидкості відтворення Користувацьке меню швидкості відтворення показується Користувацьке меню швидкості відтворення не показується Відновити старе меню швидкості відтворення Показується старе меню швидкості - Показується сучасне меню швидкості + Показується новітнє меню швидкості Користувацькі швидкості відтворення Додавання або зміна користувацьких швидкостей відтворення Користувацькі швидкості повинні бути менші ніж %s diff --git a/patches/src/main/resources/addresources/values-ur-rIN/strings.xml b/patches/src/main/resources/addresources/values-ur-rIN/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-ur-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ur-rIN/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml b/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml +++ b/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + diff --git a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml index e67c038ab4..73eb6e00f3 100644 --- a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml +++ b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml @@ -126,12 +126,12 @@ Tuy nhiên, bật tính năng này cũng sẽ ghi lại một số dữ liệu n Ghi nhật ký truy vết ngăn xếp Nhật ký gỡ lỗi bao gồm truy vết ngăn xếp Nhật ký gỡ lỗi không bao gồm truy vết ngăn xếp - Hiện thông báo nổi về lỗi ReVanced - Thông báo nổi được hiển thị nếu xảy ra lỗi - Thông báo nổi không được hiển thị nếu xảy ra lỗi - "Tắt thông báo lỗi sẽ ẩn tất cả thông báo lỗi của ReVanced. + Hiện thông báo ngắn về lỗi ReVanced + Thông báo ngắn sẽ hiện nếu xảy ra lỗi + Thông báo ngắn không hiện nếu xảy ra lỗi + "Tắt thông báo lỗi sẽ ẩn mọi thông báo lỗi từ ReVanced. -Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ nào." +Bạn sẽ không được thông báo khi xẩy ra lỗi bất ngờ." Xuất nhật ký gỡ lỗi Sao chép nhật ký gỡ lỗi ReVanced vào bảng nhớ tạm Tính năng ghi nhật ký gỡ lỗi đã tắt @@ -209,8 +209,8 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Kệ vé đang hiển thị Ẩn nhãn video đề xuất - Nhãn \"Mọi người cũng xem\" và \"Bạn có thể thích\" trong kết quả tìm kiếm đã bị ẩn - Nhãn \"Mọi người cũng xem\" và \"Bạn có thể thích\" trong kết quả tìm kiếm được hiển thị + Nhãn \"Mọi người cũng xem video này\" và \"Có thể bạn cũng thích nội dung này\" trong kết quả tìm kiếm đã bị ẩn + Nhãn \"Mọi người cũng xem video này\" và \"Có thể bạn cũng thích nội dung này\" trong kết quả tìm kiếm được hiển thị Ẩn YouTube Doodles Hoạt ảnh YouTube Doodles trên logo đã bị ẩn @@ -688,7 +688,7 @@ Nếu thay đổi cài đặt này không có hiệu lực, hãy thử chuyển "Trình đơn bản âm thanh đã bị ẩn -Để hiển thị trình đơn Bản âm thanh, hãy thay đổi 'Giả mạo luồng phát video' thành iOS TV" +Để hiển thị trình đơn bản âm thanh, hãy đổi 'Giả mạo luồng video' thành iOS TV" Ẩn Xem ở chế độ thực tế ảo Trình đơn xem ở chế độ thực tế ảo đã bị ẩn @@ -900,12 +900,12 @@ Cài đặt → Phát → Tự động phát video tiếp theo" - Lượt không thích tạm thời không khả dụng (API hết thời gian chờ) + Không thể hiện số Dislike (API hết thời gian chờ) Lượt không thích không khả dụng ( trạng thái %d) - Lượt không thích không khả dụng (giới hạn API máy khách) + Không thể hiện số dislike (đạt giới hạn API ứng dụng) Số lượt không thích không khả dụng (%s) - Tải lại video để bình chọn bằng Return YouTube Dislike + Tải lại video để bỏ phiếu bằng ReturnYouTubeDislike Đã ẩn bởi chủ sở hữu Số lượt không thích được hiển thị @@ -925,26 +925,26 @@ Hạn chế: Số lượt không thích có thể không xuất hiện ở chế Hiện lượt thích ước tính Video có lượt thích bị tắt hiển thị số lượt thích ước tính Không hiển thị lượt thích ước tính - Hiện thông báo nổi nếu API không khả dụng - Thông báo nổi được hiển thị nếu Return YouTube Dislike không khả dụng - Thông báo nổi không được hiển thị nếu Return YouTube Dislike không khả dụng + Hiện thông báo ngắn nếu API không khả dụng + Thông báo ngắn sẽ hiện nếu Return YouTube Dislike không khả dụng + Thông báo ngắn không hiện nếu Return YouTube Dislike không khả dụng Dữ liệu được cung cấp bởi API Return YouTube Dislike. Nhấn vào đây để tìm hiểu thêm Thống kê API ReturnYouTubeDislike của thiết bị này - Thời gian phản hồi của API, trung binh - Thời gian phản hồi của API, tối thiểu - Thời gian phản hồi của API, tối đa - Thời gian phản hồi của API, video cuối - Lượt không thích tạm thời không khả dụng - Đạt giới hạn API máy khách có hiệu lực + Thời gian phản hồi API, trung binh + Thời gian phản hồi API, tối thiểu + Thời gian phản hồi API, tối đa + Thời gian phản hồi API, video gần nhất + Tạm thời không thể hiển thị số lượt không thích - Đang bị giới hạn API ứng dụng Số lượt truy vấn API, số lần gọi Không gọi mạng lần nào %d lần gọi mạng Số lượt truy vấn API, số lần hết hạn Không gọi mạng lần nào bị hết hạn %d lần gọi mạng bị hết hạn - Số lần đạt giới hạn API máy khách - Không gặp phải giới hạn truy cập máy khách - Gặp phải %d lần đạt giới hạn truy cập máy khách + Giới hạn truy cập API ứng dụng + Chưa từng bị giới hạn API + Đã bị giới hạn API %d lần %d mili-giây @@ -971,9 +971,9 @@ Hoạt động tốt nhất với chất lượng video 720p trở xuống và k Bật SponsorBlock SponsorBlock là một hệ thống dựa trên đóng góp bởi cộng đồng để bỏ qua các phần gây khó chịu trong video YouTube Giao diện - Hiện nút bình chọn - Nút bình chọn phân đoạn được hiển thị - Nút bình chọn phân đoạn không được hiển thị + Hiện nút bỏ phiếu + Nút bỏ phiếu phân đoạn được hiển thị + Nút bỏ phiếu phân đoạn không được hiển thị Dùng bố cục vuông Các nút và điều khiển có hình vuông Các nút và điều khiển được bo tròn @@ -986,11 +986,12 @@ Hoạt động tốt nhất với chất lượng video 720p trở xuống và k Nút bỏ qua được hiển thị cho toàn bộ phân đoạn Thời gian hiển thị nút bỏ qua Thời gian hiển thị nút bỏ qua và nút bỏ qua đến phần nổi bật trước khi tự động ẩn - Hiện thông báo nổi hoàn tác bỏ qua - Thông báo nổi được hiển thị mỗi khi tự động bỏ qua một phân đoạn. Chạm vào thông báo nổi để hoàn tác bỏ qua phân đoạn vừa rồi - Thông báo nổi không được hiển thị - Thời gian hiển thị thông báo nổi bỏ qua - Thời gian hiển thị thông báo nổi hoàn tác bỏ qua + Hiện thông báo ngắn hoàn tác bỏ qua + Thông báo ngắn sẽ hiện mỗi khi tự động bỏ qua một phân đoạn. +Chạm vào thông báo đó để hoàn tác bỏ qua + Thông báo ngắn không hiện + Thời gian thông báo ngắn tồn tại + Thời gian thông báo ngắn tồn tại sau khi bỏ qua phân đoạn 1 giây 2 giây 3 giây @@ -1018,9 +1019,9 @@ Hoạt động tốt nhất với chất lượng video 720p trở xuống và k Đã đọc Hiện cho tôi Chung - Hiện một thông báo nổi nếu API không khả dụng - Thông báo nổi được hiển thị nếu SponsorBlock không khả dụng - Thông báo nổi không được hiển thị nếu SponsorBlock không khả dụng + Hiện thông báo ngắn nếu API không khả dụng + Thông báo ngắn sẽ hiện nếu SponsorBlock không khả dụng + Thông báo ngắn không hiện nếu SponsorBlock không khả dụng Bật theo dõi số lần bỏ qua Cho phép bảng xếp hạng SponsorBlock biết đã tiết kiệm được bao nhiêu thời gian. Một tin nhắn được gửi đến bảng xếp hạng mỗi khi một phân đoạn bị bỏ qua Theo dõi số lần bỏ qua không được bật @@ -1110,16 +1111,16 @@ ID người dùng của bạn giống như mật khẩu và không bao giờ đ Đã tồn tại" Phân đoạn được gửi thành công - SponsorBlock tạm thời không khả dụng (API hết thời gian chờ) + SponsorBlock tạm thời không khả dụng (hết thời gian chờ API) SponsorBlock tạm thời không khả dụng (trạng thái %d) SponsorBlock tạm thời không khả dụng - Không thể bình chọn cho phân đoạn (API hết hạn) - Ko thể bình chọn cho phân đoạn (t.thái: %1$d %2$s) - Không thể bình chọn cho phân đoạn: %s + Không thể bỏ phiếu phân đoạn (hết thời gian chờ API) + Không thể bỏ phiếu phân đoạn (trạng thái: %1$d %2$s) + Không thể bỏ phiếu cho phân đoạn: %s Ủng hộ Phản đối Thay đổi danh mục - Không có phân đoạn nào để bình chọn + Không có phân đoạn nào để bỏ phiếu %1$s đến %2$s Chọn danh mục phân đoạn @@ -1303,7 +1304,7 @@ Vuốt để mở rộng hoặc đóng" Pixel phải nằm giữa %1$s và %2$s Độ mờ lớp phủ Giá trị độ mờ của lớp phủ trình phát trong khoảng từ 0 đến 100, trong đó 0 là trong suốt - Độ mờ lớp phủ trình phát thu nhỏ phải nằm trong khoảng từ 0 đến 100 + Độ mờ lớp phủ phải nằm trong khoảng từ 0-100 Bật màn hình tải màu dốc @@ -1330,11 +1331,11 @@ Vuốt để mở rộng hoặc đóng" Tùy chỉnh - Vượt qua hạn chế khu vực cho hình ảnh - Đang dùng máy chủ hình ảnh yt4.ggpht.com - "Đang dùng máy chủ hình ảnh gốc + Bỏ qua hạn chế khu vực khi tải ảnh + Đang dùng máy chủ ảnh yt4.ggpht.com + "Đang dùng máy chủ ảnh gốc -Bật tính năng này có thể khắc phục hình ảnh bị thiếu khi bị chặn ở một số khu vực" +Bật tính năng này có thể khắc phục tình trạng hình ảnh không hiển thị ở một số quốc gia" @@ -1354,9 +1355,9 @@ Bật tính năng này có thể khắc phục hình ảnh bị thiếu khi bị Nếu được bật, URL video sẽ được gửi đến máy chủ API và không có dữ liệu nào khác được gửi. Nếu video không có hình thu nhỏ DeArrow, thì hình thu nhỏ gốc hoặc ảnh chụp tĩnh sẽ được hiển thị Nhấn vào đây để tìm hiểu thêm về DeArrow" - Hiện một thông báo nổi nếu API không khả dụng - Thông báo nổi được hiển thị nếu DeArrow không khả dụng - Thông báo nổi không được hiển thị nếu DeArrow không khả dụng + Hiện thông báo ngắn nếu API không khả dụng + Thông báo ngắn sẽ hiện nếu DeArrow không khả dụng + Thông báo ngắn không hiện nếu DeArrow không khả dụng Điểm cuối API DeArrow URL của điểm cuối bộ đệm hình thu nhỏ DeArrow Chụp tĩnh video @@ -1373,12 +1374,12 @@ Nhấn vào đây để tìm hiểu thêm về DeArrow" DeArrow tạm thời không khả dụng - Hiện công bố của ReVanced - Thông báo khi khởi động được hiển thị - Thông báo khi khởi động không được hiển thị - Hiện công bố khi khởi chạy - Kết nối đến nguồn cấp công bố thất bại - Từ bỏ + Hiện thông báo của ReVanced + Thông báo sẽ được hiển thị khi khởi động ứng dụng + Thông báo không được hiển thị khi khởi động ứng dụng + Hiện thông báo khi khởi động + Không thể tải thông báo từ máy chủ + Đóng Cảnh báo @@ -1394,7 +1395,7 @@ Nhấn vào đây để tìm hiểu thêm về DeArrow" Giả mạo kích thước thiết bị "Kích thước thiết bị đã được giả mạo -Chất lượng video cao hơn có thể được mở khóa nhưng bạn có thể gặp hiện tượng giật lag khi phát video, hao pin hơn và các sự cố không xác định" +Có thể mở khóa chất lượng video cao hơn nhưng bạn có thể gặp hiện tượng giật lag khi phát video, hao pin và các sự cố không xác định khác" "Kích thước thiết bị không được giả mạo Bật tính năng này có thể mở khóa chất lượng video cao hơn" @@ -1424,9 +1425,9 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Nếu gần đây bạn đã cập nhật thông tin đăng nhập tài khoản của mình, hãy gỡ và cài đặt lại MicroG. - Vượt chuyển hướng URL - Chuyển hướng URL được vượt - Chuyển hướng URL không được vượt + Bỏ qua chuyển hướng URL + Chuyển hướng URL đã được bỏ qua + Chuyển hướng URL không được bỏ qua Mở liên kết trong trình duyệt @@ -1443,7 +1444,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Đang dùng ngôn ngữ âm thanh gốc Đang dùng âm thanh mặc định - Để dùng tính năng này, hãy thay đổi \'Giả mạo luồng phát video\' thành iOS TV + Để dùng tính năng này, hãy đổi \'Giả mạo luồng video\' thành iOS TV @@ -1451,9 +1452,9 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Nhớ các thay đổi chất lượng video Thay đổi chất lượng áp dụng cho tất cả video Thay đổi chất lượng chỉ áp dụng cho video hiện tại - Hiện thông báo nổi khi chất lượng video thay đổi - Thông báo nổi sẽ hiển thị khi chất lượng video mặc định được thay đổi - Thông báo nổi sẽ không hiển thị khi chất lượng video mặc định được thay đổi + Hiện thông báo ngắn khi thay đổi chất lượng video + Thông báo ngắn sẽ hiện khi chất lượng video mặc định được thay đổi + Thông báo ngắn không hiện khi chất lượng video mặc định được thay đổi Chất lượng mặc định trên mạng Wi-Fi Chất lượng mặc định trên mạng di động Nhớ các thay đổi chất lượng Shorts @@ -1463,7 +1464,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Chất lượng Shorts mặc định trên mạng di động di động wifi - Đã thay đổi chất lượng %1$s mặc định: %2$s + Đã thay đổi chất lượng mặc định %1$s: %2$s Đã thay đổi chất lượng Shorts %1$s: %2$s @@ -1471,6 +1472,11 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Nút được hiển thị. Nhấn và giữ để đặt lại tốc độ phát về mặc định Nút không được hiển thị + + Hiện nút chất lượng video + Nút đã được hiển thị. Chạm và giữ để đặt lại chất lượng về mặc định + Nút không được hiển thị + Trình đơn tốc độ phát tùy chỉnh Trình đơn tốc độ phát tùy chỉnh được hiển thị @@ -1490,9 +1496,9 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Nhớ các thay đổi tốc độ phát Thay đổi tốc độ phát áp dụng cho tất cả video Thay đổi tốc độ phát chỉ áp dụng cho video hiện tại - Hiện thông báo nổi khi tốc độ phát thay đổi - Thông báo nổi sẽ hiển thị khi tốc độ phát mặc định được thay đổi - Thông báo nổi không hiển thị khi tốc độ phát mặc định được thay đổi + Hiện thông báo ngắn khi thay đổi tốc độ phát + Thông báo ngắn sẽ hiện khi tốc độ phát mặc định được thay đổi + Thông báo ngắn không hiện khi tốc độ phát mặc định được thay đổi Tốc độ phát mặc định Đã thay đổi tốc độ phát mặc định thành: %s @@ -1512,35 +1518,35 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Vuốt để tua không được bật - Giả mạo luồng phát video - Giả mạo luồng video máy khách để ngăn ngừa sự cố phát - Giả mạo luồng phát video + Giả mạo luồng video + Giả mạo luồng video của thiết bị nhằm ngăn chặn lỗi khi phát + Giả mạo luồng video Luồng video đã được giả mạo "Luồng video không được giả mạo -Có thể gặp sự cố phát video" - Tắt cài đặt này có thể gây ra sự cố phát video. - Máy khách mặc định - Buộc iOS AVC (H.264) - Bộ giải mã video bị buộc thành AVC (H.264) - Bộ giải mã video được xác định tự động - "Bật tính năng này có thể cải thiện thời lượng pin và khắc phục tình trạng giật lag khi phát. +Có thể gặp lỗi khi phát video" + Tắt cài đặt này có thể gây ra lỗi khi phát video. + Loại thiết bị mặc định + Bắt buộc iOS AVC (H.264) + Codec video bị buộc phải là AVC (H.264) + Codec video sẽ được xác định tự động + "Bật tuỳ chọn này có thể giúp tiết kiệm pin và khắc phục tình trạng giật lag khi phát video. -AVC có độ phân giải tối đa là 1080p, bộ giải mã âm thanh OPUS không khả dụng và phát video sẽ sử dụng nhiều dữ liệu di động hơn VP9 hoặc AV1." - Các hạn chế khi giả mạo iOS +AVC hỗ trợ độ phân giải tối đa là 1080p, codec âm thanh OPUS không khả dụng và phát video sẽ tiêu tốn nhiều dữ liệu di động hơn so với VP9 hoặc AV1." + Hạn chế khi giả mạo iOS "• Phim hoặc video có trả phí có thể không phát được • Âm lượng ổn định không khả dụng -• Video có thể kết thúc sớm hơn 1 giây" - Các hạn chế khi giả mạo Android +• Video kết thúc sớm hơn 1 giây" + Hạn chế khi giả mạo Android "• Trình đơn bản âm thanh bị thiếu • Âm lượng ổn định không khả dụng • Tùy chọn âm thanh gốc không khả dụng" - • Không có bộ giải mã video AV1 + • Không có codec video AV1 • Video dành cho trẻ em có thể không phát được khi đăng xuất hoặc ở chế độ ẩn danh Hiện trong Thống kê chi tiết - Loại máy khách được hiển thị trong Thống kê chi tiết - Máy khách đã bị ẩn trong Thống kê chi tiết - Ngôn ngữ âm thanh mặc định của VR + Loại máy khách đã được hiển thị trong Thống kê chi tiết + Loại thiết bị đã ẩn trong Thống kê chi tiết + Ngôn ngữ âm thanh mặc định (VR) diff --git a/patches/src/main/resources/addresources/values-zh-rCN/strings.xml b/patches/src/main/resources/addresources/values-zh-rCN/strings.xml index 6c9bf91748..6386f8b492 100644 --- a/patches/src/main/resources/addresources/values-zh-rCN/strings.xml +++ b/patches/src/main/resources/addresources/values-zh-rCN/strings.xml @@ -1470,6 +1470,11 @@ Second \"item\" text" 按钮已显示。点住即可将播放速度重置为默认值 按钮未显示 + + 显示视频质量按钮 + 按钮已显示。点按并按住以将画质重置为默认值 + 按钮未显示 + 自定义播放速度菜单 显示自定义速度菜单 diff --git a/patches/src/main/resources/addresources/values-zh-rTW/strings.xml b/patches/src/main/resources/addresources/values-zh-rTW/strings.xml index 2cf7c20a9f..d82cf6bf90 100644 --- a/patches/src/main/resources/addresources/values-zh-rTW/strings.xml +++ b/patches/src/main/resources/addresources/values-zh-rTW/strings.xml @@ -1475,10 +1475,15 @@ Second \"item\" text" 按鈕已顯示。長按可將播放速度重設為預設值 不顯示按鈕 + + 自訂播放速度選單 已顯示自訂播放速度選單 不顯示自訂播放速度選單 + 恢復舊版播放速度選單 + 已顯示舊版速度選單 + 已顯示新版速度選單 自訂播放速度 新增或變更自訂播放速度 自訂速度必須小於 %s diff --git a/patches/src/main/resources/addresources/values-zu-rZA/strings.xml b/patches/src/main/resources/addresources/values-zu-rZA/strings.xml index 7fe0f179cc..b64730dc01 100644 --- a/patches/src/main/resources/addresources/values-zu-rZA/strings.xml +++ b/patches/src/main/resources/addresources/values-zu-rZA/strings.xml @@ -222,6 +222,8 @@ Second \"item\" text" + + From cfffd422f8425155e2ce2a181989d97bb6448ed2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 3 Aug 2025 19:41:07 -0400 Subject: [PATCH 20/33] chore: Sync translations (#5586) --- .../src/main/resources/addresources/values-ro-rRO/strings.xml | 3 +-- .../src/main/resources/addresources/values-vi-rVN/strings.xml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml index 545a10b805..8d96015198 100644 --- a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml +++ b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml @@ -1465,8 +1465,7 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Butonul nu este afișat - Afi -tr + Afișați butonul de calitate video Butonul este afișat. Atingeți și mențineți apăsat pentru a reseta calitatea la valoarea implicită Butonul nu este afișat. diff --git a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml index 73eb6e00f3..4f20aa3a1b 100644 --- a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml +++ b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml @@ -987,8 +987,7 @@ Hoạt động tốt nhất với chất lượng video 720p trở xuống và k Thời gian hiển thị nút bỏ qua Thời gian hiển thị nút bỏ qua và nút bỏ qua đến phần nổi bật trước khi tự động ẩn Hiện thông báo ngắn hoàn tác bỏ qua - Thông báo ngắn sẽ hiện mỗi khi tự động bỏ qua một phân đoạn. -Chạm vào thông báo đó để hoàn tác bỏ qua + Thông báo ngắn sẽ hiện mỗi khi tự động bỏ qua một phân đoạn.\n\nChạm vào thông báo đó để hoàn tác bỏ qua Thông báo ngắn không hiện Thời gian thông báo ngắn tồn tại Thời gian thông báo ngắn tồn tại sau khi bỏ qua phân đoạn From 2e177a8839c95fbe2e3be4be66a215e967432c1e Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 3 Aug 2025 19:41:54 -0400 Subject: [PATCH 21/33] fix(NFC Tools): Remove broken patch that is no longer supported (#5584) --- .../app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt | 1 + .../revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt index f4f5d48c02..a185aca8ff 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt @@ -3,6 +3,7 @@ package app.revanced.patches.nfctoolsse.misc.pro import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint +@Deprecated("This patch no longer works and will soon be deleted.") internal val isLicenseRegisteredFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt b/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt index 55276126e8..ac3ac09af4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/UnlockProPatch.kt @@ -4,9 +4,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.bytecodePatch @Suppress("unused") -val unlockProPatch = bytecodePatch( - name = "Unlock pro", -) { +@Deprecated("This patch no longer works and will soon be deleted.") +val unlockProPatch = bytecodePatch{ compatibleWith("com.wakdev.apps.nfctools.se") execute { From 8c31374c5312698a5bdb639eb7314cfa7c4cef46 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Aug 2025 23:44:42 +0000 Subject: [PATCH 22/33] chore: Release v5.33.0-dev.8 [skip ci] # [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03) ### Bug Fixes * **NFC Tools:** Remove broken patch that is no longer supported ([#5584](https://github.com/ReVanced/revanced-patches/issues/5584)) ([2e177a8](https://github.com/ReVanced/revanced-patches/commit/2e177a8839c95fbe2e3be4be66a215e967432c1e)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42cfa0c028..5b556fafd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03) + + +### Bug Fixes + +* **NFC Tools:** Remove broken patch that is no longer supported ([#5584](https://github.com/ReVanced/revanced-patches/issues/5584)) ([cd3a6be](https://github.com/ReVanced/revanced-patches/commit/cd3a6be75c6bd3cc33c0b17a044bd6147f27b5ce)) + # [5.33.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.6...v5.33.0-dev.7) (2025-08-03) diff --git a/gradle.properties b/gradle.properties index 8fb806d0a7..53c21a083f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.7 +version = 5.33.0-dev.8 From 1dd01cf54a8287d999141f0470c32aae6bdf5cca Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 3 Aug 2025 21:23:27 -0400 Subject: [PATCH 23/33] fix(YouTube - Force original audio): Disable a/b feature flag that forces localized audio (#5582) --- .../patches/ForceOriginalAudioPatch.java | 11 ++- .../youtube/video/audio/Fingerprints.kt | 30 ++++--- .../video/audio/ForceOriginalAudioPatch.kt | 49 ++++++------ .../kotlin/app/revanced/util/BytecodeUtils.kt | 80 ++++++++++++++++++- 4 files changed, 128 insertions(+), 42 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ForceOriginalAudioPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ForceOriginalAudioPatch.java index 7a713d4f47..c67a5ffeca 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ForceOriginalAudioPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ForceOriginalAudioPatch.java @@ -24,6 +24,16 @@ public class ForceOriginalAudioPatch { } } + /** + * Injection point. + */ + public static boolean ignoreDefaultAudioStream(boolean original) { + if (Settings.FORCE_ORIGINAL_AUDIO.get()) { + return false; + } + return original; + } + /** * Injection point. */ @@ -50,7 +60,6 @@ public class ForceOriginalAudioPatch { return isOriginal; } catch (Exception ex) { Logger.printException(() -> "isDefaultAudioStream failure", ex); - return isDefault; } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt index a338ea6b7d..8e3755bc80 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt @@ -1,23 +1,27 @@ package app.revanced.patches.youtube.video.audio import app.revanced.patcher.fingerprint +import app.revanced.util.containsLiteralInstruction import com.android.tools.smali.dexlib2.AccessFlags -internal val streamingModelBuilderFingerprint = fingerprint { +internal val formatStreamModelToStringFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("L") - strings("vprng") + returns("Ljava/lang/String;") + custom { method, classDef -> + method.name == "toString" && classDef.type == + "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" + } } -internal val menuItemAudioTrackFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - parameters("L") - returns("V") - strings("menu_item_audio_track") +internal const val AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG = 45666189L + +internal val selectAudioStreamFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) + returns("L") + custom { method, _ -> + method.parameters.size > 2 // Method has a large number of parameters and may change. + && method.parameters[1].type == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;" + && method.containsLiteralInstruction(AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG) + } } -internal val audioStreamingTypeSelector = fingerprint { - accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) - returns("L") - strings("raw") // String is not unique -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt index c60c20db5e..40110878ce 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt @@ -5,22 +5,22 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable 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.misc.extension.sharedExtensionPatch +import app.revanced.patches.youtube.misc.playservice.is_20_07_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.getReference +import app.revanced.util.findMethodFromToString import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.insertLiteralOverride import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation -import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter @@ -37,6 +37,7 @@ val forceOriginalAudioPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, + versionCheckPatch ) compatibleWith( @@ -60,29 +61,25 @@ val forceOriginalAudioPatch = bytecodePatch( ) ) - fun Method.firstFormatStreamingModelCall( - returnType: String = "Ljava/lang/String;" - ): MutableMethod { - val audioTrackIdIndex = indexOfFirstInstructionOrThrow { - val reference = getReference() - reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" - && reference.returnType == returnType - } - - return navigate(this).to(audioTrackIdIndex).stop() + // Disable feature flag that ignores the default track flag + // and instead overrides to the user region language. + if (is_20_07_or_greater) { + selectAudioStreamFingerprint.method.insertLiteralOverride( + AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG, + "$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z" + ) } - // Accessor methods of FormatStreamModel have no string constants and - // opcodes are identical to other methods in the same class, - // so must walk from another class that use the methods. - val isDefaultMethod = streamingModelBuilderFingerprint.originalMethod.firstFormatStreamingModelCall("Z") - val audioTrackIdMethod = menuItemAudioTrackFingerprint.originalMethod.firstFormatStreamingModelCall() - val audioTrackDisplayNameMethod = audioStreamingTypeSelector.originalMethod.firstFormatStreamingModelCall() - val formatStreamModelClass = proxy(classes.first { - it.type == audioTrackIdMethod.definingClass - }).mutableClass + val isDefaultAudioTrackMethod = formatStreamModelToStringFingerprint.originalMethod + .findMethodFromToString("isDefaultAudioTrack=") + val audioTrackDisplayNameMethod = formatStreamModelToStringFingerprint.originalMethod + .findMethodFromToString("audioTrackDisplayName=") + val audioTrackIdMethod = formatStreamModelToStringFingerprint.originalMethod + .findMethodFromToString("audioTrackId=") - formatStreamModelClass.apply { + proxy(classes.first { + it.type == audioTrackIdMethod.definingClass + }).mutableClass.apply { // Add a new field to store the override. val helperFieldName = "isDefaultAudioTrackOverride" fields.add( @@ -103,7 +100,7 @@ val forceOriginalAudioPatch = bytecodePatch( // Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed. val helperMethodClass = type - val helperMethodName = "extension_isDefaultAudioTrack" + val helperMethodName = "patch_isDefaultAudioTrack" val helperMethod = ImmutableMethod( helperMethodClass, helperMethodName, @@ -143,7 +140,7 @@ val forceOriginalAudioPatch = bytecodePatch( methods.add(helperMethod) // Modify isDefaultAudioTrack() to call extension helper method. - isDefaultMethod.apply { + isDefaultAudioTrackMethod.apply { val index = indexOfFirstInstructionOrThrow(Opcode.RETURN) val register = getInstruction(index).registerA diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 60c7bdb0ef..6883776e6f 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -32,7 +32,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstructio import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.Reference +import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.util.MethodUtil import java.util.EnumSet @@ -171,6 +174,79 @@ internal val Instruction.isBranchInstruction: Boolean internal val Instruction.isReturnInstruction: Boolean get() = this.opcode in returnOpcodes +/** + * Find the instruction index used for a toString() StringBuilder write of a given String name. + * + * @param fieldName The name of the field to find. Partial matches are allowed. + */ +private fun Method.findInstructionIndexFromToString(fieldName: String) : Int { + val stringIndex = indexOfFirstInstruction { + val reference = getReference() + reference?.string?.contains(fieldName) == true + } + if (stringIndex < 0) { + throw IllegalArgumentException("Could not find usage of string: '$fieldName'") + } + val stringRegister = getInstruction(stringIndex).registerA + + // Find use of the string with a StringBuilder. + val stringUsageIndex = indexOfFirstInstruction(stringIndex) { + val reference = getReference() + reference?.definingClass == "Ljava/lang/StringBuilder;" && + (this as? FiveRegisterInstruction)?.registerD == stringRegister + } + if (stringUsageIndex < 0) { + throw IllegalArgumentException("Could not find StringBuilder usage in: $this") + } + + // Find the next usage of StringBuilder, which should be the desired field. + val fieldUsageIndex = indexOfFirstInstruction(stringUsageIndex + 1) { + val reference = getReference() + reference?.definingClass == "Ljava/lang/StringBuilder;" && reference.name == "append" + } + if (fieldUsageIndex < 0) { + // Should never happen. + throw IllegalArgumentException("Could not find StringBuilder append usage in: $this") + } + val fieldUsageRegister = getInstruction(fieldUsageIndex).registerD + + // Look backwards up the method to find the instruction that sets the register. + var fieldSetIndex = indexOfFirstInstructionReversedOrThrow(fieldUsageIndex - 1) { + fieldUsageRegister == writeRegister + } + + // If the field is a method call, then adjust from MOVE_RESULT to the method call. + val fieldSetOpcode = getInstruction(fieldSetIndex).opcode + if (fieldSetOpcode == MOVE_RESULT || + fieldSetOpcode == MOVE_RESULT_WIDE || + fieldSetOpcode == MOVE_RESULT_OBJECT) { + fieldSetIndex-- + } + + return fieldSetIndex +} + +/** + * Find the method used for a toString() StringBuilder write of a given String name. + * + * @param fieldName The name of the field to find. Partial matches are allowed. + */ +context(BytecodePatchContext) +internal fun Method.findMethodFromToString(fieldName: String) : MutableMethod { + val methodUsageIndex = findInstructionIndexFromToString(fieldName) + return navigate(this).to(methodUsageIndex).stop() +} + +/** + * Find the field used for a toString() StringBuilder write of a given String name. + * + * @param fieldName The name of the field to find. Partial matches are allowed. + */ +internal fun Method.findFieldFromToString(fieldName: String) : FieldReference { + val methodUsageIndex = findInstructionIndexFromToString(fieldName) + return getInstruction(methodUsageIndex).getReference()!! +} + /** * Adds public [AccessFlags] and removes private and protected flags (if present). */ @@ -594,7 +670,7 @@ fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfF /** * Get the index of matching instruction, - * starting from and [startIndex] and searching down. + * starting from [startIndex] and searching down. * * @param startIndex Optional starting index to search down from. Searching includes the start index. * @return The index of the instruction. @@ -617,7 +693,7 @@ fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int = i /** * Get the index of matching instruction, - * starting from and [startIndex] and searching down. + * starting from [startIndex] and searching down. * * @param startIndex Optional starting index to search down from. Searching includes the start index. * @return The index of the instruction. From 621292644c97744f20aa80a5f355ae2b1c838d2e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 4 Aug 2025 01:27:12 +0000 Subject: [PATCH 24/33] chore: Release v5.33.0-dev.9 [skip ci] # [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04) ### Bug Fixes * **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([1dd01cf](https://github.com/ReVanced/revanced-patches/commit/1dd01cf54a8287d999141f0470c32aae6bdf5cca)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b556fafd4..6681cfa7a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04) + + +### Bug Fixes + +* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([9fe13ee](https://github.com/ReVanced/revanced-patches/commit/9fe13ee1af104c009efd19b826adef375e48e191)) + # [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03) diff --git a/gradle.properties b/gradle.properties index 53c21a083f..c6bd173261 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.8 +version = 5.33.0-dev.9 From 178eed7fcd11ac2c03eefbb1c6e179a059df943e Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 4 Aug 2025 13:21:02 -0400 Subject: [PATCH 25/33] fix(YouTube - Video quality): Fix wrong qualities sometimes shown in player button dialog --- .../quality/RememberVideoQualityPatch.java | 29 +++++++------------ .../videoplayer/VideoQualityDialogButton.java | 20 +++++++++---- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java index dcbad858bc..1c6746b3bc 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java @@ -8,7 +8,6 @@ import androidx.annotation.Nullable; import com.google.android.libraries.youtube.innertube.model.media.VideoQuality; import java.util.Arrays; -import java.util.List; import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Utils; @@ -45,13 +44,11 @@ public class RememberVideoQualityPatch { private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI; private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE; - private static boolean qualityNeedsUpdating; - /** * The available qualities of the current video. */ @Nullable - private static List currentQualities; + private static VideoQuality[] currentQualities; /** * The current quality of the video playing. @@ -67,7 +64,7 @@ public class RememberVideoQualityPatch { private static VideoQualityMenuInterface currentMenuInterface; @Nullable - public static List getCurrentQualities() { + public static VideoQuality[] getCurrentQualities() { return currentQualities; } @@ -138,11 +135,11 @@ public class RememberVideoQualityPatch { Utils.verifyOnMainThread(); currentMenuInterface = menu; - final boolean availableQualitiesChanged = currentQualities == null - || currentQualities.size() != qualities.length; + final boolean availableQualitiesChanged = (currentQualities == null) + || !Arrays.equals(currentQualities, qualities); if (availableQualitiesChanged) { - currentQualities = Arrays.asList(qualities); - Logger.printDebug(() -> "VideoQualities: " + currentQualities); + currentQualities = qualities; + Logger.printDebug(() -> "VideoQualities: " + Arrays.toString(currentQualities)); } VideoQuality updatedCurrentQuality = qualities[originalQualityIndex]; @@ -155,17 +152,12 @@ public class RememberVideoQualityPatch { VideoQualityDialogButton.updateButtonIcon(updatedCurrentQuality); } - final int preferredQuality = getDefaultQualityResolution(); - if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) { - return originalQualityIndex; // Nothing to do. - } - // After changing videos the qualities can initially be for the prior video. // If the qualities have changed and the default is not auto then an update is needed. - if (!qualityNeedsUpdating && !availableQualitiesChanged) { - return originalQualityIndex; + final int preferredQuality = getDefaultQualityResolution(); + if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE || !availableQualitiesChanged) { + return originalQualityIndex; // Nothing to do. } - qualityNeedsUpdating = false; // Find the highest quality that is equal to or less than the preferred. int i = 0; @@ -213,7 +205,7 @@ public class RememberVideoQualityPatch { Logger.printDebug(() -> "Cannot save default quality, qualities is null"); return; } - VideoQuality quality = currentQualities.get(userSelectedQualityIndex); + VideoQuality quality = currentQualities[userSelectedQualityIndex]; saveDefaultQuality(quality.patch_getResolution()); } } catch (Exception ex) { @@ -243,7 +235,6 @@ public class RememberVideoQualityPatch { currentQualities = null; currentQuality = null; currentMenuInterface = null; - qualityNeedsUpdating = true; // Hide the quality button until playback starts and the qualities are available. VideoQualityDialogButton.updateButtonIcon(null); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java index 924f1ce7b1..e4f58b42a6 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java @@ -127,7 +127,7 @@ public class VideoQualityDialogButton { }, view -> { try { - List qualities = RememberVideoQualityPatch.getCurrentQualities(); + VideoQuality[] qualities = RememberVideoQualityPatch.getCurrentQualities(); VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface(); if (qualities == null || menu == null) { Logger.printDebug(() -> "Cannot reset quality, videoQualities is null"); @@ -186,13 +186,13 @@ public class VideoQualityDialogButton { */ private static void showVideoQualityDialog(Context context) { try { - List currentQualities = RememberVideoQualityPatch.getCurrentQualities(); + VideoQuality[] currentQualities = RememberVideoQualityPatch.getCurrentQualities(); VideoQuality currentQuality = RememberVideoQualityPatch.getCurrentQuality(); if (currentQualities == null || currentQuality == null) { Logger.printDebug(() -> "Cannot show qualities dialog, videoQualities is null"); return; } - if (currentQualities.size() < 2) { + if (currentQualities.length < 2) { // Should never happen. Logger.printException(() -> "Cannot show qualities dialog, no qualities available"); return; @@ -205,9 +205,17 @@ public class VideoQualityDialogButton { } // -1 adjustment for automatic quality at first index. - final int listViewSelectedIndex = currentQualities.indexOf(currentQuality) - 1; + int listViewSelectedIndex = 0; + for (VideoQuality quality : currentQualities) { + if (quality == currentQuality) { + // -1 adjustment for the missing automatic quality in the dialog list. + listViewSelectedIndex--; + break; + } + listViewSelectedIndex++; + } - List qualityLabels = new ArrayList<>(currentQualities.size() - 1); + List qualityLabels = new ArrayList<>(currentQualities.length - 1); for (VideoQuality availableQuality : currentQualities) { if (availableQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE) { qualityLabels.add(availableQuality.patch_getQualityName()); @@ -310,7 +318,7 @@ public class VideoQualityDialogButton { listView.setOnItemClickListener((parent, view, which, id) -> { try { final int originalIndex = which + 1; // Adjust for automatic. - VideoQuality selectedQuality = currentQualities.get(originalIndex); + VideoQuality selectedQuality = currentQualities[originalIndex]; Logger.printDebug(() -> "User clicked on quality: " + selectedQuality); if (RememberVideoQualityPatch.shouldRememberVideoQuality()) { From 1a8146dbc850ef9fdb216880bb078408c8338ef3 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 4 Aug 2025 17:23:50 +0000 Subject: [PATCH 26/33] chore: Release v5.33.0-dev.10 [skip ci] # [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04) ### Bug Fixes * **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([178eed7](https://github.com/ReVanced/revanced-patches/commit/178eed7fcd11ac2c03eefbb1c6e179a059df943e)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6681cfa7a9..3cb31acffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04) + + +### Bug Fixes + +* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([7378ae3](https://github.com/ReVanced/revanced-patches/commit/7378ae3c5fc88f91bf5cd6db47c6cd170a8c5a4f)) + # [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04) diff --git a/gradle.properties b/gradle.properties index c6bd173261..24aaaa9597 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.9 +version = 5.33.0-dev.10 From 9afa7d2ac642c3283bd51b7cda386ca947c8ed6d Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:00:14 -0400 Subject: [PATCH 27/33] fix(YouTube - Video quality): Fix 144p default not always used --- .../quality/RememberVideoQualityPatch.java | 18 ++++++++++++++---- .../videoplayer/VideoQualityDialogButton.java | 4 +--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java index 1c6746b3bc..5bd7f598d8 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java @@ -44,6 +44,8 @@ public class RememberVideoQualityPatch { private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI; private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE; + private static boolean qualityNeedsUpdating; + /** * The available qualities of the current video. */ @@ -152,18 +154,25 @@ public class RememberVideoQualityPatch { VideoQualityDialogButton.updateButtonIcon(updatedCurrentQuality); } - // After changing videos the qualities can initially be for the prior video. - // If the qualities have changed and the default is not auto then an update is needed. final int preferredQuality = getDefaultQualityResolution(); - if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE || !availableQualitiesChanged) { + if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) { return originalQualityIndex; // Nothing to do. } + // After changing videos the qualities can initially be for the prior video. + // If the qualities have changed and the default is not auto then an update is needed. + if (!qualityNeedsUpdating && !availableQualitiesChanged) { + return originalQualityIndex; + } + qualityNeedsUpdating = false; + // Find the highest quality that is equal to or less than the preferred. int i = 0; for (VideoQuality quality : qualities) { final int qualityResolution = quality.patch_getResolution(); - if (qualityResolution != AUTOMATIC_VIDEO_QUALITY_VALUE && qualityResolution <= preferredQuality) { + if ((qualityResolution != AUTOMATIC_VIDEO_QUALITY_VALUE && qualityResolution <= preferredQuality) + // Use the lowest video quality if the default is lower than all available. + || i == qualities.length - 1) { final boolean qualityNeedsChange = (i != originalQualityIndex); Logger.printDebug(() -> qualityNeedsChange ? "Changing video quality from: " + updatedCurrentQuality + " to: " + quality @@ -235,6 +244,7 @@ public class RememberVideoQualityPatch { currentQualities = null; currentQuality = null; currentMenuInterface = null; + qualityNeedsUpdating = true; // Hide the quality button until playback starts and the qualities are available. VideoQualityDialogButton.updateButtonIcon(null); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java index e4f58b42a6..c875f9bf79 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java @@ -205,11 +205,9 @@ public class VideoQualityDialogButton { } // -1 adjustment for automatic quality at first index. - int listViewSelectedIndex = 0; + int listViewSelectedIndex = -1; for (VideoQuality quality : currentQualities) { if (quality == currentQuality) { - // -1 adjustment for the missing automatic quality in the dialog list. - listViewSelectedIndex--; break; } listViewSelectedIndex++; From 4b2b5e3029a6ada691542427d871550079e25122 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 4 Aug 2025 19:03:03 +0000 Subject: [PATCH 28/33] chore: Release v5.33.0-dev.11 [skip ci] # [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04) ### Bug Fixes * **YouTube - Video quality:** Fix 144p default not always used ([9afa7d2](https://github.com/ReVanced/revanced-patches/commit/9afa7d2ac642c3283bd51b7cda386ca947c8ed6d)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cb31acffc..12c521c18b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04) + + +### Bug Fixes + +* **YouTube - Video quality:** Fix 144p default not always used ([2f7483a](https://github.com/ReVanced/revanced-patches/commit/2f7483a2d789c28a243b58bb7a252c0d590858ee)) + # [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04) diff --git a/gradle.properties b/gradle.properties index 24aaaa9597..cd9a4c8c58 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.10 +version = 5.33.0-dev.11 From 1bc63e50a7319c7619c81558b067bafeed06958c Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:17:00 -0400 Subject: [PATCH 29/33] fix(YouTube - Video quality): Fix dialog quality list check mark not always shown --- .../patches/playback/quality/RememberVideoQualityPatch.java | 5 ++--- .../youtube/videoplayer/VideoQualityDialogButton.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java index 5bd7f598d8..e4d1d98176 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch.java @@ -145,9 +145,8 @@ public class RememberVideoQualityPatch { } VideoQuality updatedCurrentQuality = qualities[originalQualityIndex]; - if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE && - (currentQuality == null - || !currentQuality.patch_getQualityName().equals(updatedCurrentQuality.patch_getQualityName()))) { + if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE + && (currentQuality == null || currentQuality != updatedCurrentQuality)) { currentQuality = updatedCurrentQuality; Logger.printDebug(() -> "Current quality changed to: " + updatedCurrentQuality); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java index c875f9bf79..e0a29db5f1 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/VideoQualityDialogButton.java @@ -207,7 +207,7 @@ public class VideoQualityDialogButton { // -1 adjustment for automatic quality at first index. int listViewSelectedIndex = -1; for (VideoQuality quality : currentQualities) { - if (quality == currentQuality) { + if (quality.patch_getQualityName().equals(currentQuality.patch_getQualityName())) { break; } listViewSelectedIndex++; From 36036b082dd2f928bf7fc39582dcb40bf74677b0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 4 Aug 2025 19:19:31 +0000 Subject: [PATCH 30/33] chore: Release v5.33.0-dev.12 [skip ci] # [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04) ### Bug Fixes * **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([1bc63e5](https://github.com/ReVanced/revanced-patches/commit/1bc63e50a7319c7619c81558b067bafeed06958c)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12c521c18b..45715ab19c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04) + + +### Bug Fixes + +* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([295f0f2](https://github.com/ReVanced/revanced-patches/commit/295f0f216b5e8aa9d68457862e73e312b7342703)) + # [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04) diff --git a/gradle.properties b/gradle.properties index cd9a4c8c58..a5aabc0961 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.11 +version = 5.33.0-dev.12 From a28891e5f3949e1ae18d4ad217941c96f46010bd Mon Sep 17 00:00:00 2001 From: Dawid Krajcarz <80264606+drobotk@users.noreply.github.com> Date: Tue, 5 Aug 2025 05:21:10 +0200 Subject: [PATCH 31/33] fix(Messenger - Hide Facebook button): Support the latest app version (#5590) --- .../app/revanced/patches/messenger/layout/Fingerprints.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt index b84a0c7e87..2abc12367c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt @@ -5,6 +5,5 @@ import app.revanced.patcher.fingerprint internal val isFacebookButtonEnabledFingerprint = fingerprint { parameters() returns("Z") - strings("com.facebook.messaging.inbox.tab.plugins.core.tabtoolbarbutton." + - "facebookbutton.facebooktoolbarbutton.FacebookButtonTabButtonImplementation") + strings("FacebookButtonTabButtonImplementation") } From 0cfc31c8f7e8ff3c9e556e7a0fd3b83aebee0844 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 5 Aug 2025 03:23:38 +0000 Subject: [PATCH 32/33] chore: Release v5.33.0-dev.13 [skip ci] # [5.33.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.12...v5.33.0-dev.13) (2025-08-05) ### Bug Fixes * **Messenger - Hide Facebook button:** Support the latest app version ([#5590](https://github.com/ReVanced/revanced-patches/issues/5590)) ([a28891e](https://github.com/ReVanced/revanced-patches/commit/a28891e5f3949e1ae18d4ad217941c96f46010bd)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45715ab19c..c561374090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [5.33.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.12...v5.33.0-dev.13) (2025-08-05) + + +### Bug Fixes + +* **Messenger - Hide Facebook button:** Support the latest app version ([#5590](https://github.com/ReVanced/revanced-patches/issues/5590)) ([0cab98d](https://github.com/ReVanced/revanced-patches/commit/0cab98df1689dbf7a042f18f4a961d47da1430ad)) + # [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04) diff --git a/gradle.properties b/gradle.properties index a5aabc0961..8c466034db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.33.0-dev.12 +version = 5.33.0-dev.13 From 63d64a5c8724515ddf10cdc3badb53fb4f0277e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 13:52:06 -0400 Subject: [PATCH 33/33] chore: Sync translations (#5595) --- .../main/resources/addresources/values-az-rAZ/strings.xml | 3 +++ .../main/resources/addresources/values-fi-rFI/strings.xml | 3 +++ .../main/resources/addresources/values-fr-rFR/strings.xml | 2 +- .../main/resources/addresources/values-hy-rAM/strings.xml | 2 +- .../main/resources/addresources/values-in-rID/strings.xml | 2 +- .../main/resources/addresources/values-it-rIT/strings.xml | 2 +- .../main/resources/addresources/values-ja-rJP/strings.xml | 4 ++-- .../main/resources/addresources/values-ne-rIN/strings.xml | 2 ++ .../main/resources/addresources/values-vi-rVN/strings.xml | 8 ++++---- 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml index 978b72faeb..c6e99b1199 100644 --- a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml +++ b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml @@ -1465,6 +1465,9 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər Düymə göstərilmir + Video keyfiyyəti düyməsini göstər + Düymə görünür. Keyfiyyəti ilkin vəziyyətinə qaytarmaq üçün toxunub saxlayın + Düymə görünmür Fərdi oynatma sürəti siyahısı diff --git a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml index 8cb1418cf6..fbd4cef6a8 100644 --- a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml +++ b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml @@ -1466,6 +1466,9 @@ Tämä voi avata korkealaatuisemmat videot" Painiketta ei näytetä + Näytä videolaatupainike + Painike näkyy. Paina pitkään palauttaaksesi laadun oletukseksi + Painiketta ei näytetä Mukautettu toistonopeusvalikko diff --git a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml index 9929abd00e..c8b02bf0f6 100644 --- a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml +++ b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml @@ -1468,7 +1468,7 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures" Afficher le bouton de qualité vidéo - Le bouton est affiché. Appuyez longuement pour réinitialiser la qualité par défaut + Le bouton est affiché. Appuyez longuement pour rétablir la qualité par défaut. Le bouton n\'est pas affiché diff --git a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml index 95b6ca296a..fa43eddd79 100644 --- a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml +++ b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml @@ -1468,7 +1468,7 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի Ցուցադրել տեսանյութի որակի կոճակը - Կոճակը ցուցադրված է։ Սեղմեք և պահեք՝ որակը լռելյայն վիճակի վերականգնելու համար + Կոճակը ցուցադրված է։ Հպեք և պահեք՝ որակը լռելյայնին վերականգնելու համար Կոճակը ցուցադրված չէ։ diff --git a/patches/src/main/resources/addresources/values-in-rID/strings.xml b/patches/src/main/resources/addresources/values-in-rID/strings.xml index b971cb89de..5f873731c4 100644 --- a/patches/src/main/resources/addresources/values-in-rID/strings.xml +++ b/patches/src/main/resources/addresources/values-in-rID/strings.xml @@ -1466,7 +1466,7 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Tampilkan tombol kualitas video - Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kualitas ke default + Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kualitas ke bawaan Tombol tidak ditampilkan diff --git a/patches/src/main/resources/addresources/values-it-rIT/strings.xml b/patches/src/main/resources/addresources/values-it-rIT/strings.xml index cc38025361..acea8edd9c 100644 --- a/patches/src/main/resources/addresources/values-it-rIT/strings.xml +++ b/patches/src/main/resources/addresources/values-it-rIT/strings.xml @@ -1466,7 +1466,7 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Mostra il pulsante qualità video - Il pulsante è visibile. Tocca e tieni premuto per ripristinare la qualità predefinita. + Il pulsante è visualizzato. Tocca e tieni premuto per ripristinare la qualità predefinita Il pulsante non è visibile. diff --git a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml index 8ec1cf7bd1..d6ba2831ae 100644 --- a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml +++ b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml @@ -1348,8 +1348,8 @@ Automotive レイアウト 詳細については、ここをタップしてください" API 利用不可時にトーストを表示 - DeArrow が利用できない場合は、トーストポップアップが表示されます - DeArrow が利用できない場合でも、トースト ポップアップは表示されません + DeArrow が利用できない場合にトースト通知が表示されます + DeArrow が利用できない場合にトースト通知は表示されません DeArrow API のエンドポイント DeArrow がサムネイルのキャッシュを取得するエンドポイントの URL 静止画サムネイル diff --git a/patches/src/main/resources/addresources/values-ne-rIN/strings.xml b/patches/src/main/resources/addresources/values-ne-rIN/strings.xml index b64730dc01..8289dca4e2 100644 --- a/patches/src/main/resources/addresources/values-ne-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ne-rIN/strings.xml @@ -21,6 +21,8 @@ Second \"item\" text" + ReVanced Manager द्वारा स्थापित छैन + APK निर्माण मिति खराब भएको छ diff --git a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml index 4f20aa3a1b..2b95d56a08 100644 --- a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml +++ b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml @@ -440,10 +440,10 @@ Tính năng này chỉ khả dụng trên các thiết bị cũ" Đã sao chép URL vào bảng nhớ tạm Đã sao chép URL kèm dấu thời gian Hiện nút sao chép URL video - Nút được hiển thị. Nhấn để sao chép URL video. Nhấn và giữ để sao chép kèm dấu thời gian + Nút đã được hiển thị. Nhấn để sao chép URL video. Nhấn và giữ để sao chép kèm dấu thời gian Nút không được hiển thị Hiện nút sao chép URL kèm dấu thời gian - Nút được hiển thị. Nhấn để sao chép URL video kèm dấu thời gian. Nhấn giữ để sao chép không kèm dấu thời gian + Nút đã được hiển thị. Nhấn để sao chép URL video kèm dấu thời gian. Nhấn giữ để sao chép không kèm dấu thời gian Nút không được hiển thị @@ -1468,12 +1468,12 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn" Hiện nút hộp thoại tốc độ phát - Nút được hiển thị. Nhấn và giữ để đặt lại tốc độ phát về mặc định + Nút đã được hiển thị. Nhấn và giữ để đặt lại tốc độ phát về mặc định Nút không được hiển thị Hiện nút chất lượng video - Nút đã được hiển thị. Chạm và giữ để đặt lại chất lượng về mặc định + Nút đã được hiển thị. Nhấn và giữ để đặt lại chất lượng về mặc định Nút không được hiển thị