fix: copy clipboard fix

This commit is contained in:
gosangam
2026-06-11 11:47:31 +05:30
parent 884a984e50
commit af5ab9cf6b
+29 -2
View File
@@ -103,13 +103,39 @@ export function useCopyFeedback() {
const copy = useCallback(async (text: string) => {
let success = false;
const finalText = await shortenHighlightUrlsIn(text);
// Why we don't just `await shortenHighlightUrlsIn(text)` first: the URL
// shortening is a network round-trip, and awaiting it consumes the
// transient user activation that navigator.clipboard needs. The write
// would then silently fail on the *first* click and only succeed on the
// second (when the short link is cached and the shorten resolves
// synchronously). Instead we hand the clipboard a *Promise* of the text
// via ClipboardItem — the browser keeps the gesture alive while the
// async work finishes, so a single click copies the shortened URL.
if (typeof ClipboardItem !== "undefined" && navigator.clipboard?.write) {
try {
const item = new ClipboardItem({
"text/plain": shortenHighlightUrlsIn(text).then(
(s) => new Blob([s], { type: "text/plain" }),
),
});
await navigator.clipboard.write([item]);
success = true;
} catch {
// ClipboardItem-with-promise unsupported or rejected — fall through.
}
}
if (!success) {
// Legacy path: now that ClipboardItem failed, await the text and try
// the synchronous fallbacks. (May still need a second click on very old
// browsers, but those lack ClipboardItem entirely.)
const finalText = await shortenHighlightUrlsIn(text);
try {
await navigator.clipboard.writeText(finalText);
success = true;
} catch {
// Fallback for iOS Safari and older browsers
// Fallback for older browsers without the async clipboard API.
const ta = document.createElement("textarea");
ta.value = finalText;
ta.style.position = "fixed";
@@ -127,6 +153,7 @@ export function useCopyFeedback() {
}
document.body.removeChild(ta);
}
}
if (success) {
setCopied(true);