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:
+31
-19
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user