From ec85abc1c7f92c9b00dcbf72b5588e353ac11903 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:50:56 +0900 Subject: [PATCH] feat: apply code review suggestions --- .../general/downloads/DownloadActionsPatch.kt | 136 ++++++++++++++ ...cessibilityOfflineButtonSyncFingerprint.kt | 6 +- ...ownloadPlaylistButtonOnClickFingerprint.kt | 32 ++++ .../OfflineVideoEndpointFingerprint.kt | 2 +- ...listDownloadButtonVisibilityFingerprint.kt | 7 +- .../HookDownloadActionsPatch.kt | 174 ------------------ ...ownloadPlaylistButtonOnClickFingerprint.kt | 29 --- .../OverlayButtonsBytecodePatch.kt | 21 +-- .../overlaybuttons/OverlayButtonsPatch.kt | 2 + .../youtube/utils/pip/PiPStateHookPatch.kt | 40 ++++ .../fingerprints/PiPPlaybackFingerprint.kt | 2 +- .../youtube/settings/host/values/arrays.xml | 18 +- .../youtube/settings/host/values/strings.xml | 38 ++-- .../youtube/settings/xml/revanced_prefs.xml | 13 +- 14 files changed, 265 insertions(+), 255 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt rename src/main/kotlin/app/revanced/patches/youtube/{misc/downloadactions => general/downloads}/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt (72%) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt rename src/main/kotlin/app/revanced/patches/youtube/{misc/downloadactions => general/downloads}/fingerprints/OfflineVideoEndpointFingerprint.kt (87%) rename src/main/kotlin/app/revanced/patches/youtube/{misc/downloadactions => general/downloads}/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt (54%) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/HookDownloadActionsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/pip/PiPStateHookPatch.kt rename src/main/kotlin/app/revanced/patches/youtube/{misc/downloadactions => utils/pip}/fingerprints/PiPPlaybackFingerprint.kt (86%) diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt new file mode 100644 index 000000000..f6849bea2 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt @@ -0,0 +1,136 @@ +package app.revanced.patches.youtube.general.downloads + +import app.revanced.patcher.data.BytecodeContext +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.getInstructions +import app.revanced.patcher.patch.PatchException +import app.revanced.patcher.util.smali.ExternalLabel +import app.revanced.patches.youtube.general.downloads.fingerprints.AccessibilityOfflineButtonSyncFingerprint +import app.revanced.patches.youtube.general.downloads.fingerprints.DownloadPlaylistButtonOnClickFingerprint +import app.revanced.patches.youtube.general.downloads.fingerprints.DownloadPlaylistButtonOnClickFingerprint.indexOfPlaylistDownloadActionInvokeInstruction +import app.revanced.patches.youtube.general.downloads.fingerprints.OfflineVideoEndpointFingerprint +import app.revanced.patches.youtube.general.downloads.fingerprints.SetPlaylistDownloadButtonVisibilityFingerprint +import app.revanced.patches.youtube.utils.compatibility.Constants +import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH +import app.revanced.patches.youtube.utils.pip.PiPStateHookPatch +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +@Suppress("unused") +object DownloadActionsPatch : BaseBytecodePatch( + name = "Hook download actions", + description = "Adds support to download videos with an external downloader app using the in-app download button.", + dependencies = setOf( + PiPStateHookPatch::class, + SharedResourceIdPatch::class, + SettingsPatch::class + ), + compatiblePackages = Constants.COMPATIBLE_PACKAGE, + fingerprints = setOf( + AccessibilityOfflineButtonSyncFingerprint, + DownloadPlaylistButtonOnClickFingerprint, + OfflineVideoEndpointFingerprint, + ) +) { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = + "$GENERAL_PATH/DownloadActionsPatch;" + + override fun execute(context: BytecodeContext) { + + // region patch for hook download actions (video action bar and flyout panel) + + OfflineVideoEndpointFingerprint.resultOrThrow().mutableMethod.apply { + addInstructionsWithLabels( + 0, """ + invoke-static/range {p3 .. p3}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppVideoDownloadButtonOnClick(Ljava/lang/String;)Z + move-result v0 + if-eqz v0, :show_native_downloader + return-void + """, ExternalLabel("show_native_downloader", getInstruction(0)) + ) + } + + // endregion + + // region patch for hook download actions (playlist) + + val onClickListenerClass = + DownloadPlaylistButtonOnClickFingerprint.resultOrThrow().mutableMethod.let { + val playlistDownloadActionInvokeIndex = + indexOfPlaylistDownloadActionInvokeInstruction(it) + + it.getInstructions().subList( + playlistDownloadActionInvokeIndex - 10, + playlistDownloadActionInvokeIndex, + ).find { instruction -> + instruction.opcode == Opcode.INVOKE_VIRTUAL_RANGE + && instruction.getReference()?.parameterTypes?.first() == "Ljava/lang/String;" + }?.getReference()?.returnType + ?: throw PatchException("Could not find onClickListenerClass") + } + + context.findClass(onClickListenerClass) + ?.mutableClass + ?.methods + ?.first { method -> method.name == "onClick" }?.apply { + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC + && getReference()?.name == "isEmpty" + } + val insertRegister = getInstruction(insertIndex).registerC + + addInstructions( + insertIndex, """ + invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$insertRegister + """ + ) + } ?: throw PatchException("Could not find class $onClickListenerClass") + + // endregion + + // region patch for show the playlist download button + + SetPlaylistDownloadButtonVisibilityFingerprint + .alsoResolve(context, AccessibilityOfflineButtonSyncFingerprint).let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2 + val insertRegister = + getInstruction(insertIndex).registerA + + addInstructions( + insertIndex, """ + invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->overridePlaylistDownloadButtonVisibility()Z + move-result v$insertRegister + """ + ) + } + } + + // endregion + + /** + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE_SCREEN: GENERAL", + "PREFERENCE_CATEGORY: GENERAL_EXPERIMENTAL_FLAGS", + "SETTINGS: HOOK_DOWNLOAD_ACTIONS" + ) + ) + + SettingsPatch.updatePatchStatus(this) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt similarity index 72% rename from src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt index cc7e9433f..1137e867c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/AccessibilityOfflineButtonSyncFingerprint.kt @@ -1,12 +1,12 @@ -package app.revanced.patches.youtube.misc.downloadactions.fingerprints +package app.revanced.patches.youtube.general.downloads.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccessibilityOfflineButtonSync import app.revanced.util.fingerprint.LiteralValueFingerprint import com.android.tools.smali.dexlib2.AccessFlags -object AccessibilityOfflineButtonSyncFingerprint : LiteralValueFingerprint( +internal object AccessibilityOfflineButtonSyncFingerprint : LiteralValueFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "V", literalSupplier = { AccessibilityOfflineButtonSync } -) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt new file mode 100644 index 000000000..9420767de --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt @@ -0,0 +1,32 @@ +package app.revanced.patches.youtube.general.downloads.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.general.downloads.fingerprints.DownloadPlaylistButtonOnClickFingerprint.indexOfPlaylistDownloadActionInvokeInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object DownloadPlaylistButtonOnClickFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", + opcodes = listOf(Opcode.INVOKE_VIRTUAL_RANGE), + customFingerprint = { methodDef, _ -> + indexOfPlaylistDownloadActionInvokeInstruction(methodDef) >= 0 + } +) { + fun indexOfPlaylistDownloadActionInvokeInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.parameterTypes == + listOf( + "Ljava/lang/String;", + "Lcom/google/android/apps/youtube/app/offline/ui/OfflineArrowView;", + "I", + "Landroid/view/View${'$'}OnClickListener;" + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/OfflineVideoEndpointFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/OfflineVideoEndpointFingerprint.kt similarity index 87% rename from src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/OfflineVideoEndpointFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/OfflineVideoEndpointFingerprint.kt index 280db49a1..287cdae89 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/OfflineVideoEndpointFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/OfflineVideoEndpointFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.misc.downloadactions.fingerprints +package app.revanced.patches.youtube.general.downloads.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt similarity index 54% rename from src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt index 3b5c41eda..b6f12142d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/fingerprints/SetPlaylistDownloadButtonVisibilityFingerprint.kt @@ -1,9 +1,12 @@ -package app.revanced.patches.youtube.misc.downloadactions.fingerprints +package app.revanced.patches.youtube.general.downloads.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode -object SetPlaylistDownloadButtonVisibilityFingerprint : MethodFingerprint( +/** + * Resolves using class found in [AccessibilityOfflineButtonSyncFingerprint]. + */ +internal object SetPlaylistDownloadButtonVisibilityFingerprint : MethodFingerprint( returnType = "V", opcodes = listOf( Opcode.INVOKE_VIRTUAL, diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/HookDownloadActionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/HookDownloadActionsPatch.kt deleted file mode 100644 index 1ccc4ba52..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/HookDownloadActionsPatch.kt +++ /dev/null @@ -1,174 +0,0 @@ -package app.revanced.patches.youtube.misc.downloadactions - -import app.revanced.patcher.data.BytecodeContext -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.util.smali.ExternalLabel -import app.revanced.patches.youtube.misc.downloadactions.fingerprints.* -import app.revanced.patches.youtube.utils.compatibility.Constants -import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH -import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH -import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch -import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.patch.BaseBytecodePatch -import app.revanced.util.resultOrThrow -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -@Suppress("unused") -object HookDownloadActionsPatch : BaseBytecodePatch( - name = "Hook download actions", - description = "Adds options to show the download playlist button and hook the download actions.", - dependencies = setOf( - MainActivityResolvePatch::class, - SharedResourceIdPatch::class, - SettingsPatch::class - ), - compatiblePackages = Constants.COMPATIBLE_PACKAGE, - fingerprints = setOf( - OfflineVideoEndpointFingerprint, - PiPPlaybackFingerprint, - AccessibilityOfflineButtonSyncFingerprint, - DownloadPlaylistButtonOnClickFingerprint - ) -) { - private const val INTEGRATIONS_DOWNLOAD_PLAYLIST_BUTTON_CLASS_DESCRIPTOR = - "$MISC_PATH/HookDownloadAction;" - - private const val INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR = - "$INTEGRATIONS_PATH/utils/VideoUtils;" - - override fun execute(context: BytecodeContext) { - - // region Patch for hook download actions - - OfflineVideoEndpointFingerprint.resultOrThrow().mutableMethod.apply { - addInstructionsWithLabels( - 0, """ - invoke-static/range {p3 .. p3}, $INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick(Ljava/lang/String;)Z - move-result v0 - if-eqz v0, :show_native_downloader - return-void - """, ExternalLabel("show_native_downloader", getInstruction(0)) - ) - } - - PiPPlaybackFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val insertIndex = it.scanResult.patternScanResult!!.endIndex - val insertRegister = getInstruction(insertIndex).registerA - - addInstructions( - insertIndex, """ - invoke-static {v$insertRegister}, $INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR->getExternalDownloaderLaunchedState(Z)Z - move-result v$insertRegister - """ - ) - } - } - - // endregion - - // region Force show the playlist download button - - AccessibilityOfflineButtonSyncFingerprint.resultOrThrow().let { parentResult -> - SetPlaylistDownloadButtonVisibilityFingerprint.also { - it.resolve( - context, - parentResult.classDef - ) - }.resultOrThrow().let { setVisibilityMethod -> - setVisibilityMethod.mutableMethod.apply { - // Find the index of if-nez - val insertIndex = setVisibilityMethod.scanResult.patternScanResult!!.startIndex + 2 - // Get register values used in if-nez - val insertRegister = getInstruction(insertIndex).registerA - - // Add instructions just above the index of if-nez - addInstructions( - insertIndex, - """ - invoke-static {}, $INTEGRATIONS_DOWNLOAD_PLAYLIST_BUTTON_CLASS_DESCRIPTOR->isPlaylistDownloadButtonHooked()Z - move-result v$insertRegister - """ - ) - } - } - } - - // endregion - - // region Hook Download Playlist Button OnClick method - - DownloadPlaylistButtonOnClickFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - - // region Get the index of the instruction that initializes the onClickListener - - val onClickListenerInitializeIndex = indexOfFirstInstructionOrThrow { - val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) - - opcode == Opcode.INVOKE_VIRTUAL_RANGE - && reference?.parameterTypes?.first() == "Ljava/lang/String;" - } - - // endregion - - // region Get the class that contains the onClick method - - val onClickListenerInitializeReference = - getInstruction(onClickListenerInitializeIndex).reference - - - val onClickClass = context.findClass( - (onClickListenerInitializeReference as MethodReference).returnType - )!!.mutableClass - - // endregion - - onClickClass.methods.find { method -> method.name == "onClick" }?.apply { - - // region Get the index of playlist id - - val insertIndex = implementation!!.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.INVOKE_STATIC - && instruction.getReference()?.name == "isEmpty" - } - - val insertRegister = getInstruction(insertIndex).registerC - - // endregion - - addInstructions( - insertIndex, - """ - invoke-static {v$insertRegister}, $INTEGRATIONS_DOWNLOAD_PLAYLIST_BUTTON_CLASS_DESCRIPTOR->startPlaylistDownloadActivity(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$insertRegister - """.trimIndent() - ) - } - } - } - - // endregion - - /** - * Add settings - */ - SettingsPatch.addPreference( - arrayOf( - "PREFERENCE_SCREEN: GENERAL", - "SETTINGS: HOOK_DOWNLOAD_ACTIONS" - ) - ) - - SettingsPatch.updatePatchStatus(this) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt deleted file mode 100644 index 91135c871..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/DownloadPlaylistButtonOnClickFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.youtube.misc.downloadactions.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patches.youtube.misc.downloadactions.fingerprints.DownloadPlaylistButtonOnClickFingerprint.PLAYLIST_ON_CLICK_INITIALIZE_PAREMETER -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - - -object DownloadPlaylistButtonOnClickFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - returnType = "V", - customFingerprint = { methodDef, _ -> - methodDef.indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.parameterTypes == PLAYLIST_ON_CLICK_INITIALIZE_PAREMETER - } >= 0 - } -) { - val PLAYLIST_ON_CLICK_INITIALIZE_PAREMETER = listOf( - "Ljava/lang/String;", - "Lcom/google/android/apps/youtube/app/offline/ui/OfflineArrowView;", - "I", - "Landroid/view/View${'$'}OnClickListener;" - ) -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsBytecodePatch.kt index 4c4d634ab..3c12dc4b4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsBytecodePatch.kt @@ -5,31 +5,24 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.player.overlaybuttons.fingerprints.PlayerButtonConstructorFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH -import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch -import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch -import app.revanced.util.* +import app.revanced.util.addFieldAndInstructions +import app.revanced.util.getReference +import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.iface.reference.MethodReference -@Patch( - dependencies = [ - MainActivityResolvePatch::class, - SharedResourceIdPatch::class, - VideoInformationPatch::class - ] -) object OverlayButtonsBytecodePatch : BytecodePatch( - setOf( - PlayerButtonConstructorFingerprint - ) + setOf(PlayerButtonConstructorFingerprint) ) { private const val INTEGRATIONS_ALWAYS_REPEAT_CLASS_DESCRIPTOR = "$UTILS_PATH/AlwaysRepeatPatch;" diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt index cb394a640..9ed6a2c77 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt @@ -6,6 +6,7 @@ import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatc import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.fix.bottomui.CfBottomUIPatch import app.revanced.patches.youtube.utils.integrations.Constants.OVERLAY_BUTTONS_PATH +import app.revanced.patches.youtube.utils.pip.PiPStateHookPatch import app.revanced.patches.youtube.utils.playercontrols.PlayerControlsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch @@ -29,6 +30,7 @@ object OverlayButtonsPatch : BaseResourcePatch( description = "Adds options to display overlay buttons in the video player.", dependencies = setOf( CfBottomUIPatch::class, + PiPStateHookPatch::class, PlayerControlsPatch::class, SettingsPatch::class, OverlayButtonsBytecodePatch::class, diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/pip/PiPStateHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/pip/PiPStateHookPatch.kt new file mode 100644 index 000000000..4d423c1fa --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/pip/PiPStateHookPatch.kt @@ -0,0 +1,40 @@ +package app.revanced.patches.youtube.utils.pip + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH +import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch +import app.revanced.patches.youtube.utils.pip.fingerprints.PiPPlaybackFingerprint +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + description = "Hooks YouTube to prevent it from switching to PiP when an external downloader is launched.", + dependencies = [MainActivityResolvePatch::class] +) +object PiPStateHookPatch : BytecodePatch( + setOf(PiPPlaybackFingerprint) +) { + private const val INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR = + "$INTEGRATIONS_PATH/utils/VideoUtils;" + + override fun execute(context: BytecodeContext) { + + PiPPlaybackFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.endIndex + val insertRegister = getInstruction(insertIndex).registerA + + addInstructions( + insertIndex, """ + invoke-static {v$insertRegister}, $INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR->getExternalDownloaderLaunchedState(Z)Z + move-result v$insertRegister + """ + ) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/PiPPlaybackFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/pip/fingerprints/PiPPlaybackFingerprint.kt similarity index 86% rename from src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/PiPPlaybackFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/utils/pip/fingerprints/PiPPlaybackFingerprint.kt index ae1bad0fb..6062c13ca 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/downloadactions/fingerprints/PiPPlaybackFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/pip/fingerprints/PiPPlaybackFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.misc.downloadactions.fingerprints +package app.revanced.patches.youtube.utils.pip.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode diff --git a/src/main/resources/youtube/settings/host/values/arrays.xml b/src/main/resources/youtube/settings/host/values/arrays.xml index e5a03b23a..db3c07a20 100644 --- a/src/main/resources/youtube/settings/host/values/arrays.xml +++ b/src/main/resources/youtube/settings/host/values/arrays.xml @@ -94,22 +94,28 @@ 1440 2160 - + NewPipe Seal Tubular YTDLnis - + org.schabi.newpipe com.junkfood.seal org.polymorphicshade.tubular com.deniscerri.ytdl - - https://github.com/TeamNewPipe/NewPipe/releases/latest - https://github.com/JunkFood02/Seal/releases/latest - https://github.com/polymorphicshade/Tubular/releases/latest + + https://github.com/deniscerri/ytdlnis/releases/latest + + + YTDLnis + + + com.deniscerri.ytdl + + https://github.com/deniscerri/ytdlnis/releases/latest diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml index f4804a209..8c743862f 100644 --- a/src/main/resources/youtube/settings/host/values/strings.xml +++ b/src/main/resources/youtube/settings/host/values/strings.xml @@ -4,17 +4,24 @@ Enable accessibility controls for the video player? Your controls are modified because an accessibility service is on. - + ReVanced Extended Search %s - Experimental Flags Do you wish to proceed? Restart to load the layout normally Refresh and restart Normal + Video downloader package name + Package name of your installed external downloader app, such as NewPipe or YTDLnis. + External downloader + Warning + "%1$s is not installed. +Please download %2$s from the website." + %s is not installed. Please install it. + Ads @@ -334,6 +341,16 @@ This does not bypass the age restriction. It just accepts it automatically."Spoofs the dpi to use some phone layouts. Enable tablet layout Spoofs the dpi to use some tablet layouts. + + Override video download button + Native video download button opens your external downloader. + Native video download button opens the native in-app downloader. + Override playlist download button + Native playlist download button opens your external downloader. + Native playlist download button opens the native in-app downloader. + Playlist downloader package name + Package name of your installed external downloader app, such as YTDLnis. + Spoof app version Version spoofed Version not spoofed @@ -505,9 +522,6 @@ You tab → View channel → Menu → Settings" Tap and hold to open YouTube settings." "Tap to open YouTube settings. Tap and hold to open RVX settings." - Override playlist download action - Playlist download will behave like the original, and button might not appear. - Playlist download button will be present, and the download will be handled by YTDLnis. @@ -900,20 +914,6 @@ Tap and hold to undo." SponsorBlock Failed to load channel information. - External downloader package name - Package name of your installed external downloader app, such as NewPipe or YTDLnis. - External downloader - Playlist external downloader package name - Package name of your installed external downloader app used to download from playlists, currently only YTDLnis works. - Playlist external downloader - Warning - "%1$s is not installed. -Please download %2$s from the website." - %s is not installed. Please install it. - Override download action button - Native download button opens your external downloader. - Native download button opens the native in-app downloader. - Playback speed reset: %sx. Tap and hold to change button state. Timestamp copied to clipboard. (%s) diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index f0ed5ed08..ebdc38960 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -231,9 +231,10 @@ SETTINGS: LAYOUT_SWITCH --> + + + + SETTINGS: HOOK_DOWNLOAD_ACTIONS --> + + SETTINGS: OVERLAY_BUTTONS --> @@ -695,6 +695,7 @@ +