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) => { const copy = useCallback(async (text: string) => {
let success = false; let success = false;
const finalText = await shortenHighlightUrlsIn(text);
try { // Why we don't just `await shortenHighlightUrlsIn(text)` first: the URL
await navigator.clipboard.writeText(finalText); // shortening is a network round-trip, and awaiting it consumes the
success = true; // transient user activation that navigator.clipboard needs. The write
} catch { // would then silently fail on the *first* click and only succeed on the
// Fallback for iOS Safari and older browsers // second (when the short link is cached and the shorten resolves
const ta = document.createElement("textarea"); // synchronously). Instead we hand the clipboard a *Promise* of the text
ta.value = finalText; // via ClipboardItem — the browser keeps the gesture alive while the
ta.style.position = "fixed"; // async work finishes, so a single click copies the shortened URL.
ta.style.top = "0"; if (typeof ClipboardItem !== "undefined" && navigator.clipboard?.write) {
ta.style.left = "0";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.focus();
ta.select();
try { 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; success = true;
} catch { } 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) { if (success) {