(function () { const statusEl = document.getElementById('status'); const topicEl = document.getElementById('topic'); const messageEl = document.getElementById('message'); const btnJoin = document.getElementById('btnJoin'); const btnLeave = document.getElementById('btnLeave'); const btnSend = document.getElementById('btnSend'); const peersEl = document.getElementById('peers'); const publicKeyEl = document.getElementById('publicKey'); const logEl = document.getElementById('log'); const session = BridgeSwarmExamples.sessionStore('chat'); function log(msg, type) { BridgeSwarmExamples.logLine(logEl, msg, type); } function setStatus(msg, isError) { statusEl.textContent = msg; statusEl.className = 'bs-status' + (isError ? ' error' : ''); } let swarm = null; const connections = []; function updatePeers() { peersEl.textContent = 'Peers: ' + connections.length; } function setJoinedUi(joined) { btnJoin.disabled = joined; btnLeave.disabled = !joined; messageEl.disabled = !joined; btnSend.disabled = !joined; } async function joinTopic(topic, opts) { if (swarm) return; opts = opts || {}; setStatus('Joining topic "' + topic + '"...'); swarm = new window.BridgeSwarm(session.swarmOptions('bridge-swarm-chat', topic, opts)); swarm.on('connection', (conn, peerInfo) => { connections.push({ conn, peerInfo }); updatePeers(); log('Peer connected: ' + (peerInfo.publicKey || '').slice(0, 16) + '…', 'peer'); conn.on('data', (data) => { const text = new TextDecoder().decode(data); log('Received: ' + text, 'msg'); }); conn.on('end', () => { const i = connections.findIndex(c => c.conn === conn); if (i !== -1) connections.splice(i, 1); updatePeers(); log('Peer left', 'sys'); }); conn.on('error', (err) => log('Peer error: ' + err.message, 'err')); }); await swarm.join(topic); await session.resumeConnections(swarm); session.markJoined(swarm, topic); const pubKey = await swarm.getPublicKey(); publicKeyEl.textContent = 'Your public key: ' + pubKey; setStatus('Joined "' + topic + '". Send a message or open this page in another tab.'); setJoinedUi(true); log('Joined topic: ' + topic, 'sys'); } BridgeSwarmExamples.waitForBridgeSwarm().then(async function () { var sess = session.load(); if (sess && sess.active && sess.topic) { topicEl.value = sess.topic; setStatus('Restoring session…'); try { await joinTopic(sess.topic, { swarmId: sess.swarmId }); } catch (err) { session.clear(); setStatus(err.message || 'Could not restore session', true); log('Error: ' + (err.message || err), 'err'); } return; } setStatus('Join a topic, then open this page in another tab to chat.'); }).catch(function (err) { setStatus(err.message, true); }); btnJoin.addEventListener('click', async () => { if (typeof window.BridgeSwarm === 'undefined') { setStatus('Extension not ready yet. Wait a moment and try again.', true); return; } const topic = topicEl.value.trim() || 'default-topic'; if (swarm) return; try { await joinTopic(topic); } catch (err) { setStatus('Error: ' + err.message, true); log('Error: ' + err.message, 'err'); } }); btnLeave.addEventListener('click', async () => { if (!swarm) return; try { const topic = topicEl.value.trim() || 'default-topic'; await swarm.leave(topic); await swarm.destroy(); connections.length = 0; updatePeers(); swarm = null; session.clear(); setStatus('Left topic. You can join again.'); setJoinedUi(false); log('Left topic', 'sys'); } catch (err) { log('Error: ' + err.message, 'err'); } }); function sendMessage() { const text = messageEl.value.trim(); if (!text || !swarm || connections.length === 0) return; const data = new TextEncoder().encode(text); connections.forEach(({ conn }) => { try { conn.write(data); } catch (e) {} }); log('Sent: ' + text, 'msg'); messageEl.value = ''; } btnSend.addEventListener('click', sendMessage); messageEl.addEventListener('keydown', (e) => { if (e.key === 'Enter') sendMessage(); }); })();