Preserve click gesture for copy fallback

Use a synchronous paste request so the HTTP-compatible copy fallback can run inside the original button click when browser clipboard APIs are unavailable.
This commit is contained in:
2026-05-13 01:45:34 +08:00
parent 168fc91e93
commit 41508762ad
+31 -19
View File
@@ -286,6 +286,13 @@ INDEX_HTML = f"""<!doctype html>
async function copyUrl({{ automatic = false }} = {{}}) {{
if (!currentUrl) return false;
// execCommand works in many HTTP/IP scenarios, but it usually must run
// directly inside a click event. Try it first.
if (legacyCopy()) {{
setStatus('链接已复制到剪贴板');
return true;
}}
// Async Clipboard only works in secure contexts in most browsers.
if (navigator.clipboard && window.isSecureContext) {{
try {{
@@ -293,27 +300,38 @@ INDEX_HTML = f"""<!doctype html>
setStatus('链接已复制到剪贴板');
return true;
}} catch (err) {{
// Fall through to execCommand.
// Keep the selected input visible for manual copy below.
}}
}}
// execCommand works in many HTTP/IP scenarios when called from a click.
if (legacyCopy()) {{
setStatus('链接已复制到剪贴板');
return true;
}}
selectUrl();
setStatus(
automatic
? '浏览器拦截了自动复制,链接已选中,请按 Ctrl+C / ⌘+C 复制'
: '浏览器拦截了复制,链接已选中,请按 Ctrl+C / ⌘+C 复制',
? '浏览器限制了自动复制,链接已选中,请按 Ctrl+C / ⌘+C 复制'
: '浏览器限制了复制,链接已选中,请按 Ctrl+C / ⌘+C 复制',
true,
);
return false;
}}
submit.addEventListener('click', async () => {{
function requestPasteSynchronously(value) {{
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/paste', false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({{ text: value }}));
let data = {{}};
try {{
data = JSON.parse(xhr.responseText || '{{}}');
}} catch (err) {{
data = {{ error: 'invalid response' }};
}}
if (xhr.status < 200 || xhr.status >= 300) {{
throw new Error(data.error || 'request failed');
}}
return data;
}}
submit.addEventListener('click', () => {{
const value = text.value;
if (!value.trim()) {{
setStatus('请输入文本', true);
@@ -324,13 +342,7 @@ INDEX_HTML = f"""<!doctype html>
resultEl.style.display = 'none';
setStatus('正在提交...');
try {{
const response = await fetch('/api/paste', {{
method: 'POST',
headers: {{ 'Content-Type': 'application/json' }},
body: JSON.stringify({{ text: value }}),
}});
const data = await response.json().catch(() => ({{ error: 'invalid response' }}));
if (!response.ok) throw new Error(data.error || 'request failed');
const data = requestPasteSynchronously(value);
currentUrl = data.url;
providerEl.textContent = data.provider || '';
urlEl.textContent = currentUrl;
@@ -339,7 +351,7 @@ INDEX_HTML = f"""<!doctype html>
resultEl.style.display = 'block';
copy.style.display = 'inline-block';
setStatus('提交成功,正在复制链接...');
await copyUrl({{ automatic: true }});
void copyUrl({{ automatic: true }});
}} catch (err) {{
setStatus(err instanceof Error ? err.message : '提交失败', true);
}} finally {{
@@ -347,7 +359,7 @@ INDEX_HTML = f"""<!doctype html>
}}
}});
copy.addEventListener('click', copyUrl);
copy.addEventListener('click', () => {{ void copyUrl(); }});
</script>
</body>
</html>