diff --git a/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/downloadbuttonhook/fingerprints/DownloadActionsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/downloadbuttonhook/fingerprints/DownloadActionsFingerprint.kt
new file mode 100644
index 000000000..22a9ed45c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/downloadbuttonhook/fingerprints/DownloadActionsFingerprint.kt
@@ -0,0 +1,14 @@
+package app.revanced.patches.youtube.overlaybutton.downloadbuttonhook.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+
+object DownloadActionsFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ parameters = listOf("L", "L", "Z"),
+ opcodes = listOf(Opcode.INVOKE_STATIC),
+ strings = listOf("offline/get_download_action")
+)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/downloadbuttonhook/patch/DownloadButtonHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/downloadbuttonhook/patch/DownloadButtonHookPatch.kt
new file mode 100644
index 000000000..a1ba362cc
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/downloadbuttonhook/patch/DownloadButtonHookPatch.kt
@@ -0,0 +1,44 @@
+package app.revanced.patches.youtube.overlaybutton.downloadbuttonhook.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+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.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.util.smali.ExternalLabel
+import app.revanced.patches.youtube.overlaybutton.downloadbuttonhook.fingerprints.DownloadActionsFingerprint
+import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility
+import app.revanced.util.integrations.Constants.UTILS_PATH
+
+@Name("download-button-hook")
+@Description("Replace download button with external download button.")
+@YouTubeCompatibility
+@Version("0.0.1")
+class DownloadButtonHookPatch : BytecodePatch(
+ listOf(DownloadActionsFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ DownloadActionsFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val targetIndex = it.scanResult.patternScanResult!!.startIndex
+
+ addInstructionsWithLabels(
+ targetIndex, """
+ invoke-static {}, $UTILS_PATH/HookDownloadButtonPatch;->shouldHookDownloadButton()Z
+ move-result v0
+ if-eqz v0, :default
+ invoke-static {}, $UTILS_PATH/HookDownloadButtonPatch;->startDownloadActivity()V
+ return-void
+ """, ExternalLabel("default", getInstruction(targetIndex))
+ )
+ }
+ } ?: return DownloadActionsFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/patch/OverlayButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/patch/OverlayButtonsPatch.kt
index e3133e8d6..a35c3d8a8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/patch/OverlayButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/patch/OverlayButtonsPatch.kt
@@ -11,6 +11,7 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.overlaybutton.alwaysrepeat.patch.AlwaysRepeatPatch
+import app.revanced.patches.youtube.overlaybutton.downloadbuttonhook.patch.DownloadButtonHookPatch
import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility
import app.revanced.patches.youtube.utils.overridespeed.patch.OverrideSpeedHookPatch
import app.revanced.patches.youtube.utils.playerbutton.patch.PlayerButtonHookPatch
@@ -30,6 +31,7 @@ import org.w3c.dom.Element
@DependsOn(
[
AlwaysRepeatPatch::class,
+ DownloadButtonHookPatch::class,
OverrideSpeedHookPatch::class,
PlayerButtonHookPatch::class,
PlayerControlsPatch::class,
diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml
index b0dbcbc5d..37e38b4a0 100644
--- a/src/main/resources/youtube/settings/host/values/strings.xml
+++ b/src/main/resources/youtube/settings/host/values/strings.xml
@@ -389,6 +389,9 @@
Player overlay filter is shown
Player overlay filter is hidden
Hide player overlay filter
+ "Replace download button with external download button
+Only available on YouTube v18.24.37+"
+ Hook download button
Preview comment is shown
Preview comment is hidden
Hide preview comment
diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml
index 42aa1eacf..4d9f671f2 100644
--- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml
+++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml
@@ -424,9 +424,9 @@
-
+
-
+