dify/web/hooks/use-clipboard.ts
BrianWang1990 9308287fea
fix: copy button not working on API Server and API Key pages (#34515)
Co-authored-by: Brian Wang <BrianWang1990@users.noreply.github.com>
Co-authored-by: test <test@testdeMac-mini.local>
Co-authored-by: BrianWang1990 <512dabing99@163.com>
Co-authored-by: Stephen Zhou <hi@hyoban.cc>
Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
2026-04-09 02:49:40 +00:00

73 lines
2.2 KiB
TypeScript

import { useRef, useState } from 'react'
import { writeTextToClipboard } from '@/utils/clipboard'
import { noop } from './noop'
import { useStableHandler } from './use-stable-handler-only-when-you-know-what-you-are-doing-or-you-will-be-fired'
import { useCallback } from './use-typescript-happy-callback'
import 'client-only'
type UseClipboardOption = {
timeout?: number
usePromptAsFallback?: boolean
promptFallbackText?: string
onCopyError?: (error: Error) => void
}
/** @see https://foxact.skk.moe/use-clipboard */
export function useClipboard({
timeout = 1000,
usePromptAsFallback = false,
promptFallbackText = 'Failed to copy to clipboard automatically, please manually copy the text below.',
onCopyError,
}: UseClipboardOption = {}) {
const [error, setError] = useState<Error | null>(null)
const [copied, setCopied] = useState(false)
const copyTimeoutRef = useRef<number | null>(null)
const stablizedOnCopyError = useStableHandler<[e: Error], void>(onCopyError || noop)
const handleCopyResult = useCallback((isCopied: boolean) => {
if (copyTimeoutRef.current) {
clearTimeout(copyTimeoutRef.current)
}
if (isCopied) {
copyTimeoutRef.current = window.setTimeout(() => setCopied(false), timeout)
}
setCopied(isCopied)
}, [timeout])
const handleCopyError = useCallback((e: Error) => {
setError(e)
stablizedOnCopyError(e)
}, [stablizedOnCopyError])
const copy = useCallback(async (valueToCopy: string) => {
try {
await writeTextToClipboard(valueToCopy)
}
catch (e) {
if (usePromptAsFallback) {
try {
// eslint-disable-next-line no-alert -- prompt as fallback in case of copy error
window.prompt(promptFallbackText, valueToCopy)
}
catch (e2) {
handleCopyError(e2 as Error)
}
}
else {
handleCopyError(e as Error)
}
}
}, [handleCopyResult, promptFallbackText, handleCopyError, usePromptAsFallback])
const reset = useCallback(() => {
setCopied(false)
setError(null)
if (copyTimeoutRef.current) {
clearTimeout(copyTimeoutRef.current)
}
}, [])
return { copy, reset, error, copied }
}