diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt index a2ccd3e942..e7297fde61 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt @@ -2,14 +2,18 @@ package app.revanced.patches.youtube.video.videoqualitymenu import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch import app.revanced.patches.youtube.misc.recyclerviewtree.hook.RecyclerViewTreeHookPatch +import app.revanced.patches.youtube.video.videoqualitymenu.fingerprints.VideoQualityMenuOptionsFingerprint import app.revanced.patches.youtube.video.videoqualitymenu.fingerprints.VideoQualityMenuViewInflateFingerprint +import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( @@ -50,7 +54,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction ) @Suppress("unused") object RestoreOldVideoQualityMenuPatch : BytecodePatch( - setOf(VideoQualityMenuViewInflateFingerprint) + setOf(VideoQualityMenuViewInflateFingerprint, VideoQualityMenuOptionsFingerprint) ) { private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/VideoQualityMenuFilterPatch;" @@ -60,7 +64,8 @@ object RestoreOldVideoQualityMenuPatch : BytecodePatch( override fun execute(context: BytecodeContext) { // region Patch for the old type of the video quality menu. - // Only used when spoofing to old app version. + // Used for regular videos when spoofing to old app version, + // and for the Shorts quality flyout on newer app versions. VideoQualityMenuViewInflateFingerprint.result?.let { it.mutableMethod.apply { @@ -76,6 +81,29 @@ object RestoreOldVideoQualityMenuPatch : BytecodePatch( } } + // Force YT to add the 'advanced' quality menu for Shorts. + VideoQualityMenuOptionsFingerprint.resultOrThrow().let { + val result = it.scanResult.patternScanResult!! + val startIndex = result.startIndex + val endIndex = result.endIndex + + it.mutableMethod.apply { + val freeRegister = getInstruction(startIndex).registerA + + // A condition controls whether to show the three or four items quality menu. + // Force the four items quality menu to make the "Advanced" item visible, necessary for the patch. + addInstructionsWithLabels( + startIndex + 1, + """ + invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->forceAdvancedVideoQualityMenuCreation()Z + move-result v$freeRegister + if-nez v$freeRegister, :includeAdvancedMenu + """, + ExternalLabel("includeAdvancedMenu", getInstruction(endIndex)) + ) + } + } + // endregion // region Patch for the new type of the video quality menu. diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuResourcePatch.kt index 8de2a9b0e5..41e1b8ad22 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuResourcePatch.kt @@ -13,6 +13,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch ) object RestoreOldVideoQualityMenuResourcePatch : ResourcePatch() { internal var videoQualityBottomSheetListFragmentTitle = -1L + internal var videoQualityQuickMenuAdvancedMenuDescription = -1L override fun execute(context: ResourceContext) { AddResourcesPatch(this::class) @@ -26,5 +27,10 @@ object RestoreOldVideoQualityMenuResourcePatch : ResourcePatch() { "layout", "video_quality_bottom_sheet_list_fragment_title", ] + + videoQualityQuickMenuAdvancedMenuDescription = ResourceMappingPatch[ + "string", + "video_quality_quick_menu_advanced_menu_description" + ] } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuOptionsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuOptionsFingerprint.kt new file mode 100644 index 0000000000..0d1a2cc6dc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/fingerprints/VideoQualityMenuOptionsFingerprint.kt @@ -0,0 +1,22 @@ +package app.revanced.patches.youtube.video.videoqualitymenu.fingerprints + +import app.revanced.patches.youtube.video.videoqualitymenu.RestoreOldVideoQualityMenuResourcePatch +import app.revanced.util.patch.LiteralValueFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object VideoQualityMenuOptionsFingerprint : LiteralValueFingerprint( + accessFlags = AccessFlags.STATIC.value, + parameters = listOf("Landroid/content/Context", "L", "L"), + returnType = "[L", + opcodes = listOf( + Opcode.IF_EQZ, // Check if advanced menu should be shown. + Opcode.NEW_ARRAY, + Opcode.APUT_OBJECT, + Opcode.APUT_OBJECT, + Opcode.APUT_OBJECT, + Opcode.RETURN_OBJECT, + Opcode.CONST_4 // Advanced menu code path. + ), + literalSupplier = { RestoreOldVideoQualityMenuResourcePatch.videoQualityQuickMenuAdvancedMenuDescription } +) \ No newline at end of file