Eigenen Namen eingeben vor Raum-Erstellen/Beitreten
All checks were successful
Pin to IPFS / pin (push) Successful in 9s

This commit is contained in:
Ole 2026-06-14 16:55:37 +02:00
parent 31a4c2e3a8
commit c29df1ca80
4 changed files with 46 additions and 7 deletions

13
app.js
View file

@ -53,7 +53,8 @@
const isMe = id === mesh.myPeerId; const isMe = id === mesh.myPeerId;
const li = document.createElement('li'); const li = document.createElement('li');
li.className = 'player-chip' + (isMe ? ' self' : ''); li.className = 'player-chip' + (isMe ? ' self' : '');
li.innerHTML = `<span class="dot online"></span>${isMe ? 'Du' : id.slice(0, 8)}`; const displayName = isMe ? 'Du' : mesh.getPeerName(id);
li.innerHTML = `<span class="dot online"></span>${displayName}`;
list.appendChild(li); list.appendChild(li);
}); });
} }
@ -147,7 +148,7 @@
if (r === undefined) return; if (r === undefined) return;
const isMe = id === mesh.myPeerId; const isMe = id === mesh.myPeerId;
const name = isMe ? 'Du' : id.slice(0, 8); const displayName = isMe ? 'Du' : mesh.getPeerName(id);
const item = document.createElement('div'); const item = document.createElement('div');
item.className = 'result-item'; item.className = 'result-item';
@ -159,7 +160,7 @@
<div class="coin-face back">Z</div> <div class="coin-face back">Z</div>
</div> </div>
</div> </div>
<div class="result-label">${name}</div> <div class="result-label">${displayName}</div>
`; `;
container.appendChild(item); container.appendChild(item);
}); });
@ -244,7 +245,10 @@
/* ─── Start screen ─── */ /* ─── Start screen ─── */
$('btn-create').addEventListener('click', () => { $('btn-create').addEventListener('click', () => {
role = 'host'; role = 'host';
const name = $('player-name').value.trim();
mesh = new MeshNet(); mesh = new MeshNet();
mesh.playerName = name;
mesh.names.set(mesh.myPeerId, name || mesh.myPeerId.slice(0, 8));
mesh.onpeerconnect = pid => { mesh.onpeerconnect = pid => {
renderPlayers('host-player-list'); renderPlayers('host-player-list');
@ -305,7 +309,10 @@
/* ─── Join screen ─── */ /* ─── Join screen ─── */
$('btn-join').addEventListener('click', async () => { $('btn-join').addEventListener('click', async () => {
role = 'peer'; role = 'peer';
const name = $('player-name').value.trim();
mesh = new MeshNet(); mesh = new MeshNet();
mesh.playerName = name;
mesh.names.set(mesh.myPeerId, name || mesh.myPeerId.slice(0, 8));
show('join'); show('join');
$('join-answer-section').hidden = true; $('join-answer-section').hidden = true;
$('join-scan-status').textContent = 'QR-Code scannen...'; $('join-scan-status').textContent = 'QR-Code scannen...';

View file

@ -13,6 +13,9 @@
<div class="screen-inner"> <div class="screen-inner">
<h1>randomp2p</h1> <h1>randomp2p</h1>
<p class="subtitle">Vertrauensloser Münzwurf mit Freunden</p> <p class="subtitle">Vertrauensloser Münzwurf mit Freunden</p>
<div class="name-section">
<input type="text" id="player-name" placeholder="Dein Name" maxlength="24" autocomplete="off">
</div>
<div class="btn-group"> <div class="btn-group">
<button id="btn-create" class="btn-primary">Raum erstellen</button> <button id="btn-create" class="btn-primary">Raum erstellen</button>
<button id="btn-join" class="btn-secondary">Raum beitreten</button> <button id="btn-join" class="btn-secondary">Raum beitreten</button>

17
p2p.js
View file

@ -11,6 +11,9 @@ class MeshNet {
this.roster = []; this.roster = [];
this.readyPeers = new Set(); this.readyPeers = new Set();
this._meshReadySent = false; this._meshReadySent = false;
this.playerName = '';
this.names = new Map();
this.names.set(this.myPeerId, '');
this.onpeerconnect = null; this.onpeerconnect = null;
this.onpeerdisconnect = null; this.onpeerdisconnect = null;
@ -46,7 +49,7 @@ class MeshNet {
}); });
peer.on('connect', () => { peer.on('connect', () => {
peer.send(JSON.stringify({ type: 'identity', peerId: this.myPeerId })); peer.send(JSON.stringify({ type: 'identity', peerId: this.myPeerId, name: this.playerName }));
}); });
peer.on('data', data => { peer.on('data', data => {
@ -98,7 +101,7 @@ class MeshNet {
peer.on('connect', () => { peer.on('connect', () => {
this.connections.set(remoteId, peer); this.connections.set(remoteId, peer);
peer.send(JSON.stringify({ type: 'identity', peerId: this.myPeerId })); peer.send(JSON.stringify({ type: 'identity', peerId: this.myPeerId, name: this.playerName }));
if (this.onpeerconnect) this.onpeerconnect(remoteId); if (this.onpeerconnect) this.onpeerconnect(remoteId);
}); });
@ -214,7 +217,7 @@ class MeshNet {
_broadcastRoster() { _broadcastRoster() {
this.roster = this.getPeerIds(); this.roster = this.getPeerIds();
this.readyPeers.clear(); this.readyPeers.clear();
this.broadcast({ type: 'roster', peers: this.roster }); this.broadcast({ type: 'roster', peers: this.roster.map(id => ({ id, name: this.names.get(id) || '' })) });
if (this.onreadyupdate) this.onreadyupdate(0, this.roster.length); if (this.onreadyupdate) this.onreadyupdate(0, this.roster.length);
} }
@ -224,6 +227,7 @@ class MeshNet {
const peerId = this._findPeerId(peer) || 'unknown'; const peerId = this._findPeerId(peer) || 'unknown';
if (msg.type === 'identity') { if (msg.type === 'identity') {
if (msg.name) this.names.set(msg.peerId, msg.name);
const existing = this._findPeerId(peer); const existing = this._findPeerId(peer);
if (existing && existing !== msg.peerId) { if (existing && existing !== msg.peerId) {
this.connections.delete(existing); this.connections.delete(existing);
@ -263,7 +267,8 @@ class MeshNet {
} }
if (msg.type === 'roster') { if (msg.type === 'roster') {
this.roster = msg.peers || []; this.roster = (msg.peers || []).map(p => p.id || p);
if (msg.peers) msg.peers.forEach(p => { if (p.name) this.names.set(p.id, p.name); });
this._meshReadySent = false; this._meshReadySent = false;
this._checkMeshConnections(); this._checkMeshConnections();
return; return;
@ -344,6 +349,10 @@ class MeshNet {
return this.connections.size; return this.connections.size;
} }
getPeerName(peerId) {
return this.names.get(peerId) || peerId.slice(0, 8);
}
getFullSDPData() { getFullSDPData() {
return this._fullSDPData; return this._fullSDPData;
} }

View file

@ -72,6 +72,26 @@ h3 {
margin-bottom: 32px; margin-bottom: 32px;
} }
/* Name input */
.name-section {
margin-bottom: 24px;
}
#player-name {
width: 100%;
padding: 12px 16px;
border-radius: var(--radius);
border: 1px solid var(--border);
background: var(--bg-card);
color: var(--text);
font-size: 1rem;
text-align: center;
outline: none;
transition: border-color 0.2s;
}
#player-name:focus {
border-color: var(--accent);
}
/* Buttons */ /* Buttons */
.btn-group { .btn-group {
display: flex; display: flex;