fix: copy clipboard fix

This commit is contained in:
gosangam
2026-06-11 11:47:31 +05:30
parent 884a984e50
commit af5ab9cf6b
+45 -18
View File
@@ -103,29 +103,56 @@ export function useCopyFeedback() {
const copy = useCallback(async (text: string) => {
let success = false;
const finalText = await shortenHighlightUrlsIn(text);
try {
await navigator.clipboard.writeText(finalText);
success = true;
} catch {
// Fallback for iOS Safari and older browsers
const ta = document.createElement("textarea");
ta.value = finalText;
ta.style.position = "fixed";
ta.style.top = "0";
ta.style.left = "0";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.focus();
ta.select();
// 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 {
document.execCommand("copy");
const item = new ClipboardItem({
"text/plain": shortenHighlightUrlsIn(text).then(
(s) => new Blob([s], { type: "text/plain" }),
),
});
await navigator.clipboard.write([item]);
success = true;
} catch {
// silent fail
// 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 older browsers without the async clipboard API.
const ta = document.createElement("textarea");
ta.value = finalText;
ta.style.position = "fixed";
ta.style.top = "0";
ta.style.left = "0";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.focus();
ta.select();
try {
document.execCommand("copy");
success = true;
} catch {
// silent fail
}
document.body.removeChild(ta);
}
document.body.removeChild(ta);
}
if (success) {