Explorar el Código

fix: resolve clipboard.writeText failure under HTTP protocol (#12936)

le0zh hace 3 meses
padre
commit
71fa14f791
Se han modificado 2 ficheros con 37 adiciones y 1 borrados
  1. 2 1
      web/app/components/develop/code.tsx
  2. 35 0
      web/utils/clipboard.ts

+ 2 - 1
web/app/components/develop/code.tsx

@@ -10,6 +10,7 @@ import {
 import { Tab } from '@headlessui/react'
 import { Tag } from './tag'
 import classNames from '@/utils/classnames'
+import { writeTextToClipboard } from '@/utils/clipboard'
 
 const languageNames = {
   js: 'JavaScript',
@@ -71,7 +72,7 @@ function CopyButton({ code }: { code: string }) {
           : 'bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5',
       )}
       onClick={() => {
-        window.navigator.clipboard.writeText(code).then(() => {
+        writeTextToClipboard(code).then(() => {
           setCopyCount(count => count + 1)
         })
       }}

+ 35 - 0
web/utils/clipboard.ts

@@ -0,0 +1,35 @@
+export async function writeTextToClipboard(text: string): Promise<void> {
+  if (navigator.clipboard && navigator.clipboard.writeText)
+    return navigator.clipboard.writeText(text)
+
+  return fallbackCopyTextToClipboard(text)
+}
+
+async function fallbackCopyTextToClipboard(text: string): Promise<void> {
+  const textArea = document.createElement('textarea')
+  textArea.value = text
+  textArea.style.position = 'fixed' // Avoid scrolling to bottom
+  document.body.appendChild(textArea)
+  textArea.focus()
+  textArea.select()
+  try {
+    const successful = document.execCommand('copy')
+    if (successful)
+      return Promise.resolve()
+
+    return Promise.reject(new Error('document.execCommand failed'))
+  }
+  catch (err) {
+    return Promise.reject(convertAnyToError(err))
+  }
+  finally {
+    document.body.removeChild(textArea)
+  }
+}
+
+function convertAnyToError(err: any): Error {
+  if (err instanceof Error)
+    return err
+
+  return new Error(`Caught: ${String(err)}`)
+}