Compare commits

..

No commits in common. "87d2d0f19020468e338294cf6704e0061a90c27b" and "cef5d35be71a046df4774fe4a1144419137e3acd" have entirely different histories.

6 changed files with 10 additions and 10159 deletions

49
app.js
View file

@ -12,27 +12,6 @@
document.body.classList.add('debug-mode'); 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 ─── */ /* ─── Screen routing ─── */
function show(name) { function show(name) {
['start','host','join','game','result'].forEach(s => ['start','host','join','game','result'].forEach(s =>
@ -64,8 +43,7 @@
const c = $(containerId); const c = $(containerId);
if (!c) return; if (!c) return;
c.innerHTML = ''; c.innerHTML = '';
const size = Math.min(window.innerWidth - 64, 360); qrHost = new QRCode(c, { text: data, width: 200, height: 200, correctLevel: QRCode.CorrectLevel.L });
qrHost = new QRCode(c, { text: data, width: size, height: size, correctLevel: QRCode.CorrectLevel.L });
} }
/* ─── Camera ─── */ /* ─── Camera ─── */
@ -74,22 +52,14 @@
async function camStart(videoId) { async function camStart(videoId) {
await camStop(); await camStop();
try { camStream = await navigator.mediaDevices.getUserMedia({
camStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment', width: { ideal: 320 }, height: { ideal: 240 } }
video: { facingMode: { ideal: 'environment' }, width: { ideal: 1920 }, height: { ideal: 1080 } } });
});
} catch (_) {
camStream = await navigator.mediaDevices.getUserMedia({ video: true });
}
const v = $(videoId); const v = $(videoId);
v.srcObject = camStream; v.srcObject = camStream;
v.setAttribute('playsinline', ''); v.setAttribute('playsinline', '');
v.classList.add('active'); v.classList.add('active');
await v.play(); await v.play();
try {
const track = camStream.getVideoTracks()[0];
if (track) track.applyConstraints({ advanced: [{ focusMode: 'continuous' }] });
} catch (_) {}
return v; return v;
} }
@ -101,16 +71,13 @@
function camScan(videoId, canvasId, callback) { function camScan(videoId, canvasId, callback) {
const v = $(videoId); const v = $(videoId);
const c = $(canvasId); const c = $(canvasId);
const ctx = c.getContext('2d', { willReadFrequently: true }); const ctx = c.getContext('2d');
let lastScan = 0; camRaf = requestAnimationFrame(function tick() {
camRaf = requestAnimationFrame(function tick(now) {
if (!v.videoWidth) { camRaf = requestAnimationFrame(tick); return; } 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; c.width = v.videoWidth; c.height = v.videoHeight;
ctx.drawImage(v, 0, 0); ctx.drawImage(v, 0, 0);
const img = ctx.getImageData(0, 0, c.width, c.height); const img = ctx.getImageData(0, 0, c.width, c.height);
const code = jsQR(img.data, img.width, img.height, { inversionAttempts: 'dontInvert' }); const code = jsQR(img.data, img.width, img.height);
if (code && code.data) { if (code && code.data) {
try { try {
const p = JSON.parse(code.data); const p = JSON.parse(code.data);
@ -277,8 +244,6 @@
mesh.onanswerready = answerData => { mesh.onanswerready = answerData => {
$('join-answer-section').hidden = false; $('join-answer-section').hidden = false;
showQR('qr-answer', answerData); showQR('qr-answer', answerData);
const raw = $('answer-raw');
if (raw) raw.textContent = answerData;
$('join-scan-status').textContent = 'Antwort-QR dem Host zeigen'; $('join-scan-status').textContent = 'Antwort-QR dem Host zeigen';
camStop(); camStop();
}; };

View file

@ -69,10 +69,6 @@
<p>Antwort-QR für den Host:</p> <p>Antwort-QR für den Host:</p>
<div id="qr-answer"></div> <div id="qr-answer"></div>
<p class="hint">Zeige diesen QR-Code dem Host</p> <p class="hint">Zeige diesen QR-Code dem Host</p>
<details class="debug-helper debug-only" style="margin-top:8px">
<summary>QR-Rohdaten</summary>
<pre id="answer-raw" class="raw-data"></pre>
</details>
</div> </div>
<ul id="join-player-list" class="player-list"></ul> <ul id="join-player-list" class="player-list"></ul>
</div> </div>
@ -125,9 +121,9 @@
</div> </div>
</section> </section>
<script src="vendor/simplepeer.min.js"></script> <script src="https://unpkg.com/simple-peer@9.11.1/simplepeer.min.js"></script>
<script src="vendor/qrcode.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script src="vendor/jsQR.js"></script> <script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.js"></script>
<script src="crypto.js"></script> <script src="crypto.js"></script>
<script src="p2p.js"></script> <script src="p2p.js"></script>
<script src="protocol.js"></script> <script src="protocol.js"></script>

1
p2p.js
View file

@ -233,7 +233,6 @@ class MeshNet {
if (this._pendingPeer && this._pendingPeer.peer === peer) { if (this._pendingPeer && this._pendingPeer.peer === peer) {
this._pendingPeer.peerId = msg.peerId; this._pendingPeer.peerId = msg.peerId;
this._pendingPeer.connected = true; this._pendingPeer.connected = true;
this._pendingPeer = null;
if (this.onpeerconnect) this.onpeerconnect(msg.peerId); if (this.onpeerconnect) this.onpeerconnect(msg.peerId);
if (this.isHost) { if (this.isHost) {
setTimeout(() => this._createPendingPeer(), 300); setTimeout(() => this._createPendingPeer(), 300);

10102
vendor/jsQR.js vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long