diff --git a/app.js b/app.js index 64b61d3..2e8ba22 100644 --- a/app.js +++ b/app.js @@ -12,6 +12,27 @@ document.body.classList.add('debug-mode'); } + document.querySelectorAll('.raw-data').forEach(el => { + el.style.cursor = 'pointer'; + el.title = 'Klicken zum Kopieren'; + el.addEventListener('click', async () => { + try { + await navigator.clipboard.writeText(el.textContent); + const orig = el.textContent; + el.textContent = 'Kopiert!'; + setTimeout(() => { el.textContent = orig; }, 1200); + } catch (e) { + const sel = window.getSelection(); + const range = document.createRange(); + range.selectNodeContents(el); + sel.removeAllRanges(); + sel.addRange(range); + document.execCommand('copy'); + sel.removeAllRanges(); + } + }); + }); + /* ─── Screen routing ─── */ function show(name) { ['start','host','join','game','result'].forEach(s => @@ -43,7 +64,8 @@ const c = $(containerId); if (!c) return; c.innerHTML = ''; - qrHost = new QRCode(c, { text: data, width: 200, height: 200, correctLevel: QRCode.CorrectLevel.L }); + const size = Math.min(window.innerWidth - 64, 360); + qrHost = new QRCode(c, { text: data, width: size, height: size, correctLevel: QRCode.CorrectLevel.L }); } /* ─── Camera ─── */ @@ -52,14 +74,22 @@ async function camStart(videoId) { await camStop(); - camStream = await navigator.mediaDevices.getUserMedia({ - video: { facingMode: 'environment', width: { ideal: 320 }, height: { ideal: 240 } } - }); + try { + camStream = await navigator.mediaDevices.getUserMedia({ + video: { facingMode: { ideal: 'environment' }, width: { ideal: 1920 }, height: { ideal: 1080 } } + }); + } catch (_) { + camStream = await navigator.mediaDevices.getUserMedia({ video: true }); + } const v = $(videoId); v.srcObject = camStream; v.setAttribute('playsinline', ''); v.classList.add('active'); await v.play(); + try { + const track = camStream.getVideoTracks()[0]; + if (track) track.applyConstraints({ advanced: [{ focusMode: 'continuous' }] }); + } catch (_) {} return v; } @@ -71,13 +101,16 @@ function camScan(videoId, canvasId, callback) { const v = $(videoId); const c = $(canvasId); - const ctx = c.getContext('2d'); - camRaf = requestAnimationFrame(function tick() { + const ctx = c.getContext('2d', { willReadFrequently: true }); + let lastScan = 0; + camRaf = requestAnimationFrame(function tick(now) { if (!v.videoWidth) { camRaf = requestAnimationFrame(tick); return; } + if (now - lastScan < 100) { camRaf = requestAnimationFrame(tick); return; } + lastScan = now; c.width = v.videoWidth; c.height = v.videoHeight; ctx.drawImage(v, 0, 0); const img = ctx.getImageData(0, 0, c.width, c.height); - const code = jsQR(img.data, img.width, img.height); + const code = jsQR(img.data, img.width, img.height, { inversionAttempts: 'dontInvert' }); if (code && code.data) { try { const p = JSON.parse(code.data); @@ -244,6 +277,8 @@ mesh.onanswerready = answerData => { $('join-answer-section').hidden = false; showQR('qr-answer', answerData); + const raw = $('answer-raw'); + if (raw) raw.textContent = answerData; $('join-scan-status').textContent = 'Antwort-QR dem Host zeigen'; camStop(); }; diff --git a/index.html b/index.html index d2c294a..ffe4285 100644 --- a/index.html +++ b/index.html @@ -69,6 +69,10 @@
Antwort-QR für den Host:
Zeige diesen QR-Code dem Host
+