/** * public/share.ts — "share this session" (v0.4 multi-device mirror). * * A 🔗 toolbar button shows a QR + URL of the form `/?join=` * for the ACTIVE tab. Opening that link on another device on the same network * joins the same live terminal (mirror: both see output, either can type). * Reuses the .qr-* card styles. */ import QRCode from 'qrcode' import { ICON_SHARE } from './icons.js' export function mountShareSession(toolbar: HTMLElement, getActiveId: () => string | null): void { const modal = document.createElement('div') modal.id = 'sharemodal' modal.className = 'qrmodal' modal.style.display = 'none' const card = document.createElement('div') card.className = 'qr-card' const title = document.createElement('div') title.className = 'qr-title' title.textContent = 'Share this session' const canvas = document.createElement('canvas') const urlEl = document.createElement('div') urlEl.className = 'qr-url' const note = document.createElement('div') note.className = 'qr-note' const close = document.createElement('button') close.className = 'qr-close' close.textContent = 'Close' card.append(title, canvas, urlEl, note, close) modal.appendChild(card) document.body.appendChild(modal) const hide = (): void => { modal.style.display = 'none' } modal.addEventListener('click', (e) => { if (e.target === modal) hide() }) close.addEventListener('click', hide) const open = (): void => { const id = getActiveId() if (!id) { // The active tab hasn't attached yet — no id to share. urlEl.textContent = '' note.textContent = 'This tab is still connecting — try again in a second.' const ctx = canvas.getContext('2d') if (ctx) ctx.clearRect(0, 0, canvas.width, canvas.height) modal.style.display = 'flex' return } const url = `${location.origin}/?join=${id}` urlEl.textContent = url void QRCode.toCanvas(canvas, url, { width: 220, margin: 1 }) const host = location.hostname note.textContent = host === 'localhost' || host === '127.0.0.1' ? 'Tip: open this page via your LAN IP (not localhost) so the code works on other devices.' : 'Scan on a device on the same network to mirror this session.' modal.style.display = 'flex' } const toggle = document.createElement('button') toggle.className = 'toolbtn' toggle.innerHTML = ICON_SHARE toggle.dataset.tip = 'Share session' toggle.setAttribute('aria-label', 'Share session') toggle.setAttribute('aria-label', 'Share this session') toggle.addEventListener('click', open) toolbar.appendChild(toggle) }