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 }} = {{}}) {{
|
async function copyUrl({{ automatic = false }} = {{}}) {{
|
||||||
if (!currentUrl) return 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.
|
// Async Clipboard only works in secure contexts in most browsers.
|
||||||
if (navigator.clipboard && window.isSecureContext) {{
|
if (navigator.clipboard && window.isSecureContext) {{
|
||||||
try {{
|
try {{
|
||||||
@@ -293,27 +300,38 @@ INDEX_HTML = f"""<!doctype html>
|
|||||||
setStatus('链接已复制到剪贴板');
|
setStatus('链接已复制到剪贴板');
|
||||||
return true;
|
return true;
|
||||||
}} catch (err) {{
|
}} 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();
|
selectUrl();
|
||||||
setStatus(
|
setStatus(
|
||||||
automatic
|
automatic
|
||||||
? '浏览器拦截了自动复制,链接已选中,请按 Ctrl+C / ⌘+C 复制'
|
? '浏览器限制了自动复制,链接已选中,请按 Ctrl+C / ⌘+C 复制'
|
||||||
: '浏览器拦截了复制,链接已选中,请按 Ctrl+C / ⌘+C 复制',
|
: '浏览器限制了复制,链接已选中,请按 Ctrl+C / ⌘+C 复制',
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
return false;
|
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;
|
const value = text.value;
|
||||||
if (!value.trim()) {{
|
if (!value.trim()) {{
|
||||||
setStatus('请输入文本', true);
|
setStatus('请输入文本', true);
|
||||||
@@ -324,13 +342,7 @@ INDEX_HTML = f"""<!doctype html>
|
|||||||
resultEl.style.display = 'none';
|
resultEl.style.display = 'none';
|
||||||
setStatus('正在提交...');
|
setStatus('正在提交...');
|
||||||
try {{
|
try {{
|
||||||
const response = await fetch('/api/paste', {{
|
const data = requestPasteSynchronously(value);
|
||||||
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');
|
|
||||||
currentUrl = data.url;
|
currentUrl = data.url;
|
||||||
providerEl.textContent = data.provider || '';
|
providerEl.textContent = data.provider || '';
|
||||||
urlEl.textContent = currentUrl;
|
urlEl.textContent = currentUrl;
|
||||||
@@ -339,7 +351,7 @@ INDEX_HTML = f"""<!doctype html>
|
|||||||
resultEl.style.display = 'block';
|
resultEl.style.display = 'block';
|
||||||
copy.style.display = 'inline-block';
|
copy.style.display = 'inline-block';
|
||||||
setStatus('提交成功,正在复制链接...');
|
setStatus('提交成功,正在复制链接...');
|
||||||
await copyUrl({{ automatic: true }});
|
void copyUrl({{ automatic: true }});
|
||||||
}} catch (err) {{
|
}} catch (err) {{
|
||||||
setStatus(err instanceof Error ? err.message : '提交失败', true);
|
setStatus(err instanceof Error ? err.message : '提交失败', true);
|
||||||
}} finally {{
|
}} finally {{
|
||||||
@@ -347,7 +359,7 @@ INDEX_HTML = f"""<!doctype html>
|
|||||||
}}
|
}}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
copy.addEventListener('click', copyUrl);
|
copy.addEventListener('click', () => {{ void copyUrl(); }});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user