fix(web): make bot-link copy work over plain HTTP

navigator.clipboard requires a secure context (HTTPS or localhost). For
users hosting the bot on a remote IP and accessing via http://<ip>:3000,
clipboard.writeText is undefined and the copy silently fails. Add a
hidden-textarea + execCommand('copy') fallback, with a final prompt()
fallback so the user can always grab the URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
saopig1andClaude Opus 4.6 committed 2026-04-17 00:26:05 +08:00
1 parent 4406eeacbe
commit b9e42d543c
1 file changed
+25 -3
+25 -3
View File
@@ -77,11 +77,33 @@ function selectBot(id: string) {
dropdownOpen.value = false; dropdownOpen.value = false;
} }
function copyBotLink(id: string) { async function copyBotLink(id: string) {
const url = `${window.location.origin}/bot/${id}`; const url = `${window.location.origin}/bot/${id}`;
navigator.clipboard.writeText(url).then(() => { // navigator.clipboard requires a secure context (HTTPS or localhost).
// Fall back to a hidden textarea + execCommand('copy') for plain HTTP
// access (e.g. when the bot is hosted on a remote IP).
try {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(url);
} else {
const ta = document.createElement('textarea');
ta.value = url;
ta.style.position = 'fixed';
ta.style.opacity = '0';
ta.style.pointerEvents = 'none';
document.body.appendChild(ta);
ta.focus();
ta.select();
const ok = document.execCommand('copy');
document.body.removeChild(ta);
if (!ok) throw new Error('execCommand copy returned false');
}
dropdownOpen.value = false; dropdownOpen.value = false;
}); } catch (err) {
// Last-resort: prompt the user with the URL so they can copy manually
console.error('Failed to copy bot link', err);
window.prompt('复制以下链接:', url);
}
} }
async function togglePower(bot: { id: string; connected: boolean; name: string }) { async function togglePower(bot: { id: string; connected: boolean; name: string }) {