feat(booth): copy-id button on the pickup banner (v0.1.3)

Adds a "⧉ copy" button next to the pickup id that copies the id to the
clipboard (flips to "✓ copied"). The Booth serves over plain HTTP on a LAN IP,
where navigator.clipboard is undefined (secure-context only) — so the handler
falls back to a hidden-textarea execCommand('copy') that works over HTTP.
Verified on the LAN-IP (non-secure) path: isSecureContext=false, clipboard API
absent, button state flips, no errors. Reusable via any .copy-btn[data-copy].
This commit is contained in:
2026-07-22 17:51:43 -07:00
parent 966324c5f1
commit d813f152ce
3 changed files with 43 additions and 2 deletions
+5
View File
@@ -111,6 +111,11 @@
.pickup-note{margin:-.5rem 0 1.5rem;padding:.6rem .85rem;border:1px solid var(--border-subtle);
border-left:3px solid var(--aus-bright-cyan);border-radius:var(--radius-md);background:var(--rk-well);
font-family:var(--font-mono);font-size:.78rem;color:var(--fg-2)}
.copy-btn{cursor:pointer;font-family:var(--font-mono);font-size:.68rem;letter-spacing:.04em;
padding:.12rem .5rem;margin:0 .25rem;border:1px solid var(--border-default);border-radius:var(--radius-sm);
background:transparent;color:var(--aus-bright-cyan);vertical-align:middle;transition:.12s var(--ease-out)}
.copy-btn:hover{border-color:var(--aus-cyan);background:rgba(66,220,209,.08)}
.copy-btn.copied{border-color:var(--aus-green);color:var(--aus-bright-green)}
.dl-link{color:var(--aus-bright-cyan);text-decoration:none;margin-right:.4rem;font-size:.95em}
.dl-link:hover{color:var(--aus-cyan)}
.cap-text{color:var(--fg-2)}
+37 -1
View File
@@ -13,7 +13,9 @@
{% if uploaded %}
<div class="pickup-note">
📦 Pickup <code>{{ name }}</code> — download files below, or on nh3-dev grab <code>~/booth-data/{{ name }}/</code>
📦 Pickup <code>{{ name }}</code>
<button type="button" class="copy-btn" data-copy="{{ name }}" title="copy id to clipboard">⧉ copy</button>
— download files below, or on nh3-dev grab <code>~/booth-data/{{ name }}/</code>
</div>
{% endif %}
@@ -44,4 +46,38 @@
{% endfor %}
</div>
{% endif %}
<script>
/* Copy-to-clipboard for any .copy-btn[data-copy]. The Booth serves over plain
HTTP on a LAN IP, where navigator.clipboard is undefined (secure-context
only) — so fall back to a hidden-textarea execCommand('copy'). */
(function () {
function copyText(t) {
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(t);
}
var ta = document.createElement('textarea');
ta.value = t;
ta.setAttribute('readonly', '');
ta.style.position = 'fixed';
ta.style.top = '-1000px';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); } catch (e) {}
document.body.removeChild(ta);
return Promise.resolve();
}
document.querySelectorAll('.copy-btn').forEach(function (btn) {
var label = btn.textContent;
btn.addEventListener('click', function () {
copyText(btn.getAttribute('data-copy')).then(function () {
btn.classList.add('copied');
btn.textContent = '✓ copied';
setTimeout(function () { btn.classList.remove('copied'); btn.textContent = label; }, 1300);
});
});
});
})();
</script>
{% endblock %}
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "booth"
version = "0.1.2"
version = "0.1.3"
description = "The Booth — a dead-simple standing web server that scans a data dir of drop-folders and renders each as an ephemeral media 'booth' (image/webm/audio auto-gallery, or a folder's own index.html verbatim). Also accepts browser/curl uploads for pickup under a human-readable id. 24h TTL, then the folder is wiped. Fleet tool for CC sessions to surface A/B and smoke results to the operator."
requires-python = ">=3.11"
dependencies = [