Improve clipboard copy fallback

Avoid stale page scripts and select the returned URL when browser clipboard APIs are blocked on plain HTTP access.
This commit is contained in:
2026-05-13 01:40:52 +08:00
parent 73a6614118
commit 168fc91e93
+48 -6
View File
@@ -166,6 +166,8 @@ class PublicPasteHandler(BaseHTTPRequestHandler):
self.send_response(HTTPStatus.OK)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.send_header("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
self.send_header("Pragma", "no-cache")
self.end_headers()
self.wfile.write(body)
@@ -174,6 +176,7 @@ class PublicPasteHandler(BaseHTTPRequestHandler):
self.send_response(status)
self.send_header("Content-Type", "application/json; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.send_header("Cache-Control", "no-store")
self.end_headers()
self.wfile.write(body)
@@ -228,8 +231,9 @@ INDEX_HTML = f"""<!doctype html>
.row {{ display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 14px; }}
.status {{ min-height: 24px; color: #59636e; }}
.result {{ display: none; margin-top: 18px; padding: 14px; border: 1px solid #d8dee6; border-radius: 12px; background: #f9fafb; word-break: break-all; }}
.urlbox {{ box-sizing: border-box; width: 100%; margin-top: 8px; border: 1px solid #ccd3da; border-radius: 10px; padding: 10px 12px; font: 15px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }}
.error {{ color: #b42318; }}
@media (prefers-color-scheme: dark) {{ body {{ background: #111827; color: #f9fafb; }} main {{ background: #1f2937; }} p,.status {{ color: #cbd5e1; }} textarea,.result {{ background: #111827; color: #f9fafb; border-color: #374151; }} }}
@media (prefers-color-scheme: dark) {{ body {{ background: #111827; color: #f9fafb; }} main {{ background: #1f2937; }} p,.status {{ color: #cbd5e1; }} textarea,.result,.urlbox {{ background: #111827; color: #f9fafb; border-color: #374151; }} }}
</style>
</head>
<body>
@@ -239,12 +243,13 @@ INDEX_HTML = f"""<!doctype html>
<textarea id="text" maxlength="{MAX_REQUEST_BYTES}" placeholder="在这里输入文本..."></textarea>
<div class="row">
<button id="submit" type="button">完成</button>
<button id="copy" type="button" style="display:none">再次复制链接</button>
<button id="copy" type="button" style="display:none">再次复制/选中链接</button>
<span id="status" class="status"></span>
</div>
<section id="result" class="result" aria-live="polite">
<div>Provider: <strong id="provider"></strong></div>
<div>URL: <a id="url" href="#" target="_blank" rel="noopener noreferrer"></a></div>
<input id="urlInput" class="urlbox" readonly value="" aria-label="Paste URL">
</section>
</main>
<script>
@@ -255,6 +260,7 @@ INDEX_HTML = f"""<!doctype html>
const resultEl = document.getElementById('result');
const providerEl = document.getElementById('provider');
const urlEl = document.getElementById('url');
const urlInput = document.getElementById('urlInput');
let currentUrl = '';
function setStatus(message, isError = false) {{
@@ -262,16 +268,51 @@ INDEX_HTML = f"""<!doctype html>
statusEl.className = isError ? 'status error' : 'status';
}}
async function copyUrl() {{
if (!currentUrl) return;
function selectUrl() {{
urlInput.focus();
urlInput.select();
urlInput.setSelectionRange(0, urlInput.value.length);
}}
function legacyCopy() {{
selectUrl();
try {{
return document.execCommand('copy');
}} catch (err) {{
return false;
}}
}}
async function copyUrl({{ automatic = false }} = {{}}) {{
if (!currentUrl) return false;
// Async Clipboard only works in secure contexts in most browsers.
if (navigator.clipboard && window.isSecureContext) {{
try {{
await navigator.clipboard.writeText(currentUrl);
setStatus('链接已复制到剪贴板');
return true;
}} catch (err) {{
setStatus('复制失败,请手动复制链接', true);
// Fall through to execCommand.
}}
}}
// 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 复制',
true,
);
return false;
}}
submit.addEventListener('click', async () => {{
const value = text.value;
if (!value.trim()) {{
@@ -294,10 +335,11 @@ INDEX_HTML = f"""<!doctype html>
providerEl.textContent = data.provider || '';
urlEl.textContent = currentUrl;
urlEl.href = currentUrl;
urlInput.value = currentUrl;
resultEl.style.display = 'block';
copy.style.display = 'inline-block';
setStatus('提交成功,正在复制链接...');
await copyUrl();
await copyUrl({{ automatic: true }});
}} catch (err) {{
setStatus(err instanceof Error ? err.message : '提交失败', true);
}} finally {{