diff --git a/webview-ui/src/utils/clipboard.ts b/webview-ui/src/utils/clipboard.ts index 37dc147fbd..8ef139d357 100644 --- a/webview-ui/src/utils/clipboard.ts +++ b/webview-ui/src/utils/clipboard.ts @@ -1,4 +1,4 @@ -import { useState, useCallback } from "react" +import { useState, useCallback, useEffect, useRef } from "react" /** * Options for copying text to clipboard @@ -33,15 +33,24 @@ export const copyToClipboard = async (text: string, options?: CopyOptions): Prom */ export const useCopyToClipboard = (feedbackDuration = 2000) => { const [showCopyFeedback, setShowCopyFeedback] = useState(false) + const timeoutRef = useRef(null) const copyWithFeedback = useCallback( async (text: string, e?: React.MouseEvent) => { e?.stopPropagation() + // Clear any existing timeout + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + } + const success = await copyToClipboard(text, { onSuccess: () => { setShowCopyFeedback(true) - setTimeout(() => setShowCopyFeedback(false), feedbackDuration) + timeoutRef.current = setTimeout(() => { + setShowCopyFeedback(false) + timeoutRef.current = null + }, feedbackDuration) }, }) @@ -50,6 +59,15 @@ export const useCopyToClipboard = (feedbackDuration = 2000) => { [feedbackDuration], ) + // Cleanup timeout on unmount + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + } + } + }, []) + return { showCopyFeedback, copyWithFeedback,